SQL注入(下)
SQL注入(下)
201-A4-SQL注入(下)
在本节中,我们将学习一些SQL注入中绕过网站防御机制的方法。
1. SQL注入的一些细节
当我们远程测试网站是否存在SQL注入,常常需要通过推理来进行大量测试。即看到网页上的执行结果,推理后台数据库是如何操作的。
1.1 可能存在SQL注入的功能点
SQL注入可以出现在任何从系统或接受用户输入的前段应用程序中。
换句话说,每个前端与后端数据库有交互的地方,都有可能存在SQL注入漏洞。
比如最常见的是在搜索和登录功能。但其他与数据库交互的地方也值得注意:如cookie中,XFF中。
1.2 闭合
在存在注入点的网页上,其后端代码可能是如下的几种格式:
$sql = "SELECT * FROM users WHERE id = $id LIMIT 0,1";
$sql = "SELECT * FROM users WHERE id = '$id' LIMIT 0,1";
$sql = "SELECT * FROM users WHERE id = ('$id') LIMIT 0,1";此时我们构造sql语句注入时,则要考虑闭合前面的引号括号。
因为如果注入后,破坏了原有的闭合,那么注入也会失败,所以闭合很重要,决定了最后是否可以注入成功。
如:
注入 1' or 1=1 --+
常见的闭合形式:
最后,可以用and1=1,or 1=1 等语句确认闭合完成,漏洞存在。
1.3 测试列数
除了前文中提到的 order by 语句以外。
也可以用如下的形式来探测:
不断增加 null 至不返回。
1.4 探测数据库指纹
在此前的实验中,我们都是使用MariaDB作为后端数据库的,其属于mysql系列数据库。
如果后端数据库不同,那么SQL注入的语句也会不同。有几种探测数据库指纹信息:
第一种方法找出使用后端数据库是通过观察返回的错误应用程序。 以下是一些例子的错误消息:
MySql:
Oracle:
MS SQL Server:
PostgreSQL:
常见网页与数据库的关系。
代码与数据库并不存在绑定关系,以下只能做参考。
asp : Access/SQLServer
php : Mysql
jsp : Oracle
利用语句探测数据库
一种最可靠的方法是根据数据库连接字符串方式的不同进行识别。
如我们查询字符串farmsec得到了一个结果,可以在请求中提交特殊的值,测试用各种方法连接,以生成farmsec字符串。如过查询结果相同,就可以确定是哪一种数据库。
如果注入数字数据,可以使用下面的攻击语句来识别字符串。
每个语句在其对应的数据库中求值结果为0,在其他数据库中则会报错。
1.5 各类数据库注入语句
不同的数据库,需要用不同的sql语句注入。
1.5.1 MySQL数据库
1.5.2 Oracle数据库
1.5.3 MSSQL数据库
1.5.4 PostgreSQL数据库
2.绕过网站防御机制思路
绝大部分的网站防御机制,无论是过滤、转义或是商业waf,都是基于某种正则表达式的规则匹配而运作的。也就是说,攻击者的行为一旦匹配了某种正则表达式所预料到的特征,就可能被拦截。而绕过防御机制则是,将简单的攻击语句复杂化,使其出乎编写防御程序者的意料,同时确保被复杂化的攻击语句保持原有的功效。下面将介绍几种常见的绕过思路:
2.1 大小写绕过
一般来说,只要网站考虑了防御机制,现在的设计者是不会忘记注意大小写的。但我们还是把绕过思路从简单到复杂的讲述出来,大小写绕过是最简单的一种绕过方法,它成功的前提是网站防御规则中只匹配了字母小写的攻击语句特征。如select可能会被规则发现,SeLeCt则不会。
2.2 双写绕过
在某些网站,会对用户提交的一段字符进行匹配,对其认为危险的字符删除,同时放过余下其认为安全的字符。
例如,用户输入1' and 1=2 union select 1,2,3,4#,经过网站的过滤机制,服务器实际接收到的则是1' and 1=2 1,2,3,4#
此时可以双写绕过:
经过网站过滤机制,UNIunionON SELselectECT实际变成了UNION SELECT。但要注意,这只适用于网站防御机制只匹配一次、过滤一次的情况。如果网站正则具有循环匹配,循环过滤直至匹配不到的机制,那么这种绕过方法就不再适用了。
2.3 编码绕过
如果网站防御机制未考虑过各类编码情况,那么将攻击语句编码后再发送也是一种很好的方法。
2.3.1 URL编码
通常来说,在浏览器输入URL时,浏览器会对一些字符进行URL 编码如,空格变为%20、单引号%27、左括号%28、右括号%29。而服务器收到后会对其进行解码。如果网站具备防御机制,则会对解码后的内容进行规则匹配。然而一些程序在执行了过滤之后还会执行一次不必要的解码,
比如我们输入带有url编码的字符串:
1%2527%20and%201%253d1%23,这条字符在会被解码为:1%27 and 1%3d1#,其中没有'和=,假设这样就不会触发某些防御规则,然而当waf放过这串字符后,网站程序又会执行一次不必要的解码,再次解码后文本变成如此:1' and 1=1#,这一条将被数据库执行。
2.3.2 十六进制编码
主要用于where语句后的引号问题,如:



==2.3.3 char()函数==
2.4 注释绕过
2.4.1 注释绕过针对空格的过滤



2.4.2 内联注入
/*![数据库版本][数据库函数]*/,和注释/**/的区别是多了一个感叹号,可选的数据库版本号。
这种注释在mysql中叫做内联注释,当实际的版本等于或是高于写入的[数据库版本],应用程序就会将注释内容解释为SQL命令,否则就会当做注释来处理。默认情况下,不添加数据库版本也会当做SQL命令来执行。
内联注释可以用来包裹数据库关键字和非关键字。


2.5 等价语句替换
在有些函数或命令因其关键字被检测出来而无法使用的情况下,我们可以考虑使用与之等价或类似的代码替代其使用。
sleep()与benchmark()
mysql中可用BENCHMARK(50000000,MD5(‘A’))产生延迟,执行MD5()50000000次,产生的延迟时间和服务器性能有关。

concat_ws() 与 group_concat()



2.6 常见过滤字符及绕过
当空格被过滤后,可通过以下方法绕过:
过滤union\select
过滤引号
过滤=
过滤逗号
过滤注释符
过滤where
过滤limit
过滤group by
过滤select
过滤hex
过滤substr
过滤and,or
3.sql注入的防御方法
3.1 过滤
可以对用户提交的敏感字符进行过滤和拦截。
3.2 转义
可以对用户提交的敏感字符进行转义。
3.3 参数化查询
参数化查询也叫做预处理,它分两个步骤处理用户的输入。
网站应用程序指定了查询语句结构,并为用户输入的每个数据预留了占位符。
网站应用程序指定每个占位符的内容。
在第二个步骤中,用户输入被填入占位符,但不会改变第一个步骤中预设好的查询语句结构。这样,网站应用程序就不会将用户输入判断为sql语句执行了,而会把用户的输入当做一个整体去查询。
3.4 加密存储
对重要数据,不在表单中明文存储,而选择加密存储。
3.5 限制数据库权限和特权
将数据库用户的功能设置为最低要求;这将限制攻击者在设法获取访问权限时可以执行的操作。
最后更新于
这有帮助吗?