您的数据对您有价值吗?






1.80/5 (9投票s)
本文讨论了在缺乏适当验证程序的情况下,应用程序面临的威胁。
您的数据对您有价值吗?
“2005年6月17日,在可能是有史以来最大的数据安全泄露事件中,万事达卡国际公司于周五表示,超过4000万张信用卡的信息可能已被盗。该公司在一份声明中称,在泄露的账户中,约有1390万张是万事达品牌的信用卡。据称,约有2000万张维萨品牌的信用卡可能受到了影响,其余的品牌包括美国运通和发现卡。万事达卡表示,此次泄露发生在位于亚利桑那州图森的第三方支付数据处理商CardSystems Solutions。一名入侵者利用安全漏洞侵入了CardSystems网络并访问了持卡人数据。”[CNET News.com]
上述例子是近年来发生的几起安全事件之一。
在本文中,我将讨论在缺乏适当的数据验证和清理的情况下,恶意用户如何通过应用程序轻松地操纵数据库内容。
应用程序如何受到威胁?
黑客将一个格式错误的 SQL 语句输入到文本框中。然后,输入的数据会被用于对数据库执行 SQL 查询。如果数据在将其作为 SQL 查询发送到数据库之前没有进行清理,就可能导致插入、修改甚至删除数据库中的内容。
可以通过一个例子来很好地解释 SQL 注入攻击。
该 Windows 应用程序包含两个窗体,一个用于用户验证,另一个用于显示员工的工资。
数据库是 SQL Server 2000。数据库中有两个表。


普通用户
假设一个普通用户是该组织的员工。要查看工资详细信息,他/她将通过以下窗体登录。

在这种情况下,形成的 SQL 查询将是
SELECT COUNT (1) FROM tblusers where UserName='Ujwal' AND password='watgule'
既然 Ujwal
是该组织的授权员工,他将被导向一个窗体,使他能够查看自己的工资详细信息。

恶意用户
现在,一个用户在登录窗体中输入了以下数据,如下图所示。

现在形成的 SQL 查询是
SELECT COUNT (1) FROM tblusers where UserName='' OR 1=1 --'AND password=''
查询不是将用户提供的数据与 tblUser
表中的数据进行比较,而是将一个引号(空)与另一个引号(空)进行比较。这总是返回 True
。在 SQL 中,‘--’ 被视为注释。由于恶意用户在 User Id 文本框中输入了 ‘--’,查询中检查密码的部分被注释掉了:--'AND password=''. 因此,带有输入数据的 SQL 查询将始终返回多条记录,并将恶意用户导向工资详细信息页面。
更恶劣的用户
现在考虑一个更了解 SQL 语言的用户。我们之前的用户,即恶意用户,只能查看他人的工资详细信息。但这个更恶劣的用户可以插入、更新、删除员工的工资记录。
更恶劣的用户可以在 Employee No. 的文本框中输入 ‘ OR 1=1--,从而查看所有员工的工资详细信息,如下图所示。

插入记录
现在考虑更恶劣的用户输入的以下格式错误的语句。

形成的 SQL 查询是
SELECT * FROM tblSalary where EmployeeID='' OR 1=1;
INSERT INTO tblSalary (EmployeeID, EmployeeName, Salary, _
IncomeTax, ProfessionalTax, HRA) VALUES (5,'xyzBad','$70,000', 0, 0, 0)--'
在 SQL 中,我们可以执行由分号 (;) 分隔的多个查询。
如上一个查询所示,更恶劣的用户已在新记录添加到 Salary
表中,如下所示。

更新记录
现在考虑更恶劣的用户输入的以下语句。

形成的 SQL 查询是
SELECT * FROM tblSalary where EmployeeID='' OR 1=1;
Update tblSalary SET Salary='$ 0 ' WHERE EmployeeID =1--'
因此,更恶劣的用户已将员工编号 1 的工资更改为 0 美元。
删除记录
现在考虑更恶劣的用户输入的以下语句。

SELECT * FROM tblSalary where EmployeeID='' OR 1=1;
Delete FROM tblSalary WHERE EmployeeID='1'--'
更恶劣的用户通过在 Employee no. 文本框中插入 DELETE
查询,删除了员工编号 1 的记录。
有什么办法可以解决?
为了保护我们的应用程序(无论是 Windows 应用程序还是 Web 应用程序)免受 SQL 注入攻击,我们需要非常谨慎地处理客户端提供的数据。用户输入的每个字符都需要进行验证和清理。
就我们的 EmployeeSalary
应用程序而言,用户在两个地方输入数据:
- 一次是身份验证时,以用户名和密码的形式。
我们知道,通常用户名包含小写字母、大写字母、单引号或数字。除了这些字符,我们不应接受其他用户提供的数据。
在应用程序中,我们有一个名为
ValidateData()
的函数。此函数会检查用户输入的恶意字符。For intCount = 0 To strUserName.Length - 1 If strUserName.Substring (intCount, 1) = ";" Or _ strUserName.Substring (intCount, 1) = "=" Or _ strUserName.Substring (intCount, 1) = "-" Then blnFlag = False End If Next For intCount = 0 To strPassWord.Length - 1 If strPassWord.Substring(intCount, 1) = ";" Or _ strPassWord.Substring(intCount, 1) = "=" Then blnFlag = False End If Next If blnFlag = False Then Return False Else Return True End If
- 第二次是在显示
Salary
详细信息时,用户输入员工编号。我们知道,员工编号只包含数字。除了数字,我们不应接受其他用户提供的数据。
在应用程序中,我们有一个名为
ValidateData()
的函数。此函数会检查用户输入的恶意字符。For intCount = 0 To strEmpNo.Length - 1 If strEmpNo.Substring (intCount, 1) = ";" Or _ strEmpNo.Substring (intCount, 1) = "=" Or _ strEmpNo.Substring (intCount, 1) = "-" Then blnFlag = False End If Next If blnFlag = False Then Return False Else Return True End If
如何使您的应用程序更安全?
保护应用程序免受任何外部威胁的首要也是最重要的步骤是安全编码。在设计应用程序时应格外小心。我们必须遵守软件工程原则进行编码,绝不能妥协。
以下是一些针对 SQL 注入的建议措施:
- 验证和清理所有用户输入。
- 切勿使用动态 SQL 查询。
- 使用权限较低的帐户执行应用程序(请确保在 App.config 文件中,您没有使用默认帐户类型,即 sa)。
- 在可能的情况下,对您认为敏感的数据进行加密。
- 避免在用户提供的数据中使用注释(--)。
- 禁止批量执行查询。
- 禁止使用
sp_password
函数,因为如果它用于 SQL 查询,该查询不会出现在 SQL 日志中。 - 将单引号 (‘) 替换为双引号 (“)。