[Library File]
As we discussed earlier, include() and require() are mainly to support code bases, because we generally put some frequently used functions into an independent file. This independent file is the code base. When we need to use the functions in it, we just need to include the code base in the current file.
Initially, when people developed and released PHP programs, in order to distinguish the code base from the main program code, they usually 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 kind of file on the server, we will get the source code of the file. This is because when using PHP as an Apache module, the PHP interpreter decides whether to resolve to PHP code based on the file extension. The extensions are specified by the site administrator, generally ".php", ".php3" and ".php4". If important configuration data is included in PHP files without a suitable extension, remote attackers can easily get this information.
The easiest solution is to assign a PHP file extension to each file, which can prevent the problem of leaking the source code, but create new problems. By requesting this file, the attacker may make the code that should have been run in the context run independently, which may lead to all the attacks discussed earlier.
Here is a very obvious example:
In :
<?php
$libDir = "/libdir";
$langDir = "$libdir/languages";
...
include("$libdir/":
?>
In libdir/:
<?php
...
include("$langDir/$userLang");
?>
It is quite safe when "libdir/" is called by "", but because "libdir/loadlanguage" has the extension of ".php", remote attackers can directly request this file and can arbitrarily specify the values of "$langDir" and "$userLang".
[Session File]
PHP 4 or later provides support for sessions, and its main function is to save the status information between pages in PHP programs. For example, when a user logs into a website, he logs into this fact and who logs into this website are saved in the session. When he browses everywhere in the website, all PHP codes can obtain these status information.
In fact, when a session is started (actually set to automatically start on the first request in the configuration file), a random "session id" will be generated. If the remote browser always submits this "session id" when sending the request, the session will remain. This is easy to do with cookies, or by submitting a form variable (including "session id") on each page. PHP programs can register a special variable with session. Its value will be stored in the session file after each PHP script is finished and will also be loaded into the variable before each PHP script starts. Here 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
?>
New versions of PHP will automatically set the value of "$session_auth" to "shaun". If they are modified, future scripts will automatically accept the modified value. This is indeed a very good tool for stateless web, but we should also be careful.
An obvious problem is to make sure that the variables do come from the session, for example, given the above code, if the subsequent script is as follows:
<?php
if (!empty($session_auth))
// Grant access to site here
?>
The above code assumes that if "$session_auth" is set, it is set from session, not from user input. If the attacker sets it through form input, he can gain access to the site. Note that the attacker must use this attack method before the session registers the variable, and once the variable is put into the session, any form input will be overwritten.
Session data is generally stored in a file (the location is configurable, generally "/tmp"), and the file name is generally similar to "sess_<session id>". This file contains variable name, variable type, variable value and some other data. In multi-host systems, because the file is saved as a user (usually nobody) running the web server, malicious site owners can create a session file to gain access to other sites, and can even check sensitive information in the session file.
The Session mechanism also provides another convenient place for attackers to save their input in the remote system file. For the above example, the attacker needs to place a file containing PHP code in the remote system. If it cannot be done using file upload, he usually uses session to assign a value to a variable according to his own wishes, and then guess the location of the session file. He knows that the file name is "php<session id>", so he only needs to guess the directory, and the directory is generally "/tmp".
In addition, an attacker can arbitrarily 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 relatively loose data types, and the types of variables depend on the context in which they are located. For example: "$hello" starts with a string variable with a value of "", but when evaluated, it becomes the shaping variable "0", which may sometimes lead to some unexpected results. If the value of "$hello" is different or "0", the result returned by empty() will not be true.
Arrays in PHP are associative arrays, that is, the index of the array is string type. This means that "$hello["000"]" and "$hello[0]" are also different.
When developing programs, we should carefully consider the above issues. For example, we should not test whether a variable is "0" in one place, but use empty() to verify in another place.
[Error-prone function]
When we analyze vulnerabilities in PHP programs, if we can get the source code, then a list of error-prone functions is something we need very much. If we can remotely change the parameters of these functions, we are likely to find vulnerabilities. Here is a more detailed list of error-prone functions:
<PHP Code Execution>
require(): read the content of the specified file and interpret it as PHP code.
include(): Same as above
eval(): Execute the given string as PHP code.
preg_replace(): When used with the "/e" switch, the replacement string will be interpreted as PHP code.
<Command Execution>
exec(): Execute the specified command and return the last line of the execution result.
passthru(): Execute the specified command and return all results to the client browser.
``: Execute the specified command and return all results to an array
system(): same as passthru(), but does not process binary data.
popen(): Execute the specified command and connect the input or output to the PHP file descriptor
<File Leakage>
fopen(): Open the file and correspond to a PHP file descriptor
readfile(): Read the content of the file and then output it to the client browser.
file(): Read the entire file content into an array
Translator's note: Actually, this list is not very complete. For example, commands such as "mail()" may also execute commands, so you need to add them yourself.
[How to enhance PHP security]
All the attacks I introduced above can be implemented well for the default installation of PHP 4, but I have repeated it many times. The configuration of PHP is very flexible. By configuring some PHP options, we are completely likely 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 just a personal opinion, but I can guarantee that if you use all the options provided by PHP, your PHP will be very safe, even for third-party code, as many of these features are no longer available.
**** Set "register_globals" to "off"
This option will prohibit PHP from creating global variables for user input, that is, if the user submits the form variable "hello", PHP will not create "$hello", but will only create "HTTP_GET/POST_VARS['hello']". This is an extremely important option in PHP. Turning off this option will cause great inconvenience to programming.
*** Set "safe_mode" to "on"
Turning on this option will add the following restrictions:
1. Restrict which command can be executed
2. Restrict which function can be used
3. File access restrictions based on script ownership and target file ownership
4. Prohibit file upload function
This is a great option for ISPs, and it can also greatly improve PHP security.
** Set "open_basedir"
This option can prohibit file operations outside the specified directory, effectively eliminating the attacks of local or remote files being included(), but you still need to pay attention to file upload and session files attacks.
** Set "display_errors" to "off", and set "log_errors" to "on"
This option prohibits the display of error messages on web pages, but records them in log files, which can effectively resist attackers' detection of functions in target scripts.
* Set "allow_url_fopen" to "off"
This option can disable remote file function, highly recommended!