用户工具

站点工具


cwe:cn:definition:89

这是本文档旧的修订版!


CWE-89:SQL命令中使用的特殊元素转义处理不恰当(SQL注入)

概要描述

软件使用来自一个上游组件的外部输入数据构造全部或部分的SQL命令,但它在将SQL命令发送到下游组件时,没有处理或没有正确地处理输入数据中可能会改变预期的SQL的特殊元素。

扩展描述

在没有充分地去除或引述用户可控的输入中的SQL语法的情况下,生成的SQL查询可能导致这些用户输入被解释为SQL语句而并非普通的用户数据。这能够被用于改变查询逻辑以绕过安全检查或者插入额外的语句修改后台数据库,甚至包括执行系统命令。

SQL注入已经成为数据驱动网站的一个普遍问题。这种缺陷容易被发现,容易被利用,正因如此,任何网站或软件包——哪怕只有很小的用户群体都有可能成为这种类型攻击的主体。这种缺陷依赖于一个事实,即SQL没有将控制层和数据层真正地区别开。

引入方式

这种弱点通常出现在使用数据库保存用户输入的富数据(data-rich)应用程序中。

利用要点

应用程序动态地生成包含用户输入的查询。

利用可能性

非常高

常见的影响

范围 技术影响 备注
机密性读取应用程序数据因为SQL数据库通常保存有敏感数据,机密性被破坏是SQL注入漏洞带来的常见问题。
访问控制绕过防御机制如果检查用户名和口令的SQL命令设计失误,可能会导致在不知悉口令的情况下使用另外用户的身份登录到系统。
访问控制绕过防御机制如果身份认证信息保存在SQL数据库中,那么成功利用SQL注入漏洞可能能够更改这些认证信息。
完整性篡改应用程序数据同读取敏感信息一样,SQL注入攻击还能够篡改甚至删除这些信息。

检测方法

检测方法 - 1

Automated Static Analysis

This weakness can often be detected using automated static analysis tools. Many modern tools use data flow analysis or constraint-based techniques to minimize the number of false positives.

Automated static analysis might not be able to recognize when proper input validation is being performed, leading to false positives - i.e., warnings that do not have any security consequences or do not require any code changes.

Automated static analysis might not be able to detect the usage of custom API functions or third-party libraries that indirectly invoke SQL commands, leading to false negatives - especially if the API/library code is not available for analysis.

This is not a perfect solution, since 100% accuracy and coverage are not feasible.
2013/05/30 09:36

检测方法 - 2

Automated Dynamic Analysis

This weakness can be detected using dynamic tools and techniques that interact with the software using large test suites with many diverse inputs, such as fuzz testing (fuzzing), robustness testing, and fault injection. The software's operation may slow down, but it should not become unstable, crash, or generate incorrect results.

2013/05/30 09:36

检测方法 - 3

Manual Analysis

Manual analysis can be useful for finding this weakness, but it might not achieve desired code coverage within limited time constraints. This becomes difficult for weaknesses that must be considered for all inputs, since the attack surface can be too large.

2013/05/30 09:36

缓解方案

缓解方案 - 1

Architecture and Design

Strategy:Libraries or Frameworks

Use a vetted library or framework that does not allow this weakness to occur or provides constructs that make this weakness easier to avoid.

For example, use anti-CSRF packages such as the OWASP CSRFGuard. [R.352.3]

Another example is the ESAPI Session Management control, which includes a component for CSRF. [R.352.9]

2013/05/30 09:36

缓解方案 - 2

Architecture and Design

Strategy:Parameterization

If available, use structured mechanisms that automatically enforce the separation between data and code. These mechanisms may be able to provide the relevant quoting, encoding, and validation automatically, instead of relying on the developer to provide this capability at every point where output is generated.

Process SQL queries using prepared statements, parameterized queries, or stored procedures. These features should accept parameters or variables and support strong typing. Do not dynamically construct and execute query strings within these features using “exec” or similar functionality, since this may re-introduce the possibility of SQL injection. [R.89.3]

2013/05/30 09:37

缓解方案 - 3

Architecture and Design Operation

Strategy:Environment Hardening

Run your code using the lowest privileges that are required to accomplish the necessary tasks [R.98.2]. If possible, create isolated accounts with limited privileges that are only used for a single task. That way, a successful attack will not immediately give the attacker access to the rest of the software or its environment. For example, database applications rarely need to run as the database administrator, especially in day-to-day operations.

2013/05/30 09:37

缓解方案 - 4

Architecture and Design

For any security checks that are performed on the client side, ensure that these checks are duplicated on the server side, in order to avoid CWE-602. Attackers can bypass the client-side checks by modifying values after the checks have been performed, or by changing the client to remove the client-side checks entirely. Then, these modified values would be submitted to the server.

2013/05/30 09:37

缓解方案 - 5

Implementation

Strategy:Output Encoding

While it is risky to use dynamically-generated query strings, code, or commands that mix control and data together, sometimes it may be unavoidable. Properly quote arguments and escape any special characters within those arguments. The most conservative approach is to escape or filter all characters that do not pass an extremely strict whitelist (such as everything that is not alphanumeric or white space). If some special characters are still needed, such as white space, wrap each argument in quotes after the escaping/filtering step. Be careful of argument injection (CWE-88).

Instead of building a new implementation, such features may be available in the database or programming language. For example, the Oracle DBMS_ASSERT package can check or enforce that parameters have certain properties that make them less vulnerable to SQL injection. For MySQL, the mysql_real_escape_string() API function is available in both C and PHP.

2013/05/30 09:37

缓解方案 - 6

Implementation

Strategy:Input Validation

Assume all input is malicious. Use an “accept known good” input validation strategy, i.e., use a whitelist of acceptable inputs that strictly conform to specifications. Reject any input that does not strictly conform to specifications, or transform it into something that does.

When performing input validation, consider all potentially relevant properties, including length, type of input, the full range of acceptable values, missing or extra inputs, syntax, consistency across related fields, and conformance to business rules. As an example of business rule logic, “boat” may be syntactically valid because it only contains alphanumeric characters, but it is not valid if the input is only expected to contain colors such as “red” or “blue.”

Do not rely exclusively on looking for malicious or malformed inputs (i.e., do not rely on a blacklist). A blacklist is likely to miss at least one undesirable input, especially if the code's environment changes. This can give attackers enough room to bypass the intended validation. However, blacklists can be useful for detecting potential attacks or determining which inputs are so malformed that they should be rejected outright.

2013/05/30 09:37

缓解方案 - 7

Architecture and Design

Strategy:Enforcement by Conversion

When the set of acceptable objects, such as filenames or URLs, is limited or known, create a mapping from a set of fixed input values (such as numeric IDs) to the actual filenames or URLs, and reject all other inputs.

2013/05/30 09:37

缓解方案 - 8

Implementation

Ensure that error messages only contain minimal details that are useful to the intended audience, and nobody else. The messages need to strike the balance between being too cryptic and not being cryptic enough. They should not necessarily reveal the methods that were used to determine the error. Such detailed information can be used to refine the original attack to increase the chances of success.

If errors must be tracked in some detail, capture them in log messages - but consider what could occur if the log messages can be viewed by attackers. Avoid recording highly sensitive information such as passwords in any form. Avoid inconsistent messaging that might accidentally tip off an attacker about internal state, such as whether a username is valid or not.

In the context of SQL Injection, error messages revealing the structure of a SQL query can help attackers tailor successful attack strings.

2013/05/30 13:23

缓解方案 - 9

Operation

Strategy:Firewall

Use an application firewall that can detect attacks against this weakness. It can be beneficial in cases in which the code cannot be fixed (because it is controlled by a third party), as an emergency prevention measure while more comprehensive software assurance measures are applied, or to provide defense in depth.

2013/05/30 09:37

缓解方案 - 10

Operation Implementation

Strategy:Environment Hardening

When using PHP, configure the application so that it does not use register_globals. During implementation, develop the application so that it does not rely on this feature, but be wary of implementing a register_globals emulation that is subject to weaknesses such as CWE-95, CWE-621, and similar issues.

Often, programmers do not protect direct access to files intended only to be included by core programs. These include files may assume that critical variables have already been initialized by the calling program. As a result, the use of register_globals combined with the ability to directly access the include file may allow attackers to conduct file inclusion attacks. This remains an extremely common pattern as of 2009.

2013/05/30 09:37

示例

示例 - 1

在2008年,大量的Web服务器被同一条SQL注入攻击字符串攻陷。这一条字符串能够应用于大量不同的程序。后来这些SQL注入攻击被用于将web网站篡改为恶意代码的载体。[1]

示例 - 2

下面的代码动态地创建并执行一个用来搜索符合某个特定名称条目的SQL查询。查询限定为仅显示当前已登录用户所属的条目。

... 
string userName = ctx.getAuthenticatedUserName(); 
string query = "SELECT * FROM items WHERE owner = '" + userName + "' AND itemname = '" + ItemName.Text + "'"; 
sda = new SqlDataAdapter(query, conn); 
DataTable dt = new DataTable(); 
sda.Fill(dt); 
... 

这条查询期望执行下面的SQL语句:

SELECT * FROM items WHERE owner = <userName> AND itemname = <itemName>; 

但是,由于查询是由一段固化的查询语句和用户的输入组合而成的,所以查询仅在itemName不包含单引号的情况下是正确的。如果一名用户名称为wiley的攻击者输入下面的字符串:

name' OR 'a'='a 

作为itemName,那么查询变成了下面这样:

SELECT * FROM items WHERE owner = 'wiley' AND itemname = 'name' OR 'a'='a'; 

添加了下面代码后:

OR 'a'='a' 

用户输入的条件导致WHERE语句的计算结果永远为true,这样这条查询逻辑上等于下面这条简单的多的查询:

SELECT * FROM items; 

这种简单的技巧允许攻击者绕过原始查询仅返回认证用户所拥有条目的限制;修改后的查询会返回存储在数据表中的全部条目,不论这些条目的拥有者是哪个用户。

示例 - 3

本示例在示例2的基础上,分析了另一种不同的恶意值被传递到查询中并执行会出现的后果。

如果一个用户名称为wiley的攻击者输入如下字符串:

name'; DELETE FROM items; -- 

作为itemName的值,那么这条查询变成了下面两条查询语句:

SELECT * FROM items WHERE owner = 'wiley' AND itemname = 'name'; 
DELETE FROM items; 
--' 

很多数据库服务器,包括Microsoft(R) SQL Server 2000,允许一次执行多个使用分号分隔开的SQL语句。然而这条攻击字符串在Oracle或其它不允许批量执行分号分隔的SQL语句的数据库服务器中会产生一条错误。在允许批量执行的数据库系统中,这种攻击允许攻击者在数据库系统中执行任意的指令。

注意尾部的两个连字符(–),在大部分数据库服务器中,这两个符号表示其后的语句为注释部分而不应被执行。在此例中,注释符号把被修改的查询语句后面剩下的一个单引号给注释掉了。在数据库不允许使用这样的注释符号的情况下,上个示例中的技巧依然管用。

如果一个攻击者输入下面的字符串:

name'; DELETE FROM items; SELECT * FROM items WHERE 'a'='a 

那么实际上生成了如下3个语句:

SELECT * FROM items WHERE owner = 'wiley' AND itemname = 'name'; 
DELETE FROM items; 
SELECT * FROM items WHERE 'a'='a'; 

一种防御SQL注入攻击的惯用解决方案是把它们看待为输入验证问题:可以创建白名单仅接受安全的取值,或者创建黑名单过滤具有潜在危险的取值。从执行严格的输入验证规则方面来看,白名单机制是非常有效的,但是参数化SQL语句需要更少的维护,而且能够提供更多的安全保障。而黑名单机制却总是存在千疮百孔的漏洞,它很难有效地应对SQL注入攻击。举例来说,攻击者可以做如下事情绕过黑名单的防御:

  • 定位没有进行安全处理的字段。
  • 找到被转义(escape)的特定元字符(meta-characters)的替代方法。
  • 使用存储过程隐藏注入原字符。

人工地转义输入到SQL查询中的字符能够起到一定作用,但它不能保证让你的应用不受到SQL注入的攻击。

Another solution commonly proposed for dealing with SQL injection attacks is to use stored procedures. Although stored procedures prevent some types of SQL injection attacks, they do not protect against many others. For example, the following PL/SQL procedure is vulnerable to the same SQL injection attack shown in the first example.

procedure get_item ( itm_cv IN OUT ItmCurTyp, usr in varchar2, itm in varchar2) 
is open itm_cv for 
' SELECT * FROM items WHERE ' || 'owner = '|| usr || ' AND itemname = ' || itm || '; 
end get_item; 

Stored procedures typically help prevent SQL injection attacks by limiting the types of statements that can be passed to their parameters. However, there are many ways around the limitations and many interesting statements that can still be passed to stored procedures. Again, stored procedures can prevent some exploits, but they will not make your application secure against SQL injection attacks.

示例 - 4

MS SQL has a built in function that enables shell command execution. An SQL injection in such a context could be disastrous. For example, a query of the form:

SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='$user_input' ORDER BY PRICE 

Where $user_input is taken from an untrusted source.

If the user provides the string:

'; exec master..xp_cmdshell 'dir' -- 

The query will take the following form:

SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY=''; exec master..xp_cmdshell 'dir' --' ORDER BY PRICE 

Now, this query can be broken down into:

  1. a first SQL query: SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='';
  2. a second SQL query, which executes the dir command in the shell: exec master..xp_cmdshell 'dir'
  3. an MS SQL comment: –' ORDER BY PRICE

As can be seen, the malicious input changes the semantics of the query into a query, a shell command execution and a comment.

示例 - 5

This code intends to print a message summary given the message ID.

$id = $_COOKIE["mid"]; 
mysql_query("SELECT MessageID, Subject FROM messages WHERE MessageID = '$id'"); 

The programmer may have skipped any input validation on $id under the assumption that attackers cannot modify the cookie. However, this is easy to do with custom client code or even in the web browser.

While $id is wrapped in single quotes in the call to mysql_query(), an attacker could simply change the incoming mid cookie to:

1432' or '1' = '1 

This would produce the resulting query:

SELECT MessageID, Subject FROM messages WHERE MessageID = '1432' or '1' = '1' 

Not only will this retrieve message number 1432, it will retrieve all other messages.

In this case, the programmer could apply a simple modification to the code to eliminate the SQL injection:

$id = intval($_COOKIE["mid"]); 
mysql_query("SELECT MessageID, Subject FROM messages WHERE MessageID = '$id'"); 

However, if this code is intended to support multiple users with different message boxes, the code might also need an access control check (CWE-285) to ensure that the application user has the permission to see that message.

示例 - 6

This example attempts to take a last name provided by a user and enter it into a database.

$userKey = getUserID(); 
$name = getUserInput(); 
# ensure only letters, hyphens and apostrophe are allowed 
$name = whiteList($name, "^a-zA-z'-$"); 
$query = "INSERT INTO last_names VALUES('$userKey', '$name')"; 

While the programmer applies a whitelist to the user input, it has shortcomings. First of all, the user is still allowed to provide hyphens which are used as comment structures in SQL. If a user specifies – then the remainder of the statement will be treated as a comment, which may bypass security logic. Furthermore, the whitelist permits the apostrophe which is also a data / command separator in SQL. If a user supplies a name with an apostrophe, they may be able to alter the structure of the whole statement and even change control flow of the program, possibly accessing or modifying confidential information. In this situation, both the hyphen and apostrophe are legitimate characters for a last name and permitting them is required. Instead, a programmer may want to use a prepared statement or apply an encoding routine to the input to prevent any data / directive misinterpretations.

验证实例

Reference Description
CVE-2004-0366chain: SQL injection in library intended for database authentication allows SQL injection and authentication bypass.
CVE-2008-2790SQL injection through an ID that was supposed to be numeric.
CVE-2008-2223SQL injection through an ID that was supposed to be numeric.
CVE-2007-6602SQL injection via user name.
CVE-2008-5817SQL injection via user name or password fields.
CVE-2003-0377SQL injection in security product, using a crafted group name.
CVE-2008-2380SQL injection in authentication library.
cwe/cn/definition/89.1370661293.txt.gz · 最后更改: 2013/06/08 11:14 由 evan