Generally speaking, there are four primary ways to prevent falling victim to a PHP File Include attack. These are:
1. Add an IPS...of course!
2. Modify your php configuration via php.ini.
3. When writing PHP, make sure to sanitize all variables before passing them into include and fopen functions.
4. Add firewall egress rules for all ports on all externally accessible PHP web servers.
I'll touch on all four of these methods, but lets start by looking at what happens when you add an IPS into the mix. Below is a diagram describing the four stages of a PHP File Include attack which I described in a previous post:
.------------.
.----------. Stage 1: | | 1 .--------.
| | -------->------> | | ---------> | |
| Attacker | | | | Target |
| | Stage 4: | | 4 | |
.----------. <-------<------- | | <--------- .--------.
| Intrusion | | ^
| Prevention | | |
| System | | |
.-------------. | and/or | | |
| | Stage 2: | Firewall | 2 | |
| webhost.com | <------<----- | | <------<-----. |
| | | | ^
.-------------. | | |
| | | |
| Stage 3: | | 3 |
.------->------------> | | ----->------->----.
.------------.
As you can see, by putting an IPS between the internet and the server you want to protect, attack traffic will pass through the IPS on four separate occasions. This gives the IPS four separate opertunaties to block any given attack, and indeed the TippingPoint IPS ships filters that address all four stages of these attacks. As of 2/15/2007 these filters are:
- Stage1: 2205,2362,3601,3885,4404,4212,4321,4324,4356,4375,4392, 4395,4417,4466,4611,4618,4657,4686,4778,4808,4810,5147
- Stage2: 4458 (this filter is very effective if you can't apply egress firewall rules)
- Stage3: 3674,4387,4388,4389,4390,4483,4486,4548,4549,4669,4675, 4676,4677,4678,4679,4680,4681,4682,4735,4736,5081
- Stage4: 4739
So, just to recap, IPSs are in a particularly good position to protect against these types of attacks because the attack traffic must pass through the device four times.
In addition to adding an IPS, there are other changes that can be made to protect yourself:
1. Modify php.ini settings:
Specifically, there are two php.ini settings that need to be looked at.
- register_globals: This directive should turned off if at all possible. It can lead to a great number of vulnerabilities in an application.
- allow_url_include/allow_url_fopen: These directives control weather the fopen and include functions will follow http links to remote files. Applications rarely need to do this, so it is best to disable these. However, setting this directive to off is not a panacea since these directives do not work on all protocol stream handlers. A full list of available protocol handlers (taken from here) is below.
Protocol Handler: Restricted by allow_url_fopen:
zlib: No
compress.zlib: No
compress.bzip2: No
ogg: No
http: Yes
https: Yes
php: No
ftp: Yes
ftps: Yes
data: No
ssh2.shell: Yes
ssh2.exec: Yes
ssh2.tunnel: Yes
ssh2.sftp: Yes
ssh2.scp: Yes
expect: No2. Add egress firewall rules:
Simply put, outbound requests from your DMZ to the internet should be blocked if possible. This is very important for preventing the spread of viruses and sensitive information. This is also one of the best ways to prevent your site from being compromised via a file include attack since the attacker does not have the ability to directly retrieve malicious code from the internet. (although we will see a way around this next week.)
3. Add input validation:
If your PHP application relies on register_globals, then this is not going to be an easy task, however it is still worth adding at least basic checks for malformed data wherever your application passes variables into functions such as include(), mysql_query(), and fopen().
That’s it for this week. Stop by next week for the final part in this series where we will look at a new trick for bypassing some of these protections.
