php double extension vulnerability - php

I am trying to learn more about file upload in PHP. I faced with a problem.
I read some articles and watch some videos that hacker can attack with double extension however you check the file extension. like
something.php.jpg
How can it be prevented? Thank you in advance!

I have also been interested in this question. I have tested a double extension like something.php.jpg on multiple servers and I am starting to believe that it is not a real security vulnerability unless there is something else set incorrectly on the server. On all the Apache servers I tested it on it did not execute the php code in the file.
Most discussions on php upload vulnerabilities quote from this website: https://www.acunetix.com/websitesecurity/upload-forms-threat/ where the author first quotes from: http://httpd.apache.org/docs/2.4/mod/mod_mime.html#multipleext where it says:
Files can have more than one extension; the order of the extensions is normally irrelevant. For example, if the file welcome.html.fr maps onto content type text/html and language French then the file welcome.fr.html will map onto exactly the same information. If more than one extension is given that maps onto the same type of metadata, then the one to the right will be used, except for languages and content encodings. For example, if .gif maps to the media-type image/gif and .html maps to the media-type text/html, then the file welcome.gif.html will be associated with the media-type text/html.
Then the author of https://www.acunetix.com/websitesecurity/upload-forms-threat/ says:
Therefore, a file named filename.php.123, will be interpreted as a PHP file by Apache HTTP Server, and it will be executed. This of course, will only work if the last extension (in this case .123), is not specified in the list of MIME-types known to the web server...If AddHandler directive is used, all filenames containing the .php extension ( .php, .php.jpg) will be executed as a PHP script.
It seems like this is reverse as to what the Apache docs stated. Please correct me if I am missing something. The Apache docs stated, "welcome.gif.html will be associated with the media-type text/html", therefore I would assume that something.php.jpg would be associated with media-type image/jpeg.
Then the author of the article states that the vulnerability arises if the apache configuation file has this line:
AddHandler php5-script .php
I tried that line as well and the file still did not execute as php. But most AddHandler lines I have seen in the past 10 years are more like this:
AddHandler application/x-httpd-php .html .htm .php
So is the above line not vulnerable to the double extension vulnerability? Or is there particular versions of php or Apache that are vulnerable and certain versions of php or Apache that are not vulnerable?
Of course, I believe that the uploaded file should still have the mime type checked, but I have read that the mime type can be spoofed as well.

User uploads are problematic. There are things you can do to mitigate the risk. For instance, if you intend to allow only image uploads, then you can use the inbuilt mime_content_type() function to ensure that the user is actually uploading a valid image file.
// Let's assume that the name attribute of the file input field you have used is "myfile"
$tempFile = $_FILES['myFile']['tmp_name']; // path of the temp file created by PHP during upload
switch(mime_content_type($tempFile)) {
case "image/jpeg":
// your actions go here...
}
}
else {
echo "This is not a valid image file";
}
Further reading: https://security.stackexchange.com/questions/32852/risks-of-a-php-image-upload-form

Related

When would I want to use .html, vs. .php, as a file extension?

I've noticed that the .html and .php file extensions can be interchanged without apparent effect. Why would I want to use one file extension over the other?
A page ending in .php can include both HTML and/or PHP code (also javascript, css, etc inside their appropriate tags). Note that it is perfectly fine for a page without any PHP code to still have the .php extension.
However, if your page does include PHP code, the filename extension must be .php. Try it - on most web servers this won't work:
FILENAME: test.html
<?php
echo 'Hello there';
The above page will be blank. But if you rename it to test.php, you will see the hello message.
Filename extensions are also an indicator to yourself, or other programmers, as to what type of code the file contains. It is clear at a glance that a file ending in .HTML does not contain any PHP code (especially since any PHP code contained within won't work unless the webserver config is specifically modified to allow it).
One Final Note: these days it is pleasing to have web pages that do not end with an extension at all. Of course, you cannot leave off the extension of a .php or .html page... but you can hide the extension (including the period), making the page look like it was served by Flask or React or etc. You do this via a .htaccess file (yes, exactly like that, dot and all) that sits in the root folder of your website (same folder as the index.php or index.html). See:
https://code-boxx.com/hide-php-extension-url-htaccess/
https://tecadmin.net/remove-file-extension-from-url-using-htaccess/
Here is an interesting tool to help build .htaccess files
Use .html as a default.
If your page is running phpscripts then use .php
So, if you are communicating with server, use .php
.html and .php are file extensions but the more important question is how they are run.
A .php file can run server side script and take in mysql queries and open a connection etc...all of which are server-side functions.
Html is static and only displays static content but that has now changed with HTML 5.I suggest you do a simple search to learn more about php and html and their fundamental differences.
Files are handled depending on config and context. Shebangs, default programs, Apache Handler's, HTTP Headers, etc. describe handling files in various scenarios.
Executing Files In Terminal
The .php extension indicates that it is a PHP script, but the extension isn't necessary.
example-file.php
<?php
echo 'Hello World';
The script can be executed with PHP, which is clear because of the extension:
> php example-file.php
example2-file
#!/usr/bin/env php
<?php
echo 'Hello World';
With a shebang on the first line the OS can try to use the correct interpreter for the user so that the command is simplified to:
> ./example2-file
Some of the implementation details are hidden from the user by removing the file extension.
Packages often retain the extension on the source, but drop the extension during installation.
Default Programs
An extension can indicate to an OS which program to use to open a file.
Files ending in .php on my computer open in an IDE for editing whereas .html files open in a browser.
Servers and Headers
Web servers can send a file with any extension and content-type since many files don't actually exist, but are dynamically generated.
PHP web servers will serve .php files with the text/html content-type because the PHP is interpreted into text. Servers configured to return the raw PHP file as another content-type, i.e. servers not configured for PHP, will cause the web browser to download the source file rather than view the rendered file as HTML.
Since the resulting file after execution is HTML and web servers can dictate the extension, some developers decide to use .html in the URL and have them correlate to .php files to execute and return. Or the URL can not use an extension at all.
Using distinct extensions has the same purpose in PHP as it does in any language -- it makes it easier to determine the type of file you're using.
You may want to ease your web server's burden by having .html files not ran through the PHP processor, or you may want to have your PHP files not labeled .php to help hide what technology you're using server-side.

How can I protect a PHP image upload script from exploits?

I've created (using a script and some help from Stack and some help from friends; I know very little about PHP) a simple page for a local non-profit publication where people can upload photos.
I'm not great with security (from a basis of ignorance, not deliberate negligence) but I've taken the following steps to protect this page:
• the PHP script is set to only accept .jpg, .png and .tif files for upload;
• the subfolder that it saves the form content to has permissions set at 700, and the subfolder it saves uploaded photos to has permissions set at 700;
• according to documentation, my host has the following configuration to ensure that only .php files run as .php:
<FilesMatch \.php$>
SetHandler php52-fcgi
</FilesMatch>
• I’ve put an .htaccess file in the relevant (main and saved content) folders:
RemoveHandler .php
RemoveHandler .inc
RemoveHandler .pl
RemoveHandler .cgi
RemoveHandler .py
RemoveHandler .fcgi
Overnight, however, somebody found this test page and submitted what seems to be a perfectly benign test message and small .jpg. This is a private test page with a non-intuitive URL that only I and about three other people know about; none of the others sent this test.
This obviously has me worried that there's something hinky going on, and I'm worried that I don't know enough about security to make sure this page is safe.
Is there something obvious that I'm missing?
When dealing with uploaded you should keep in mind that all the data you can find in the $_FILES array can be faked. It's traveling through HTTP so it's pretty easy to give the image/jpg mime to an executable file for exemple.
1- Check the true mime
PHP come with some function to check the real mime of a file. For that you should use fileinfo
$finfo = new finfo(FILEINFO_MIME, "/usr/share/misc/magic");
$filename = "/var/tmp/afile.jpg";
echo $finfo->file($filename);
2- Check the image's properties
You apparently want to upload only image , so the received file must have a width and a height :
Use getImageSize() to get all the required information about the image. If it return false , the file is probably not an image and you can delete it.
getImageSize can also give you a mime type , but i don't know if it can be trusted.
2.5- Reprocess image
As suggested by user628405 , reprocessing the image with GD is probably the more secure thing to do.
$img = imagecreatefrompng('vulnerable.png');
imagepng($img, 'safe.png');
Obviously it has to be adapted according to the image type. See all the imagecreatefrom* in php documentation.
3- Upload folder
In addition of what you have already done :
Make sure your upload folder is not available from the web. Validate the uploaded file then move it to an other folder if needed and rename the file.
It will prevent hacker from executing a malicious file (can't execute it if it can't be reached by an url).
Further reading : https://www.owasp.org/index.php/Unrestricted_File_Upload
Don't rely on any data from the client, including content type!
Don't save uploaded files in the web root. Uploaded files should be only accessible via your scripts, for better control.
Don't save uploaded files with their original file names and extensions! Store this data in a database for retrieval later.
You can check the MIME type of the file, but don't worry as long as your php handler can only execute .php files and you're taking care of not saving uploaded .php files in your script, you're not exposing any security leak.
This is valid for .php files as well as any other server-side scripting language installed on your server of course.
A better idea is to keep a white of the extensions you're accepting to save on your filesystem.
I would ignore the MIME type and the file extension of the incoming file. These can be faked.
Store those files in a directory if you are going down that avenue.
Ensure that that directory is just for images (music) and then get a script to place the correct extension on them by looking at the files format.
Also ensure that that directory cannot execute PHP (or anything else).
This will keep you safe.

Uploading and displaying .html files in browser

I'm working on a little project with a few friends, and have set up a pretty simple PHP upload script that only certain users can access. I am not worried about any type of attacks against the server, since this is for fun, but I do have a question.
I've made a subdomain (static.foo.bar) where the uploaded files are moved to. This subdomain had mod_php turned off, to prevent malicious upload and execution of php scripts. The script also checks for file extensions and mime content types, but I assume those can easily be bypassed/spoofed.
However, a user could easily upload an .html file and have it redirect somewhere else. Likewise, they could upload an image file instead and have it display an image in the browser, instead of being asked to download the image.
I assume this is the behavior of the browser, but I've also noticed that when uploading a file to sendspace (or any other service), even if the file is .html (and valid html) it will ask the user to download it instead of displaying it on the website.
I am running Apache on CentOS.
How do I accomplish this?
ForceType is probably what you're looking for.
# In your .htaccess file
<Location /uploads_directory>
ForceType application/octet-stream
</Location>
You want to set all files' mime type to application/octet-stream so the browser will download them instead of trying to show the content.

How is a website hacked by a "maliciously encoded image that contained a PHP script hidden inside it"?

My ad server has been hacked over the weekend.
It seems to be a widespread problem, according to this article.
There is something in there that got me thinking...
Attackers used one attack to get login
rights to his server, and then
uploaded a maliciously encoded image
that contained a PHP script hidden
inside it, he said. By viewing the
image, attackers forced the script to
execute on the server
How is this possible? Does it rely on the image being opened with GD or similar? Do they upload a script posing as an image, and somehow include it?
It can be as simple as uploading a file like
GIF89a<?php
echo 'hi';
If your upload script tests the content type via fileinfo or mime_content_type() it is recognized as "GIF image data, version 89a" since GIF89a is the only pattern/magic number that is required to identify a file as gif.
And the OpenX upload script apparently kept the proposed filename, i.e. it was possible to save this "image" as foo.php on the server. Now, if you requested that file via http://hostname/uploaddir/foo.php the script was executed as a php script because webservers usually/often determine the content type only by the filename extension, e.g. via
<FilesMatch "\.php$">
SetHandler application/x-httpd-php
</FilesMatch>
php then echoes the leading GIF89a and executes the <?php ...code... block.
Putting the <?php block into a gif comment is slightly more sophisticated but basically the same thing.
Your server is parsing that file for w/e reason. The attackers are putting the PHP into the image comment.
How are you validating the file is an image? If you do it solely on mime type, then I believe they can fake the image header and include whatever they want after that. VolkerK has a practical example
In the perfect world, I wouldn't serve any public facing images via PHP for fear of such an issue.
Serve the image directly using the server; A good suggestion is to save those images to a directory where they can be served without PHP.
I think that's the gist of it, someone correct me if I'm wrong.
The only possibility I see for a server compromise is the image being included instead of read through e.g. readfile and other stream functions.

Using the filename for GET data and making the PHP page output as a JPG extension?

Alright, currently I'm using GD to create a PNG image that logs a few different things, depending on the GET data, for example: http://example.com/file.php?do=this will log one thing while http://example.com/file.php?do=that will log another thing.
However, I'd like to do it without GET data, so instead http://example.com/dothis.php will log one thing, and http://example.com/dothat.php will log the other.
But on top of that, I'd also like to make it accessible via the JPG file extension. I've seen this done but I can't figure out how. So that way http://example.com/dothis.JPG will log one thing, while http://example.com/dothat.JPG logs the other.
The logging part is simple, of course. I simple need to know how to use filenames in place of the GET data and how to set the php file to be accessible via a jpg file extension.
filename is accessible via $_SERVER array (I hope you can explore this array and find suitable variable)
while extension trick is web-server responsibility
For the Apache module API it could be
RemoveHandler .jpg
AddType application/x-httpd-php .jpg
If you don't want to have duplicate scripts / links, and the webserver is apache, then its mod_rewrite you need, e.g.
RewriteEngine On
RewriteRule ^doth/(.*) index.php?page=$1 [L]
C.
If you want to embed PHP inside a file using the extension .jpg, you will need to instruct your web server to parse .jpg files as PHP. One way to do this, if you are using Apache, is to add the following to an .htaccess file in the directory where the files are located:
addtype application/x-httpd-php .jpg .php
Or you can add it to your server configuration. See this page for details on htaccess for Apache.
Next, write your scripts such that they log the appropriate data. In your example, it looks like you won't need GET data anymore, and the script will log different data based simply on the fact it was called. i.e. dothis.jpg "knows" to log this data, whereas dothat.jpg logs that data.
dothis.jpg:
<?php
header("Content-type: image/jpeg");
// log "this" code
$img = imagecreate($x, $y); // example
// GD image generation code
imagejpg($img);
?>
dothat.jpg:
<?php
header("Content-type: image/jpeg");
// log "that" code
$img = imagecreate($x, $y); // example
// GD image generation code
imagejpg($img);
?>

Categories