如果你每天访问的网站需要登录,那么你的登录用户名和密码很可能是保存在关系数据库中,其他网站用户的登录信息也和你一起保存在数据库中,但愿你的密码保存前经过加密处理,如果是明文存储的话简直太可怕了。
  不幸的是,有一些网站存在安全漏洞,***者可以通过一种叫做SQL注入的***技术窃取到存储在数据库中的密码信息。
  更令人担忧的是,即使数据库打上所有补丁也不能避免这种***,这不是一个补丁问题,更多的与数据库工作方式及系统设计有关。
  这种***可以针对任何包含来自数据库的数据的网页,如一个搜索页面,客户意见反馈页面,不管数据库是MySQL,SQL 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=’345作为用户名,查询解析器将会解析为:
 
SELECT * FROM users

  
WHERE username = ' ' or email = ' 345 ' AND password = ' '
 
  如果数据库users表中不存在email列,它可能会爆出一个错误,另一方面,它可能无法给出错误消息暗示缺少一列email,我们需要做的是给用户输入一个email地址,由于大多数机构都有一个标准的电子邮件地址结构,因此很容易得到员工的名字,然后使用这个名字作为SQL注入时的用户名。
  正如你所看到的,从用户登录页面就可以很容易地构造出数据库结构,有时通过猜测也可以得到数据库结构。
  好消息是,保护数据库避免SQL注入也完全是可能的。常见的措施包括过滤用户输入,Cookie和URL中的单引号、双引号、斜线、反斜线和分号等特殊字符,此外,数字值先转换成整数再传递给数据库。
  另一方面,数据库活动监控解决方案通常会保护Web应用程序,处于学习模式的数据库活动监控工具会自动学习应用程序的“正常”活动,学习完后就知道哪些活动是正常的,因此***者伪造的查询就会被诊断为可疑活动,遇到这种行为,数据库活动监控工具就会产生一个警告,并采取适当的行动阻止非正常活动。
  良好的系统设计是防止SQL注入的重要方法,但和数据库活动监控工具结合使用,你将会更加放心。