首页
社区
课程
招聘
[翻译]碎片化SQL注入攻击防御方案
2018-12-31 11:14 5572

[翻译]碎片化SQL注入攻击防御方案

2018-12-31 11:14
5572

碎片化SQL注入攻击防御方案

 
当你询问他人如何检测Web应用程序中是否存在SQL注入漏洞,他们很可能会建议将单引号放入应用程序中的参数中,然后,如果收到报错,他们可以推断存在SQL注入漏洞。如果你遇到将SQL注入定义为单引号注入的人,请不要感到惊讶。

 

SQL注入

 

本文中,我们将讨论对碎片化SQL注入(Fragmented SQL Injection)的研究,黑客控制同一上下文中的两个入口点以绕过验证表单。让我们快速看一下SQL注入攻击中单引号的重要性。

SQL注入中的单引号

在系统(例如命令解释器,文件系统或数据库管理系统)中,具有特殊含义的字符称为元字符。例如,在SQL查询上下文中,单引号和双引号用作字符串分隔符,用于字符串的开头和结尾。这就是为什么把单引号或双引号注入查询时,查询会中断并抛出错误。以下是在查询中插入引号的正确示例:

 

SELECT * FROM users WHERE user_name='USER_INPUT'

 

因此,当单个单引号被插入到上面的入口点时,查询解释器将提示无效语法或无法在字符串末尾找到引号对:

Code:
$username = "'";
$query = "SELECT * FROM users WHERE username='".$username."'"

Result:
SELECT * FROM users WHERE username='''

系统将在查询结束时抛出未配对的单引号错误。这仅对字符串上下文有效。由于id参数不是字符串格式,下面的上下文中并不需要插入单引号或双引号:

 

$query = "SELECT * FROM users WHERE id= " . $user_input;

 

在上面的示例中,为了执行SQL注入,你必须先输入一个数值,之后拼接的值也会被当做SQL命令的一部分。

 

由于注入单引号而返回的错误可能表示来自用户的输入未做任何过滤或处理,并且输入包含对数据库本身有特殊含义的字符。

 

让我们看一下单引号被屏蔽或在命令中被转义的例子:

$username ="' or 1=1 --";
$password ="qwerty123456";
// . . .
$query = "SELECT * FROM users WHERE username='".$username."' AND password='".$password."'";

select * from users where username='\' or 1=1 -- ' or password='qwerty123456';

如上例所示,因为单引号(')被转义为反斜杠,所以payload(有效载荷)无法按照黑客的意图执行。

碎片化SQL注入

碎片化SQL注入(不是其发明者Rodolfo使用的术语)指的是联合使用两个输入点以绕过认证表单的SQL注入。

 

如果黑客可以控制多个输入点,并且这些输入点的值处于同一个上下文中,则可以使用碎片化的payload来绕过黑名单和字符限制。

 

我们在上面的例子中看到,注入的单引号被转义为反斜杠(\)。在碎片化SQL注入中,如果在第一个字段中使用反斜杠,而在第二个字段中使用一个将返回'true'的SQL命令,则可以绕过该表单。演示如下:

username: \
password: or 1 # 

$query = select * from users where username='".$username."' and password='".$password."'";

select * from users where username='\' or password=' or 1 # ';

反斜杠转义了后面的单引号。因此,用户名列的值将以password=之后的单引号结束。这样做将从命令中删除所需的密码字段。由于or 1命令,条件将始终返回'true'。#(hash)将忽略函数的其余部分,就能够绕过登录控制和登录表单。

有缺陷的SQL注入攻击解决方案

请注意,我们在本文中引用的博客文章建议使用PHP中的htmlentities()函数来过滤输入,以防止我们上面描述的攻击。如果设置ENT_QUOTES标志,HTML编码会将单引号,双引号以及标签开始和结束标志转换为对应的HTML实体。例如,双引号将被编码为"

 

但是,这不是理想的解决方案,因为在某些情况下,不需要单引号或双引号来完成SQL注入攻击。除此之外,像GBK编码这样的老套技术可以用来绕过像PHP中的addslashes()函数这样的防范措施,这削弱了整体防范机制。

预处理语句(Prepared Statements)是防止SQL注入攻击的理想方法

在Netsparker,我们认为防止SQL注入攻击的正确和合理的解决方案是使用预处理语句,也称为参数化查询(Parameterized Queries)。

 

参数化查询允许将SQL查询的结构与值分开。其余防止SQL注入攻击的方法可能会在不久的将来被比如Chris Shiflett的巧妙方法绕过,因此不可靠。

在PHP和.NET中使用参数化查询

在PHP中,可以使用如下所示的参数化查询技术:

$stmt = $dbh->prepare("UPDATE users SET email=:new_email WHERE id=:user_id");
$stmt->bindParam(':new_email', $email);
$stmt->bindParam(':user_id', $id);

对于.NET应用,如下所示:

string sql = "SELECT * FROM Customers WHERE CustomerId = @CustomerId";
SqlCommand command = new SqlCommand(sql);
command.Parameters.Add(new SqlParameter("@CustomerId", System.Data.SqlDbType.Int));
command.Parameters["@CustomerId"].Value = 1;

结论

开发人员仍然使用黑名单来防止SQL注入漏洞。他们要么手动,要么使用专门的函数(例如addslashes函数)来防范SQL注入。但是,我们每天都会遇到新的信息安全威胁,试图挑战这些黑名单措施。最终,对抗基于注入的缺陷(比如SQL注入漏洞)的最佳方法是使用预处理语句。这是开发人员可以控制系统不要将用户控制参数作为查询结构一部分的唯一有效方法。

 

原文链接:https://www.netsparker.com/blog/web-security/fragmented-sql-injection-attacks/

 

翻译:看雪翻译小组 SpearMint

 

校对:看雪翻译小组 StrokMitream


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2018-12-31 11:14 被SpearMint编辑 ,原因:
收藏
点赞2
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回