如果你每天访问的网站需要登录
那么你的登录用户名和密码很可能是保存在关系数据库中
其他网站用户的登录信息也和你一起保存在数据库中
但愿你的密码保存前经过加密处理
如果是明文存储的话简直太可怕了
不幸的是有一些网站存在安全漏洞攻击者可以通过一种叫做SQL注入的攻击技术窃取到存储在数据库中的密码信息
更令人担忧的是即使数据库打上所有补丁也不能避免这种攻击这不是一个补丁问题更多的与数据库工作方式及系统设计有关
这种攻击可以针对任何包含来自数据库的数据的网页如一个搜索页面客户意见反馈页面不管数据库是MySQLSQL Server还是Oracle都无法避免这种攻击SQL注入攻击不仅是针对SQL Server的
通常在数据库中使用一个表来存储用户登录信息这个表至少有两列一列存储用户名(username)另一列存储密码(password)而表名通常会被取为users或类似的名字
当用户在网站上提交他们的详细信息时数据库将会解析username和password然后转换为SQL字符串发送给数据库数据库引擎接收到的SQL类似
SELECT * FROM users WHERE username = fredsmith AND password = userspassword
这是一个非常标准的SQL语句无论你使用什么数据库存储用户的数据SQL语句看起来都大同小异
攻击者对SQL注入攻击非常有兴趣因为他们通过发送一些伪造数据就可以操纵数据库如传入一个无效用户名
SELECT * FROM users WHERE username = AND password =
攻击者提供一个单引号字符作为用户名一个空格作为密码数据库也表现得非常好遇到这种查询就返回一个错误消息但攻击者看到返回的错误消息后不会就此罢手而是要深入挖掘可利用的信息可能一不小心数据库就暴露了表结构这正是攻击者想要得到的东西经验丰富的攻击者可以迅速地入侵数据库
在接下来的例子中通过向username添加其它字符串来进一步欺骗数据库例如如果我们输入or email=作为用户名查询解析器将会解析为
SELECT * FROM users
WHERE username = or email= AND password =
如果数据库users表中不存在email列它可能会爆出一个错误另一方面它可能无法给出错误消息暗示缺少一列email我们需要做的是给用户输入一个email地址由于大多数机构都有一个标准的电子邮件地址结构因此很容易得到员工的名字然后使用这个名字作为SQL注入时的用户名
正如你所看到的从用户登录页面就可以很容易地构造出数据库结构有时通过猜测也可以得到数据库结构
好消息是保护数据库避免SQL注入也完全是可能的常见的措施包括过滤用户输入Cookie和URL中的单引号双引号斜线反斜线和分号等特殊字符此外数字值先转换成整数再传递给数据库
另一方面数据库活动监控解决方案通常会保护Web应用程序处于学习模式的数据库活动监控工具会自动学习应用程序的正常活动学习完后就知道哪些活动是正常的因此攻击者伪造的查询就会被诊断为可疑活动遇到这种行为数据库活动监控工具就会产生一个警告并采取适当的行动阻止非正常活动
良好的系统设计是防止SQL注入的重要方法但和数据库活动监控工具结合使用你将会更加放心