常见安全漏洞及修复方法
一、SQL 注入
1.1概况及技术描述
严重性:高
类型:应用程序级别测试
W ASC威胁分类:命令执行类型:SQL注入
CVE引用:不适用
安全风险:可能会在WEB服务器上运行远程命令,这通常意味着完全破坏服务器及其内容。
可能原因:
未对用户输入正确执行危险字符清理
技术描述:
这个“SQL 注入”变体试图将易受到攻击的脚本和参数名称所组成的文本写入本地文件系统的文件中。
不过,AppScan 不可能访问 SQL Server 文件系统,因此必须由用户来验证测试是否成功。AppScan 测试完成之后,请实际访问 SQL Server 机器,或通过远程连接来访问。
在 C 驱动器的根目录下,请检查是否有名称为“”的文件(也就是C:\)。
如果有,它会包含一份列表,列出所有易受攻击的脚本和参数。
这个变体的技术描述:
MS SQL 有一个能够运行 Shell 命令的内建函数。从查询环境安装一个 Shell 操作参数,便可以调用这个函数。
这个函数的利用方式如下:
假设基于 Web 的应用程序使用下列查询:
SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='$category' ORDER BY PRICE 其中 $category 是用户提供的类别描述(可能使用选择框)。
提供 ' p_cmdshell 'echo some text >> ' -- 字符串(作为$category)之后,形成的查询如下:
SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='' p_cmdshell 'echo some text >> ' --' ORDER BY PRICE
现在,这个查询可以分为三个部分:
[1] 第一个 SQL 查询:SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY=''
[2] 第二个 SQL 查询,执行 Shell 命令:p_cmdshell 'echo some text >> '
[3] MS SQL 注释:--' ORDER BY PRICE
如您所能见到,恶意的输入将查询的语意改成:查询、执行 Shell 命令,以及注释。
Web 应用程序通常在后端使用数据库,以与企业数据仓库交互。查询数据库事实上的标准语言是SQL(各大数据库供应商都有自己的不同版本)。Web 应用程序通常会获取用户输入(取自HTTP 请求),将它并入SQL 查询中,然后发送到后端数据库。接着应用程序便处理查询结果,有时会向用户显示结果。
如果应用程序对用户(攻击者)的输入处理不够小心,攻击者便可以利用这种操作方式。在此情况下,攻击者可以注入恶意的数据,当该数据并入SQL 查询中时,就将查询的原始语法更改得面目全非。例如,如果应用程序使用用户的输入(如用户名和密码)来查询用户帐户的数据库表,以认证用户,而攻击者能够将恶意数据注入查询的用户名部分(和/或密码部分),查询便可能更改成完全不同的数据复制查询,可能是修改数据库的查询,或在数据库服务器上运行Shell 命令的查询。
一般而言,攻击者会分步实现这个目标。他会先学习SQL 查询的结构,然后使用该知识来阻挠查询(通过注入更改查询语法的数据),使执行的查询不同于预期。假设相关查询是:
SELECT COUNT(*) FROM accounts WHERE username='$user' AND password='$pass'
其中$user 和$pass 是用户输入(从调用构造查询的脚本的HTTP请求收集而来-可能是来自GET 请求查询参数,也可能是来自POST 请求主体参数)。此查询的一般用法,其值为$user=john、$password=secret123。形成的查询如下:SELECT COUNT(*) FROM accounts WHERE username='john' AND password='secret123'
如果数据库中没有这个用户密码配对,预期的查询结果便是0,如果此类配对存在(也就是数据库中有名称为“john”的用户,且其密码为“secret123”),结果便是>0。这是应用程序的基本认证机制。但攻击者可以用下列方式来更改此查询:
攻击者可以提供单引号字符(')所组成的输入,使数据库发出错误消息,其中通常包含关于SQL 查询的有价值的信息。攻击者只需在发送的请求中包含用户值',并在密码中包含任何值(如foobar)。结果便是下列(格式错误)的SQL 查询:SELECT COUNT(*) FROM accounts WHERE username=''' AND password='foobar'
这可能会产生以下错误消息(取决于后端所使用的特定数据库):查询表达式'username = ''' AND password = 'foobar'' 中发生语法错误(遗漏运算符)。
这时攻击者便得知查询是根据表达式username='$user' AND password='$pass' 来构建的。利用手边的SQL 查询时需要这一关键信息。攻击者了解查询的格式后,下一步只需使用:
user = ' or 1=1 or ''=' password = foobar
生成的查询如下:
SELECT COUNT(*) FROM accounts WHERE username='' or 1=1 or ''='' AND
password='foobar'
这表示查询(在SQL 数据库中)对于“accounts”表的每项记录都会返回TRUE,因为1=1 表达式永远为
真。因此,查询会返回“accounts”中的记录数量,于是用户(攻击者)也会被视为有效。这个探测方法有若干变体,例如,发送'; or \'(您应该记住,几乎所有供应
商都有他们自己唯一的SQL“版本”。具体地说,发送' having 1=1,也会生成错误消息,此消息会泄露有关列名称的信息。在某些情况下,用户输入不会并入字符串上下文(用单引号括住),而是并入数字上下文,换言之,就是依现状嵌入。因此,在这种情况下,可以使用输入字符串 1 having 1=1。
* 盲目SQL注入技术:
降低SQL 注入攻击风险的一般方式,是禁止详细的SQL 错误消息,攻击者通常便利用这些消息(如上述示例所说明),轻易出容易遭受“SQL 注入”的脚本。
这个(以遮盖获取安全)解决方案可以利用称为“盲目SQL 注入”的技术来略过,黑客不需要依赖返回SQL 错误消息,便能出容易遭受“SQL 注入”的脚本。
这项技术需要发送易受攻击的参数(被嵌入在SQL 查询中的参数)已被修改的请求,将参数修改成,使响应指出是否在SQL 查询上下文中使用数据。这项修改包括搭配原始字符串来使用AND Boolean 表达式,使它一时得出true,一时得出false。在一种情况中,最终结果应该与原始结果相同(例如:登录成功),在另一情况中,结果应该不同(例如:登录失败)。在某些少见的情况中,得出true 的OR 表达式也很有用。
如果原始数据是数字,可以耍较简单的花招。原始数据(如123)可以在一个请求中替换为0+123,在另一个请求中替换为456+123。第一个请求的结果应该与原始结果相同,第二个请求的结果应该不同(因为得出的数字是579)。在某些情况中,我们仍需要上面所说明的攻击版本(使用AND 和OR),但并不转义字符串上下文。
盲目SQL 注入背后的概念是,即使未直接收到数据库的数据(以错误消息或泄漏信息的形式),也可能抽取数据库中的数据,每次一个位,或以恶意方式修改查询。观念在于,应用程序行为(结果与原始结果相同,或结果与原始结果不同)可以提供关于所求值(已修改)之查询的单位元相关信息,也就是说,攻击者有可能规划出以应用程序行为(相同/不同于原始行为)的形式来影响其求值(单位元)的SQL Boolean
受影响产品:
基于MS SQL 的Web 应用程序及各种类型的产品。
参考资料
SQL注入常见问题:www.sqlsecurity/FAQs/SQLInjectionFAQ/tabid/56/Default.aspx 清理CGI脚本中的用户提供数据:/advisories/CA-1997-25.html
1.2修复方法
一般
若干问题的补救方法在于对用户输入进行清理。
通过验证用户输入未包含危险字符,便可能防止恶意的用户导致应用程序执行计划外的任务,例如:启动任意 SQL 查询、嵌入将在客户端执行的 Javascript 代码、运行各种操作系统命令,等等。
建议过滤出所有以下字符:
[1] |(竖线符号)
[2] & (& 符号)
[3];(分号)
[4] $(美元符号)
[5] %(百分比符号)
[6] @(at 符号)
[7] '(单引号)
[8] "(引号)
[9] \'(反斜杠转义单引号)
[10] \"(反斜杠转义引号)
[11] <>(尖括号)
[12] ()(括号)
[13] +(加号)
[14] CR(回车符,ASCII 0x0d)
[15] LF(换行,ASCII 0x0a)
[16] ,(逗号)
[17] \(反斜杠)
以下部分描述各种问题、问题的修订建议以及可能触发这些问题的危险字符:
SQL 注入和 SQL 盲注:
A. 确保用户输入的值和类型(如 Integer、Date 等)有效,且符合应用程序预期。
B. 利用存储过程,将数据访问抽象化,让用户不直接访问表或视图。当使用存储过程时,请利用 ADO 命令对象来实施它们,以强化变量类型。
C. 清理输入以排除上下文更改符号,例如:
[1] '(单引号)
[2] "(引号)
[3] \'(反斜线转义单引号)
[4] \"(反斜杠转义引号)
[5] )(结束括号)
[6] ;(分号)
跨站点脚本编制:
A. 清理用户输入,并过滤出 JavaScript 代码。我们建议您过滤下列字符:
[1] <>(尖括号)
[2] "(引号)
[3] '(单引号)
[4] %(百分比符号)
[5] ;(分号)
[6] ()(括号)
[7] &(& 符号)
[8] +(加号)
B. 如果要修订 <%00script> 变体,请参阅 MS 文章 821349
C. 对于 UTF-7 攻击: [-] 可能的话,建议您施行特定字符集编码(使用 'Content-Type' 头或 <meta> 标记)。
HTTP 响应分割:清理用户输入(至少是稍后嵌入在 HTTP 响应中的输入)。
请确保输入未包含恶意的字符,例如:
[1] CR(回车符,ASCII 0x0d)
[2] LF(换行,ASCII 0x0a)远程命令执行:清理输入以排除对执行操作系统命令有意义的符号,例如:
[1] |(竖线符号)
[2] & (& 符号)
[3];(分号)
执行 shell 命令:
A. 绝不将未检查的用户输入传递给 eval()、open()、sysopen()、system() 之类的 Perl 命令。
B. 确保输入未包含恶意的字符,例如:
[1] $(美元符号)
[2] %(百分比符号)
[3] @(at 符号)
XPath 注入:清理输入以排除上下文更改符号,例如:
[1] '(单引号)
[2] "(引号)等
LDAP 注入:
A. 使用正面验证。字母数字过滤(A..,0..9)适合大部分 LDAP 查询。
B. 应该过滤出或进行转义的特殊 LDAP 字符:
[1] 在字符串开头的空格或“#”字符
[2] 在字符串结尾的空格字符
[3] ,(逗号)
[4] +(加号)
[5] "(引号)
[6] \(反斜杠)
[7] <>(尖括号)
[8] ;(分号)
xpath注入解决方案[9] ()(括号)
MX 注入:
应该过滤出特殊 MX 字符:
[1] CR(回车符,ASCII 0x0d)
[2] LF(换行,ASCII 0x0a)记录伪造:
应该过滤出特殊记录字符:
[1] CR(回车符,ASCII 0x0d)
[2] LF(换行,ASCII 0x0a)
[3] BS(退格,ASCII 0x08)
ORM 注入:
A. 确保用户输入的值和类型(如 Integer、Date 等)有效,且符合应用程序预期。
B. 利用存储过程,将数据访问抽象化,让用户不直接访问表或视图。
C. 使用参数化查询 API
D. 清理输入以排除上下文更改符号,例如: (*):
[1] '(单引号)
[2] "(引号)
[3] \'(反斜线转义单引号)
[4] \"(反斜杠转义引号)
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论