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注入的语句也会不同。有几种探测数据库指纹信息:

  1. 第一种方法找出使用后端数据库是通过观察返回的错误应用程序。 以下是一些例子的错误消息:

MySql:

Oracle:

MS SQL Server:

PostgreSQL:

  1. 常见网页与数据库的关系。

代码与数据库并不存在绑定关系,以下只能做参考。

asp : Access/SQLServer

php : Mysql

jsp : Oracle

  1. 利用语句探测数据库

一种最可靠的方法是根据数据库连接字符串方式的不同进行识别。

如我们查询字符串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命令来执行。

内联注释可以用来包裹数据库关键字和非关键字。

http://book.fsec.io/bookimages/image-20220330103816362.png
http://book.fsec.io/bookimages/image-20220330104030637.png

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 限制数据库权限和特权

将数据库用户的功能设置为最低要求;这将限制攻击者在设法获取访问权限时可以执行的操作。

最后更新于

这有帮助吗?