您的位置:首页 > 数据库

Tip/Trick: Guard Against SQL Injection Attacks 提示/技巧:防范SQL注入攻击

2008-10-14 18:19 417 查看
SQL Injection attacks are really nasty security vulnerabilities, and something all web developers (regardless of platform, technology or data layer) need to make sure they understand and protect themselves against.
SQL注入攻击是非常严重的安全漏洞,所有web开发人员(不管平台,技术或数据层是什么)都必须确保他们理解并防范这些漏洞.

Unfortunately developers too often neglect putting focused time on this - and leave their applications (and worse their customers) extremely vulnerable.
不幸的是,开发人员经常对此视而不见,给他们的应用程序(特别是他们的客户)留下了严重的安全隐患.

Michael Sutton recently published a very sobering post about just how widespread this issue is on the public web. He built a C# client application that uses the Google Search API to look for sites vulnerable to SQL Injection Attacks. The steps to achieve this were simple:
Michael Sutton最近发了一个关于这个问题在公网上是如何普遍的帖子,发人深醒.他用Google搜索API写了一个C#客户应用程序
去寻找在SQL注入攻击方面存在安全漏洞的网站,简单步骤如下:

Look for sites that have querystring values (example: search for URLs with "id=" in the URL)
寻找有查询串值(例如:搜索URL中有"id="的那些URL)

Send a request to the sites identified as dynamic with an altered id= statement that adds an extra quote to attempt to cancel the SQL statement (example: id=6')
使用改变的id=语句给标记为动态的网站发送请求,同时在这些语句中添加额外的引号以试图注释SQL语句(例如:id=6')

Parse the response sent back to look for words like "SQL" and "query" - which typically indicate that the app is often sending back detailed error messages (also bad)
分析返回的响应以寻找类似"SQL"和"query"词语,这些通常表明应用程序总是时常返回详细的错误消息(也是严重的).

Review whether the error message indicates that the parameter sent to SQL wasn't encoded correctly (in which case the site is open to SQL Injection Attacks)
审查这些消息是否表明发送到SQL的参数没有正确编码(这种情况说明站点对SQL注入攻击是敞开大门的)

Of a random sampling of 1000 sites he found via his Google search, he detected possible SQL Injection Attack vulnerability with 11.3% of them. That is really, really scary. It means hackers can remotely exploit the data in those applications, retrieve any unhashed/encrypted passwords or credit-card data, and potentially even log themselves in as administrators to the application. This is bad not only for the developer who built the application, but even worse for any consumer/user of the application who has provided data to the site thinking it will be secure.
从他使用Google搜索发现的的1000个网站中随机取样,其中11.3%可能存在SQL注入攻击漏洞.这是非常非常可怕的.这意味着黑客能远程利用那些应用程序中的数据,检索任何明文或加密的密码或信用卡数据,他们甚至能够以管理员的身份登录到应用程序.这不仅对创建这个应用程序的开发人员是严重的,而且对使用应用程序的用户更严重,因为应用程序提供了数据给网站,而网站认为这些数据是安全的.

So what the heck is a SQL Injection Attack?
SQL注入攻击到底是什么?


There are a couple of scenarios that make SQL Injection attacks possible. The most common cause are cases where you are dynamically constructing SQL statements without using correctly encoded parameters. For example, consider this SQL query code that searches for Authors based on a social security number provided via a querystring:
有许多场景使SQL注入攻击成为可能.最常见的原因是你动态构建SQL语句时没有使用正确编码的参数.例如,下面的SQL查询代码基于查询串提供的社会安全号搜索作者:

Dim SSN as String
Dim SqlQuery as String

SSN = Request.QueryString("SSN")
SqlQuery = "SELECT au_lname, au_fname FROM authors WHERE au_id = '" + SSN + "'"

If you have SQL code like the snippet above, then your entire database and application can be hacked remotely. How? Well in the normal scenario users will hit the site using a social security number which will be executed like so:
如果你有类似上面片段的SQL代码,你的整个数据库和应用程序能被远程黑掉.怎样黑?好,在正常情况下,用户使用社会安全号进入这个站点,
执行过程大致如下:

' URL to the page containing the above code http://mysite.com/listauthordetails.aspx?SSN=172-32-9999
' SQL Query executed against the database
SELECT au_lname, au_fname FROM authors WHERE au_id = '172-32-9999'

This does what the developer expected, and searches the database for author information filtered by the social security number. But because the parameter value hasn't been SQL encoded, a hacker could just as easily modify the querystring value to embed additional SQL statements after the value to execute. For example:
通过社会安全号从数据库中搜索作者信息,这是开发人员期望的结果.但是因为没有SQL编码参数,黑客能够非常容易地通过在参数值后嵌入额外的SQL语句来修改查询串值.例如:

' URL to the page containing the above code http://mysite.com/listauthordetails.aspx?SSN=172-32-9999';DROP DATABASE pubs --

' SQL Query executed against the database
SELECT au_lname, au_fname FROM authors WHERE au_id = '';DROP DATABASE pubs --
Notice how I was able to add the ';DROP DATABASE pubs -- clause to the SSN querystring value and use it to terminate the current SQL statement (via the ";" character), and then add my own malicious SQL statement to the string, and then comment out the rest of the statement (via the "--" characters). Because we are just manually concatenating the SQL statement in our code, we will end up passing this to the database - which will execute first the query against the authors table, and then delete our pubs database table. Bang - it is now gone.

In case you think the idea of anonymous hackers deleting your database tables is bad, that is unfortunately actually one of the better scenarios when a SQL Injection Attack is involved. Rather than just destroy data, a hacker could instead use the above code vulnerability to perform a JOIN that retrieves all of the data within your database and displays it on the page (allowing them to retrieve username/passwords/credit-cards). They could also add UPDATE/INSERT statements to modify product prices, add new admin users, and really screw up your life (imagine auditing your inventory at the end of the month, only to discover that the actual number of products in your warehouse is different then what your accounting system reports...).
注意我是如何添加';DROP DATABASE pubs -- 子句到SSN查询串值,并且使用它终止当前SQL语句的执行(通过分号字符),然后我添加恶意的SQL语句到串,并且注释掉其余语句(通过"--"字符).因为在代码中我们仅仅手工连接SQL语句,所以我们能传这个恶意代码到数据库.它首先
针对authors 表执行查询,然后删除我们的pubs数据库表.砰!-数据库立马消失了.

如果你认为匿名黑客删除你的数据库的想法是龌龊的,那么,不幸的是,这还只是SQL注入攻击中不算严重的情况.除了仅仅摧毁数据外,黑客还能使用上面的代码漏洞执行一个连接,从而查询数据库中所有的数据,并且显示在页面(允许它们检索用户名/密码/信用卡)上.他们也能够增加UPDATE/INSERT语句去修改产品价格,添加新的管理员账户,这些真正搅乱你的生活(想像月末盘点你的库存,意外发现仓库中产品的实际数量是不同的,然后你会计系统报告一些.....)

How do you protect yourself?
怎样保护自己呢?


SQL Injection Attacks are something you need to worry about regardless of the web programming technology you are using (all web frameworks need to worry about it). A couple of very basic rules you must always follow:
不管你正在使用什么编程技术(所有Web框架都需要留意SQL注入攻击),SQL注入攻击都值得你去高度关注.你必须遵循如下一些最基本的规则:

1) Don't construct dynamic SQL Statements without using a type-safe parameter encoding mechanism. Most data
APIs (including ADO + ADO.NET) have support for allowing you to specify the exact type of a parameter being
provided (for example: string, integer, date) and can ensure that they are escaped/encoded for you to avoid
hackers trying to exploit it. Always use these features.
不要构建不使用类型安全参数编码机制的动态SQL语句.大多数数据API(包括ADO+ADO.NET)允许你指定参数的准确类型(例如:字符
串, 整数,日期),并且能确保这些参数被转义或编码,以避免黑客试图利用它们.

For example, with dynamic SQL using ADO.NET you could re-write the code above like below to make it safe:
例如,你能使用ADO.NET重写上面的代码来构建如下安全的动态SQL

Dim SSN as String = Request.QueryString("SSN")

Dim cmd As new SqlCommand("SELECT au_lname, au_fname FROM authors WHERE au_id = @au_id")
Dim param = new SqlParameter("au_id", SqlDbType.VarChar)
param.Value = SSN
cmd.Parameters.Add(param)
This will prevent someone from trying to sneak in additional SQL expressions (since ADO.NET above knows to
string encode the au_id value), and avoid other data problems (incorrectly type-casting values, etc). Note that
the TableAdapter/DataSet designer built-into VS 2005 uses this mechanism automatically, as do the ASP.NET 2.0
data source controls.
这将阻止有人试图插入额外的SQL表达式(因为上面的ADO.NET知道用字符串编码au_id值),同时也避免了其它数据问题(不正确的数据类
型转换值等).注意内置到VS 2005中的TableAdapter/DataSet设计器自动使用了这种机制,ASP.NET 2.0数据源控件也是一样.

One common misperception is that if you are using SPROCs or a ORM you are completely safe from SQL Injection
Attacks. This isn't true - you still need to make sure you are careful when you pass values to a SPROC, and/or
when you escape or customize a query with an ORM that you do it in a safe way.
一个常见的误解是如果你使用存储过程或对象关系映射,你就能完全避开SQL注入攻击.这是不正确的--当你传值到存储过程及转义或使用
对象关系映射安全自定义一个查询时,你还是必须谨慎处理.

2) Always conduct a security review of your application before ever put it in production, and establish a formal
security process to review all code anytime you make updates. This later point is super important. Too often I
hear of teams that conduct a really detailed security review before going live, then have some "really minor"
update they make to the site weeks/months later where they skip doing a security review ("it is just a tiny update
- we'll code review it later"). Always do a security review.
在产品化你的应用程序前总是对它作一个安全评估,也要确定一个正式的安全过程来评估你任何时候修改的代码.后者是超级重要的.我经常
听到一些团队在产品上线前做了非常细致的安全评估.几周或数月后他们对站点做了非常小的更新,但是忽略了对这些更新的安全评估("这
只是一个微不足道的更新,意味着我们先编码,以后再评估.")

3) Never store sensitive data in clear-text within a database. My personal opinion is that passwords should always
be one-way hashed (I don't even like to store them encrypted). The ASP.NET 2.0 Membership API does this for
you automatically by default (and also implements secure SALT randomization behavior). If you decide to build
your own membership database store, I'd recommend checking out the source code for our own Membership
provider implementation that we published here
. Also make sure to encrypt credit-card and other private data in
your database. This way even if your database was compromised, at least your customer private data can't be
exploited.
从来不要在数据库中以明文方式存储敏感数据.我的个人观点是密码应该总是单向哈希(我不喜欢以加密方式存储它们).ASP.NET 2.0
Membership API默认就是自动这样处理的(也实现了安全的SALT随机化行为).如果你决定创建你自己的成员资格数据库存储,我推荐你看
source code for our own Membership provider implementation that we published here. 也要确保在数据库中加密信用
卡和其它私密数据.这样即使你的数据库泄漏,至少你的客户私密数据不可能被利用.

4) Ensure you write automation unit tests that specifically verify your data access layer and application against SQL
Injection attacks. This is really important to help catch the "it is just a tiny update so I'll be safe" scenario, and
provide an additional safety layer to avoid accidentally introducing a bad security bug into your application.
你要保证写自动单元测试来针对SQL注入攻击检验你的数据访问层和应用层.这对帮助你发现"它仅仅是一个微小更新,所以是安全的"的情
况,非常重要,同时也提供了一个额外的安全层来避免突然引入一个严重的安全漏洞到你的应用程序.

5) Lock down your database to only grant the web application accessing it the minimal set of permissions that it
needs to function. If the web application doesn't need access to certain tables, then make sure it doesn't have
permissions to them. If it is only read-only generating reports from your account payables table then make sure
you disable insert/update/delete access.
只对web应用程序开放数据库,并且只给予功能需要的权限.如果web应用程序不需要访问某些表,就绝不要给其访问权限.如果它只是从你
account payables表读取数据生成只读报表,那么你就要保证禁用插入/更新/删除访问权限.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: