Does your site also allow you to upload everything?

    One French "security researcher" this summer published unprecedentedly many vulnerabilities he found such as arbitrary file upload in various "written on his knee", but popular CMS and plugins for them. It is amazing how reckless there are creators and administrators of small forums, blogs and online stores. As a rule, in the directory where avatars, resumes, emoticons and other resources are downloaded that the user can upload to the site, PHP code execution is allowed; which means that loading a PHP script under the guise of a picture will allow an attacker to execute arbitrary code on the server.

    Executing code with apache privileges is, of course, not complete control over the server, but do not underestimate the possibilities that an attacker can open: 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, host any illegal content from you, thereby substituting you for abuses; maybe, having found the parameters of binding to the payment system, refund all orders and leave you without income for the entire last month. It's a shame, right?

    How will he succeed?

    You do not check downloads at all?

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

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

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

    Are you checking if the file is a picture?

    Before saving the downloaded file to upload /, you call getimagesize () to make sure that the picture is uploaded. Much to the delight of "security researchers," PHP allows you to embed executable code anywhere in any file, ignoring anything that isn't in the <? ?>. I can take a photo of my beloved cat, add something to my end <?php passthru($_GET['c']); ?>and fill it with the name pwn.php. Then getimagesize () will confirm that there is a JPEG image in the file, because it analyzes only the headers; and my "photo with postscript" will pass the test.

    Are you checking mime-type?

    Why you can’t trust the “mime” field returned by getimagesize () is clear: it is taken based on the file header. Moreover, you can’t trust it $_FILES["file"]["type"]- nothing prevents me from transmitting “Content-Type: image / jpeg” in front of the PHP script in the HTTP request. It seems commonplace, but people really rely on it . So I just saw a check if(substr($_FILES["file"]["type"], 0, 6)=="image/") {/* сохранить файл */}in one self-confident project. They go and consider it elegant and cunning that they were able to cover all possible types of pictures with one check! But do not borrow from them this "best practice."

    Are you checking the extension?

    In another self-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") {/* сохранить файл */}
    A feature of Apache is that when it encounters files with unfamiliar extensions, it “bites off” these extensions and looks for familiar extensions in front of them. Therefore, if I upload the pwn.php.omgif file, it will pass the test, but Apache will see a PHP script in it, because neither the mime-type nor the handler module are registered for the omgif extension.

    Do you check for "bad" extensions?

    In the third self-confident project, I saw a check if(strpos($_FILES["file"]["name"], ".php")===FALSE) {/* сохранить файл */}- they say, if the .php extension is found in the file name at least somewhere, then the file is not suitable. But do not forget that, by default, the PHP interpreter is also called for the .phtml and .php3 extensions, and some hosters include it for other extensions - sometimes even for .html, .js, .jpg and so on, to be inserted into static resources some kind of SEO code, or track hit statistics. (You can check how many google find questions “how can I make PHP code execute in JPEG files?”) In addition, if an attacker manages to download his .htaccess , he will be able to execute PHP code in files with any extensions - even in this .htaccess file itself. In general, be vigilant.

    Are you checking the extension correctly?

    Suppose you are convinced that the file name ends with .jpg (along with a dot!) Can you be sure that the PHP code will not be executed in it? Given the previous paragraph - most likely, but there is no guarantee. It may happen that an attacker (or a crooked admin) somehow damaged /etc/mime.types, so that the .jpg extension turns out to be unregistered, and Apache will analyze the extension before it. It may happen that /etc/mime.types has become unavailable due to chroot . It may happen that an attacker (or a krivoruky admin) has thrown such .htaccess into the upload / directory, which allows you to execute PHP code in all files in a row.

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

    So what to do?

    They tried to compile an exhaustive checklist on stackoverflow . In short: a) explicitly prohibit the execution of PHP in the directory where the user files are stored; b) rename user files to names not controlled by users; c) if possible, re-save images using GD to remove unnecessary metadata and unsolicited posts at the end of the file.

    Also popular now: