SQL注入漏洞原理
注射式攻击的根源在于,程序命令和用户数据(即用户输入)之间没有做到泾渭分明。这使得攻击者有机会将程序命令当作用户输入的数据提交给Web程序,以发号施令,为所欲为(注:注入最终是数据库,属于服务端攻击,与脚本、平台、数据库类型无关)。
总之一句话:注入产生的原因是接受相关参数未经处理直接带入数据库查询操作
手工检测SQL注入点
只要有带参数交互的地方都有可能有SQL注入漏洞
登录的地方、更新的地方、注册的地方、留言板、查询、删除等
可能出现注入的地方:http头、cookices、referee、user agent,post提交数据包的地方等等
最常用的SQL注入点判断方法,是在网站中寻找如下形式的网页链接。
http://www.*****.com/***.asp?id=xx (ASP注入)
或者下面的链接。
http://www.*****.com/***.php?id=xx (php注入)
http://www.*****.com/***.jsp?id=xx (jsp注入)
http://www.*****.com/***.aspx?id=xx (aspx注入)
http://www.*****.com/index.asp?id=8&page=99 (注:注入的时候确认是id参数还是page参数,工具默认只对后面page参数注入,所以要对工具进行配置或者手工调换)
http://www.*****.com/index/new/id/8 伪静态
http://www. *****.com/index/new/php-8.html伪静态
其中的“**”可能是数字,也有可能是字符串,分别被称为整数类型数据和字符型数据。
Http Header注入
把http header直接代入数据库(referer/user-agent)
在数据库有记录referer/user-agent头的情况下可用
先在pikachu平台打开Http Header注入模块,点击提示查看登录帐号和密码,登陆后去BurpSuite中找到登陆地GET请求,把请求发送到Repeater模块中,去除User-Agent:,然后输入' 然后运行后观察MYSQL语法报错然后发现存在SQL注入漏洞。这时候可以设置payload。在User-Agent输入payload
' or updatexml(1,concat(0x7e,database ()),0) or '
Cookie注入
把数据参数写入到cookie里面。
Cookie是网站为了识别用户身份来跟踪会话的,虽然Cookie是由后端生成的,但每次页面跳转,后端都回对前端的Cookie的信息进行验证,但如果后端获取Cookie后放在数据库中进行拼接,那么这也将是一个SQL注入点。在
ant[uname]=admin后添加一个’观察反馈的MYSQL的语法报错,发现了存在SQL
注入漏洞,在设置Payload
'andupdatexml(1,concat(0x7e,database()),0)#
观察报错和之前是否相同。
如何判断某个网页链接是否存在SQL注入漏洞呢?通常有两种检测方法。
1.“单引号”法
第一种检测SQL注入漏洞是否存在的方法是“单引号”法。方法很简单,直接在浏览器地址栏中的网址链接后加上一个单引号,如果页面不能正常显示,浏览器返回一些异常信息,则说明该链接可能存在注入漏洞。
2. 1=1和1=2法
很多时候检测提交包含引号的链接时,会提示非法字符,或者直接不返回任何信息,但这并不等于不存在SQL注入漏洞。此时可使用经典的“1=1和1=2”法进行检测。方法很简单,就是直接在链接地址后分别加上and 1=1和and 1=2进行提交,如果返回不同的页面,那么说明存在SQL注入漏洞。
23.注入分类和注入提交方式
数字型 (' or 1=1#;) 数字型不需要单引号闭合字符型 (vince' or 1=1#;) 关键是如何闭合SQL语句和注释多余代码
搜索性 ('%vince%' or 1=1#;)
回到pikachu平台,将拼接语句写为%xxxx%'or 1=1 #%
XX型 (username=('xx') or 1=1#;)
回到pikachu平台,将拼接语句写为XX') or 1=1#
注释符
#
--空格
/**/
注释的提交方式
GET提交 一般直接通过浏览器提交
POST提交 通过burp抓包、火狐浏览器插件(hackbar)
COOKIE提交 通过burp抓包
HTTP Header头提交
24.注入攻击支持类型
联合查询,函数报错型,时间布尔型(盲注),堆叠注入,宽字节注入
Union注入
?id=1 order by
?id=1 order by 2 ?id=1 order by 3
?id=1 union select 1,2,3,4
?id=1 union select 1,databases(),3,4
?id=1 union select 1,databases(),user(),4
information_schema mysql5.0以上才有
mysql账户密码存在MySQL>user>
以下需要BP
基于函数报错注入
Insert注入
Update注入
Dalete注入
前提条件:后台没有屏蔽数据库报错信息,在语法发生错误时会输出在前端。函数
报错updatexml()、extractvalue()、 floor()
httphead注入
cookie注入
同上httphead注入cookie注入
盲注
1.基于布尔型SQL盲注
输入语句
select ascii(substr(database(),1,1))>xx;
通过对比ascii码的长度,判断出数据库表名的第一个字符。
注:substr()函数
substr(string,start,length)
string(必需)规定要返回其中一部分的字符串。start(必需)规定在字符串的何处开始。length(可选)规定被返回字符串的长度。
那么通过这个方法,虽然只能通过判断单个字符,我们同样可以使用length来判断表名的长度,判断出长度后就能多次输入payload来爆破出每一个表名的字符。输入语句:
select length(database())<xx;
判断表名长度为7。
回到pikachu平台按照之前的逻辑,我们构造语句,如果返回1,那么就会爆出选择的信息,返回0,就会返回 您输入的username不存在! 。按照之前逻辑,输入sql语句:
vince' and ascii(substr(database(),1,1))=112#
通过这个方法,就能得到后台数据库的名称的第一个字符的ascii码。
p
同之前的办法,我们也可以获得information_schema.tables里的数据。但在实际操作中通常不会使用手动盲注的办法,可以使用sqlmap等工具来增加盲注的效率。
2. 基于时间型SQL盲注
到base on time盲注下,输入上个演示中设置好的payload vince' and ascii(substr(database(),1,1))=112#,返回的信息发现不存在注入点。那这样就不能进行注入了?但其实可以通过后端的执行时间来进行注入。这里会用到的payload: vince' and sleep(x)#
基于时间的延迟,构造一个拼接语句:
vince' and if(substr(database(),1,1)='X' (猜测点:比如p)',sleep(10),null#,
输入后,如果猜测真确,那么就会响应10秒,如果错误会立刻返回错误。输入:vince' and if(substr(database(),1,1)='p',sleep(10),null)#,再web控制台下,判断出database的表名的一个字符为p。通过这个办法我们就能逐步向下获取数据。
p
堆叠注入
宽字节注入
宽字节注入是利用了编码中使用的是Ascii编码,而MySql使用了GBK编码,导致的注入漏洞单独注入一个单引号:’没任何反应。
代表了无法注入,主要原因是mysql中的addslashes函数,起作用是:,让’变成’,让引号变得不再是“单引号”,只是一撇而已。一般绕过方式就是,想办法处理’前面的\:
1.想办法给\前面再加一个\(或单数个即可),变成\’,这样\被转义了,'逃出了限制
2.想办法把\弄没有。
我们这里的宽字节注入是利用mysql的一个特性,mysql在使用GBK编码的时候,会认为两个字符是一个汉字(前一个ascii码要大于128,才到汉字的范围。
输入%df’ 试试:
为什么从刚才到现在,只是在’也就是%27前面加了一个%df就报错了?而且从图中可以看到,报错的原因就是多了一个单引号,而单引号前面的反斜杠不见了。
这就是mysql的特性,因为gbk是多字节编码,他认为两个字节代表一个汉字,所以%df和后面的\也就是%5c变成了一个汉字“運”,而’逃逸了出来。
明白了这个特性之后,就可以进行宽字节注入:
例如:?id=1%df’ order by 5%23 其中%23是为匹配本来属于sql语句的剩余的单引号
提示:输入表名或库名时,需要将之转为16进制表达。