写在前面:
本人是刚开始探索安全技术的小白一枚,所以各位大佬看到我的文章有错误一定要告诉我啊啊啊(不要喷我,捂脸逃走),大家一起进步,向成为一名大佬前进!~
我是用phpstudy(5.2版本)进行的阿帕奇和数据库的搭建,系统window7,这里有一个开始解决的问题是进行sqli-lab第一题注入时,系统一直将我的 ’ 转义成 /’ 。这里要修改phpstudy中的一个参数,关闭magic_quotes_gpc(魔术引号开关,会进行自动转义设置)
开始第一关因为转义字符的原因一直都进行不下去,所以就把第一种方法写在了第二关下,后来成功解决转义字符的问题,然后就用另一种方法来爆破第一关吧~
这里我们还是回到最基础的一个问题,如何判断这是一个什么注入,对比字符注入和数字型的注入:
字符型注入:
数字型注入:
可以看到字符型注入错误显示到单引号截止,而数字型注入会把所有的错误显示出来。
为什么用 ’ 就可以进行判断:
一开始SQL语句是这样的:
SELECT * FROM XXX WHERE id=‘1’
当加了单引号后变为:
SELECT * FROM XXX WHERE id=‘1’‘
这不符合语法规则,并进行报错,说明原来程序没有这种注入的防范措施,所以你要做的就是利用这个错误把他变成正确的并输入自己想进行的语句。
有用and语句进行判断:
XXX/?id=1’ and 1=1 --+ 可以
XXX/?id=1’ and 1=2 --+ 不可以
关于最后–+的作用,我是看这位大佬的博客理解的:https://zhuanlan.zhihu.com/p/23899464 (关于字符注入判断的总结))见最后,还有一篇文章讲的非常清楚
所以判断为字符型注入
之后进行爆破:得到数据库的名字:
XXX/?id=1' and extractvalue(1,concat(0x7e,(select database()))) --+
XXX?id=1' and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()))) --+
获得字段名:
XXX?id=1' and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users'))) --+
XXX/?id=1' and extractvalue(1,concat(0x7e,(select group_concat(username,0x7e,password) from users))) --+
XXX/?id=1' and extractvalue(1,concat(0x7e,(select group_concat(username,0x7e,password) from users where username not in (~Dumb~,~Angelina~)))) --+
对于一个小白选手,首先要区分的就是整型与字符型注入的区别,这里借鉴一些大佬的笔记:
数字型注入意味着,当输入的参数是整型时,如:ID,年龄,页码等。例如URL为:http://www.xxx.com/test.php?id=5 可以猜测SQL语句为:select * from xxtable where id=5
数字型注入多见于ASP和PHP的应用程序中,因为ASP和PHP输入弱类型语言,例如:参数id=5,PHP会自动来推导变量id的数据类型为int类型,那么id=5 and 1=1 则会推导为String类型,这是弱类型语言的特征,而Java,c#这类强类型语言,如果试图把一个字符串转化为int类型,处理不当就会抛出异常,无法继续执行。这方面强类型语言比弱类型语言有先天优势,所以作为一个合格程序员,在数据类型处理方面一定要严格设置。
所以此处判断为数字型注入是因为输入单引号,根据报错信息确定咱们输入的内容被原封不动的带入到数据库中
一些判断方法:
SQL 注入挖掘
and 1=1 和 and 1=2 回显页面不同(整形判断)
单引号判断 ‘ 显示数据库错误信息或者页面回显不同(整形,字符串类型判断)
\ (转义符)
-1/+1 回显下一个或上一个页面(整型判断)(需要用%2b 转码+号)
and sleep(5) (判断页面返回时间)
咱接着往下走
这里看到了一些大佬写的关于union语句进行爆破的一些原理:
- 到这里SQL注入的基本原理就清楚了,其实id=后面不论写什么(数字,字符串,语句),传递到后端后都会为其加上一对单引号变成’xxxxxxxxxxxxxx’,在这里输入的一对东西都被系统当做是参数,这里在1后加单引号的目的实际上就是把服务器为参数加的一对单引号打断,这个结果叫做闭合,即union前的语句可以顺利执行(没有语法错误),那么后半句无论我们要查询什么,系统都会执行。这里的例子是参数被单引号封装的情况,其它情况同样类似,通过返回的错误信息进行分析,相关的教程网上很齐全,不再赘述。
- 通过上面的分析我们知道,通过闭合以及Union查询,系统不但执行了原本的传参语句,还执行了我们自己编写的select语句,这种技巧实际上就是一种语句的拼接,如果服务器没有对参数进行相关的过滤,就会造成SQL漏洞,使得注入发生。这时union前后的两个select语句都被执行,会通过前端返回的窗口来进行显示,而后半句才是我关心的信息,如何能让后半句被执行而前半句不被执行呢?这里需要注意,只能通过修改前半句的参数,如把参数1变成1’,或1xxx,或任意数据库中肯定不存在的参数,那么前半句就会返回空值,只显示后半句的查询结果。
首先使用union爆破库名,得到库名为security的数据库
可以判断一下这个表有几列是有效列:发现到4的时候就出现了错误,前面测试过3没有错,所以可以判断大概三列的位置是有效的
之后进行数据库表名的爆破:
XXX?id=-1 union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database()
所得到的表名:显然获取用户名和密码users对我们是比较有用的
这里要注意几个数据库相关的知识:
1.group_concat()函数:将与括号中内容相关的所有数据都表示出来
2.information_schema是MySQL自带的信息数据库,用于存储数据库元数据(关于数据的数据),比如数据库名、表名、列的数据类型、访问权限等
之后爆破数据表中的字段名:得到username和password两个字段名
XXX?id=-1 union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'
XXX/?id=-1 20union select 1,2,group_concat(username,0x3a,password) from users
参考文献:
1.https://zhuanlan.zhihu.com/p/61796909(SQL注入-入门篇)
2.https://blog.csdn.net/weixin_44840696/article/details/88959371(使用Union语句进行SQL注入的基本原理)
3.https://www.jianshu.com/p/8a6f7011a72c(从0到1学习SQL安全注入)
还有一篇大佬的文章讲的很详细:
https://blog.csdn.net/fly_hps/article/details/80234840(sqli-lab----Less-1 字符型注入)