📜 ⬆️ ⬇️

Does your site also allow you to upload everything?

One French “security researcher” this summer published unprecedentedly many vulnerabilities found by him such as arbitrary file upload in various “written on the knees”, but popular CMS and plugins for them. It's amazing how careless are the creators and administrators of small forums, blogs and online stores. As a rule, in the directory where avatars are loaded, resumes, emoticons and other resources that the user can upload to the site - PHP code execution is allowed; therefore, downloading a PHP script in the guise of a picture will allow an attacker to execute arbitrary code on the server.

Execution of code with apache rights is, of course, not full control over the server, but do not underestimate the possibilities opened up for an attacker: he gets full access to all the scripts and configuration files of the site and, through them, to the databases used; he can send spam on your behalf, harass any illegal content from you, thereby substituting abuses; may, having found the parameters of binding to the payment system, otrefandit all orders and leave you without income for the entire last month. It's a shame, right?

How can he do it?
')

You do not check the downloadable files at all?


Clinical case: you copied a line from the PHP manual
move_uploaded_file($_FILES["file"]["tmp_name"], "upload/" . $_FILES["file"]["name"]);
and so it was left in the production code.

So I can upload any files at all, and not only in the upload directory, but anywhere I can specify as the file name ../index.html and replace your main page with my own. It's a shame, right?

Add at least a basename () call for $_FILES["file"]["name"] . In the latest version of PHP, judging by my experiments, $_FILES["file"]["name"] and so returns only the basename of the filename given in the HTTP request; but caution here will not be superfluous.

Are you checking if the file is a picture?


Before saving the uploaded file to upload /, you call getimagesize () to make sure that the image is uploaded. Much to the delight of "security researchers", PHP allows you to insert executable code anywhere in any file, ignoring everything that is not enclosed in <? ?>. I can take a photo of my favorite cat, add something like <?php passthru($_GET['c']); ?> to its end <?php passthru($_GET['c']); ?> <?php passthru($_GET['c']); ?> and fill in as pwn.php. Then getimagesize () will confirm that the JPEG file is in the file, because it analyzes only the headers; and my "photo with postscript" will be checked.

Are you checking mime-type?


Why you can't trust the “mime” field returned by getimagesize () is understandable: it is taken based on the file header. Moreover, you cannot trust $_FILES["file"]["type"] - nothing prevents me from transmitting in the HTTP Content-Type: image / jpeg request before the PHP script. It seems commonplace, but people really rely on it . So I just saw the if(substr($_FILES["file"]["type"], 0, 6)=="image/") {/* */} check if(substr($_FILES["file"]["type"], 0, 6)=="image/") {/* */} in one self-confident project. They, it seems, consider it elegant and ingenious that they could cover all possible types of pictures with one test! But do not borrow from them this "best practice".

Do you check the extension?


In another confident project, I just saw a check.
if(substr($_FILES["file"]["name"], -3)=="jpg" || substr($_FILES["file"]["name"], -3)=="gif" || substr($_FILES["file"]["name"], -3)=="png") {/* */}
The Apache feature is that when it encounters files with unfamiliar extensions, it “bites off” these extensions and searches for familiar extensions in front of them. Therefore, if I fill in the pwn.php.omgif file, it will be checked, but Apache will see a PHP script in it, because neither mime-type nor a handler module is registered for the omgif extension.

Are you checking for bad extensions?


In the third self-confident project, I saw a check if(strpos($_FILES["file"]["name"], ".php")===FALSE) {/* */} - they say that if somewhere met the extension. php, then the file is no good. But do not forget that by default the PHP interpreter is also called for extensions .phtml and .php3, and some hosters include it for other extensions - sometimes even for .html, .js, .jpg, and so on, to embed in static resources any SEO code, or track hit statistics. (Can you check for yourself how many Google finds the questions “how do I get the PHP code to run in JPEG files?”) Also, if an attacker manages to upload his .htaccess file, he can execute the PHP code in files with any extensions - even in this .htaccess file itself. In general, beware.

Are you testing the extension correctly?


Suppose you make sure that the file name ends in .jpg (along with a dot!) Can you be sure that the PHP code will not run in it? Considering the previous point - most likely it is possible, but there is no guarantee. It may happen that the attacker (or Krivoruk administrator) somehow damaged /etc/mime.types, so that the .jpg extension will be unregistered, and Apache will analyze the extension in front of it. It may happen that /etc/mime.types became unavailable due to chroot . It may happen that an attacker (or Krivoruk administrator) has thrown into the upload / directory. Htaccess, which allows you to run PHP-code in all files in a row.

In addition, until recent versions of PHP, it was possible to download a file called “pwn.php \ 0.jpg”, which, if saved to disk, would turn into “pwn.php”, because for system calls the string with the file name ends with \ 0 , and for PHP functions, this is the usual valid character in a string. In this case, checking the extension would also not guarantee anything.

And what to do?


An exhaustive checklist was attempted on stackoverflow . In short: a) explicitly prohibit the execution of PHP in the directory where user files are saved; b) rename user files to user names that are not controlled by users; c) if possible, resave images with GD to remove unnecessary metadata and unsolicited postscripts at the end of the file.

Source: https://habr.com/ru/post/148999/


All Articles