In the PHP implementation of the system to external command-and-vulnerability warning-the black bar safety net

ID MYHACK58:62200717023
Type myhack58
Reporter 佚名
Modified 2007-09-24T00:00:00


PHP as a server side scripting language, like writing a simple, or a complex dynamic web page such a task, it is fully able to do the job. But the thing is not always the case, sometimes in order to achieve a certain function, it must be by means of theoperating systemof the external program, or call commands, so you can do more with less.

So, can the PHP script call an external command? If can, how to do? What are the concerns? Believe you have seen this article, can certainly answer these questions.


The answer is Yes. PHP and other programming language like, totally can within the program to call an external command, and is very simple: as long as one or a few functions can be.


Since PHP is basically used for WEB application development, IT security became the people to consider one important aspect. So PHP designers to PHP added a door: security mode. If you are running in Safe mode, then the PHP script will be subject to the following four dimensions of restrictions:

The implementation of the external command

When you open the file with some restrictions

Connect to a MySQL database

HTTP-based authentication

In Safe mode, only in the specific directory of the external program can be executed, the other programs of the call will be rejected. This directory can be in php. ini file with the safe_mode_exec_dir Directive, or compile PHP to add--with-exec-dir option to specify, the default is/usr/local/php/bin.

If you call a should be the output result of the external command means is PHP a script there is no error, the resulting is a blank, then probably your network has put the PHP running in Safe Mode.

How to do?

In PHP to call an external command, you can use the following three methods to achieve:

  1. PHP provides a special function

PHP provides a total of 3 dedicated to the implementation of the external command function: system (), exec () and passthru () as well.


Prototype: string system (string command [, int return_var])

system()function is the other language of the same, it executes the given command, the output and returns the result. The second parameter is optional, used to get the command executed after the status code.




?& gt;


Prototype: string exec (string command [, string array [, int return_var]])

the exec()function with system()is similar, but also execute the given command, but does not output the results, but returns the result of the last line. Although it only returns the command results of the last row, but with the second parameter array can get the full results, the method is to put the results line by line to append to the array at the end. So if the array is not empty before the call is best to use unset()the most it cleared off. Only specify the second parameter only when you can use the third parameter, is used to obtain the command execution status code.




exec("/bin/ls-l", $res);

$res is a data, each element represents a result row

exec("/bin/ls-l", $res, $rc);

$rc is the value of the command/bin/ls-l status code. The success of the case usually is 0

?& gt;

the passthru()

Prototype: void passthru (string command [, int return_var])

passthru()just calls the command does not return any results, but the command of the operation result is directly output to the standard output device. So passthru()function is often used to call as pbmplus Unix under an image processing Tool, the output of the binary of the original picture of the flow of the program. Likewise it can also get the command execution status code.



header("Content-type: image/gif");

passthru("./ ppmtogif hunte. ppm");

?& gt;

2 Use the popen()function opens the process

The above method can be simply executed the command, but not with the command interaction. But at some point have to command some kind of input, such as an increase in Linux users of the system, to invoke su to the current user change to root, and the su command must be on the command line enter the root password. In this case, with the above-mentioned method is clearly not do.

popen()function opens a process pipe to perform a given command, returns a file handle. Since the return is a file handle, then it is possible for it to read and write. In PHP3, this handle can only do a single mode of operation, either write or read; from PHP4 start, you can both read and write. Unless this handle is a mode to read or write to open, otherwise you must call pclose()function to close it.

Example 1:


$fp=popen("/bin/ls-l", "r");

?& gt;

Example 2 This example from the PHP Chinese Alliance website http://www. phpx. com/the show. php? d=col&i=5 1):


/* PHP how to add a system user

The following is a section of a routine, increase a name for james of the user,

the root password is * user-friendly design。 FYI


$sucommand = "su --login root --command";

$useradd = "useradd ";

$rootpasswd = "* user-friendly design";

$user = "james";

$user_add = sprintf("%s "%s %s"",$sucommand,$useradd,$user);

$fp = @popen($user_add,"w");



?& gt;

3 with a reverse apostrophe, The`, that is, on the keyboard the ESC key the following, and~in the same above)

This method was not previously included PHP document, as a savegame exists. The method is very simple, with two reverse apostrophes put the command to be executed enclosed as an expression, this expression's value is the command execution results. Such as:



echo '<b><pre>'.$ res.'& lt;/pre></b>';

?& gt;

This script the output is like:


hunte. ppm




You want to consider?

To consider two issues: security and timeouts.

Look at the security. For example, you have a small online store, so you can sell the products list is placed in a file. You Write a form of HTML files, allow your users to enter their EMAIL address, and then put the list of products sent to them. Assuming you're not using PHP's mail()function or have never heard of, you call the Linux/Unix system mail program to send this file. The program like this:


system("mail $to < products.txt");

echo "our product catalog has been sent to your email:$to";

?& gt;

With this code, The General user does not produce anything dangerous, but in fact there is a very big security vulnerability. If there is a malicious user input a EMAIL address:

'--bla mail < /etc/passwd'

Then this command eventually becomes:

'mail --bla mail < /etc/passwd < products.txt'

I believe that, regardless of which network management personnel to meet such an order, will be scared out in a cold sweat.

Fortunately, PHP provides us with two functions: EscapeShellCmd()and EscapeShellArg () as well. Function EscapeShellCmd Put a string in all the possible hidden from the Shell and to execute another command characters escaped. These characters in the Shell is to have a special meaning, like the semicolon that redirection> and read from the file into(<, etc. Function EscapeShellArg is used to handle command parameters. It is in the given string on both sides plus a single quotes, and strings in single quotes escaped, so the string can be safely used as command parameters.

Then look at the timeout problem. If you want to perform the command takes a long time, then you should put this command into the background of the system to run. But in the default case, like the system()function to wait until this command finished running before returning in effect to the output of the command results, this will certainly lead to PHP script timeout. The solution is to put the command redirect output to another file or stream, such as:

<? system("/usr/local/bin/order_proc > /tmp/null &"); ?& gt;