Skip to main content

Uploading a Shell Bypassing the Security Checks


Hi,
In this Article i will try to Explain how can you bypass the security provided to upload functionality to upload a webshell.

Now Consider this scenarios, suppose u have got access to the Admin panel or  to any other page which provides u the functionality to upload a document or a image.

The Examples in the articles are in PHP but it can be used for upload function checks in any language.

Letss Start!



Now as u all know the upload Functionality is basically define in HTML as shown Below
<form name=upload action=upload.php method=post>
   upload a file : <input type=file name=fileName >
   <input type=submit name=upload>
</form>

Now the above code will give an button to select the file from ur system and the the submit button will ask the upload.php(containing the code) to process the file .

a) Normal Implementation

In this Implementation the upload.php does not check the file and directly performs the upload as shown in below code

    <?php
   $uploaddir = 'uploads/'; // Relative path under webroot
        $uploadfile = $uploaddir . basename($_FILES['userfile']['name']);
   if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile))
       {
          echo "File is valid, and was successfully uploaded.\n";
   }
   else
   {
          echo "File uploading failed.\n";
   }
     ?>

Now In the above code we see that the code directly upload the file to the directory .
Hence we can directly upload a Webshell and excecutes its as

   http://<someSite>/uploads/webshell.php
  or
  curl http://<someSite>/uploads/webshell.php

b) Content Type Verification

In this type of Implementation the code in upload.php checks for the type of the file that is being uploaded if it contents plain text or PHP it will not upload it

Consider the below code
       <?php
      //checks if file is Gif or not
       if($_FILES['userfile']['type'] != "image/gif") 
       {
          echo "Sorry, we only allow uploading GIF images";
          exit;
       }
      $uploaddir = 'uploads/';
      $uploadfile = $uploaddir . basename($_FILES['userfile']['name']);
      if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile))
   {
          echo "File is valid, and was successfully uploaded.\n";
   }
   else
    {
          echo "File uploading failed.\n";
    }
   ?>

The above code will check if the content/MIME Type of the file is Gif or not

Now if the files having content/Header other than the GIf is uploaded then the HTTP Request is as shown

"
   POST /upload2.php HTTP/1.1
   TE: deflate,gzip;q=0.3
   Connection: TE, close
   Host: localhost
   User-Agent: libwww-perl/5.803
   Content-Type: multipart/form-data; boundary=xYzZY
   Content-Length: 156
   --xYzZY
   Content-Disposition: form-data; name="userfile"; filename="shell.php"
   Content-Type: text/plain

"

The code will check the highlighted portion and see that its not Gif image and will not upload it

Now We can Bypass this protection by implicitly setting the content type either by Program like perl or by the Form Data tamper plugin in firefox
Eg
     "Content-Type" =>"image/gif"
This will make the upload.php script happily accept the file and u can access it as
   
   http://<someSite>/uploads/webshell.php
  or
  curl http://<someSite>/uploads/webshell.php


C) Image File Content Verification

In this Type of Verification the developer might decide to verify the content of the uploaded file to check if it has a script or not

Consider the below example
<?php
 $imageinfo = getimagesize($_FILES['userfile']['tmp_name']); //check image size
if($imageinfo['mime'] != 'image/gif' && $imageinfo['mime'] != 'image/jpeg')
{
    echo "Sorry, we only accept GIF and JPEG images\n";
    exit;
}
$uploaddir = 'uploads/';
$uploadfile = $uploaddir . basename($_FILES['userfile']['name']);
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
    echo "File is valid, and was successfully uploaded.\n";
} else {
    echo "File uploading failed.\n";
}
?>

In above Example the php functions getImageSize returns the size and type  of the image checks if the file is valid image file .

Now to Bypass this type of verification we can use a program like GIMP to embedded a php script inside the Image File Binary data .

When the getimagesize()  looks at the file it sees a valid image file but when a php interpreter sees at the file it sees it as a php code and executes the php code in it along with binary data

Hence even if we change the extension of the shell to php and if File name verification is not there then the file would be uploaded as a valid GI or JPEG image

hence
 
   http://<someSite>/uploads.webshell.gif
Will show a proper image file (even if the code is embedded in it)
and
      http://<someSite>/uploads/webshell.php
Will show the shell (it is uploaded as a php file only )


D) File Name Verification

SomeTimes the Developer decides to check the extensions of the uploaded file to decide if the file is Image or not as shown in the following code
<?php
   $blacklist = array(".php", ".phtml", ".php3", ".php4");
   foreach ($blacklist as $item)
    {
         if(preg_match("/$item\$/i", $_FILES['userfile']['name']))
       {
              echo "We do not allow uploading PHP files\n";
              exit;
          }
    }
   $uploaddir = 'uploads/';
   $uploadfile = $uploaddir . basename($_FILES['userfile']['name']);
   if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
           echo "File is valid, and was successfully uploaded.\n";
   }
   else
   {
           echo "File uploading failed.\n";
   }
?>

In the Above Code
The variable $blacklist contains the extensions to be checked for uploaded file

The function pregmatch Checks the name of the uploaded file to see if it contains any of the blacklisted extensions if the blocked extension is not ther in the uploaded file name then the file is uploaded else a error msg is displayed .

Now the Above code can also be bypass by uploading the .Gif or .jpeg file with a php Code embedded in it as shown in step C if the webserver is not configure correctly (which is the case in most of the cases ) then the GIf file is also passed to the PHP Interpreter which Executes the PHP code within it .

Another way of bypassing this Method is of Using Null Byte Parameter

Change the File Name to Shell.php.gif

Now if above file is uploaded the uploded function will check the extention of the file as .gif and allow it to be process .

But while uploding as the file contains a nullByte Character () it will ignore everything which is after and save the file as shell.php

u can access the file as
   http://<someSite>/uploads/Shell.php

The above hack is possible because in  native code, the length of a string is determined by the position of the first null byte from the start of the string - the null byte effectively terminates the string.

Hope This Article was self sufficient.

Please add if i have left anything extra (New Knowledge is always welcome)

Comments are as always appreciated and welcome.

References: ScanIT, Internet.

Share this with your friends
Loading...