攻击动机可能有很多种,但乍一看好像种类更多。这是非常正确的-如果恶意用户找到执行多个查询的方法。如果您的脚本正在执行SELECT命令,攻击者可以强制显示表中的每一行-通过在WHERE子句中注入诸如“1=1”的条件,如下所示(其中,注入的部分以粗体显示):SELECT*FROMwinesWHEREvariety='lagrein'OR1=1;'正如我们之前讨论的,这本身就是有用的信息,因为它揭示了表的一般结构(普通记录无法做到这一点),并可能揭示包含秘密信息的记录。更新指令可能具有更直接的威胁。通过在SET子句中放置其他属性,攻击者可以修改正在更新的记录中的任何字段,例如以下示例(注入部分以粗体显示):UPDATEwinesSETtype='red','vintage'='9999'WHEREvariety='lagrein'通过在update命令的WHERE子句中加入常量true条件如1=1,可以将这个修改范围扩展到每条记录,比如下面的例子(其中,注入部分以粗体显示):UPDATEwinesSETtype='red','vintage'='9999WHEREvariety='lagrein'OR1=1;'最危险的命令可能是DELETE——这不难想??象。注入技术与我们已经看到的一样——通过修改WHERE子句来扩大受影响记录的范围,例如下面的例子(其中,注入部分以粗体显示):DELETEFROMwinesWHEREvariety='lagrein'OR1=1;'其次,多查询注入多查询注入会增加攻击者可能造成的潜在破坏——通过允许在单个查询中包含多个破坏性指令。当使用MySQL数据库时,攻击者可以通过在查询中插入一个意外的停止字符来轻松实现这一点——注入的引号(单引号或双引号)符号期望变量的结尾;然后用分号停止命令。现在,可以将额外的攻击命令添加到现在停止的原始命令的末尾。最终的破坏性查询可能如下所示:SELECTFROMwinesWHEREvariety='lagrein';GRANTALLON.*TO'BadGuy@%'IDENTIFIEDBY'gotcha';'此注入将创建一个新用户BadGuy并赋予其网络权限(所有表的所有权限);与此同时,一个“不祥”的密码被添加到这个简单的SELECT语句中。如果您按照我们在上一篇文章中的建议严格限制进程用户的权限,那么这应该不起作用,因为Web服务器守护进程不再具有您撤销的GRANT权限。但从理论上讲,这样的攻击可以让BadGuy可以自由地对您的数据库做任何他想做的事。至于这样的多查询会不会被MySQL服务器处理,结论并不唯一。部分原因可能是MySQL版本不同造成的,但大部分是多查询存在的方式造成的。MySQL的主管程序完全允许这样的查询。常用的MySQLGUI-phpMyAdmin,在最终查询之前复制了所有以前的内容,并且只这样做了。但是,注入上下文中的大多数多个查询都是由PHP的mysql扩展管理的。幸运的是,默认情况下不允许在一个查询中执行多条指令;尝试执行两条指令(如上面所示的注入)只会失败——不会设置错误,也不会生成任何输出信息。在这种情况下,虽然PHP只是实现了它的默认行为“well-behaved”,但它确实可以保护你免受大多数简单的注入攻击。PHP5中新的mysqli扩展(参见http://php.net/mysqli),和mysql一样,本身不支持多查询,但是它提供了一个mysqli_multi_query()函数来支持你完成多查询——如果你真的想要去做吧。然而,SQLite的情况更加糟糕-与PHP5捆绑在一起的可嵌入SQL数据库引擎(参见http://sqlite.org/和http://php.net/sqlite),由于其易用性而备受关注.引起了众多用户的关注。在某些情况下,SQLite默认允许这样的多命令查询,因为数据库可以优化批量查询,尤其是非常高效的批量INSERT语句处理。但是,如果查询的结果被您的脚本使用(例如,在使用SELECT语句检索记录的情况下),则sqlite_query()函数不允许执行多个查询。三、INVISIONPowerBOARDSQL注入漏洞InvisionPowerBoard是一个知名的论坛系统。2005年5月6日,在登录代码中发现SQL注入漏洞。它是由GulfTechSecurityResearch的JamesBercegay发现的。登录查询如下:$DB->query("SELECT*FROMibf_membersWHEREid=$midANDpassword='$pid'");其中,成员ID变量$mid和密码ID变量$pid在my_cookie()函数中检索到的以下两行代码中使用了:$mid=intval($std->my_getcookie('member_id'));$pid=$std->my_getcookie('pass_hash'); 这里,my_cookie()函数使用以下语句从cookie中检索请求的变量:returnurldecode($_cookie[$ibforums->vars['cookie_id'].$name]);[注意]cookie返回的值根本不被处理。虽然$mid在查询中使用之前被强制转换为整数,但$pid保持不变。因此,它很容易受到我们之前讨论的注入类型的影响。 因此,通过如下修改my_cookie()函数可以暴露此弱点:(urldecode($_cookie[$ibforums->vars['cookie_id'].$name]));}else{returnurldecode($_cookie[$ibforums->vars['cookie_id'].$name]);}之后这样的更正,关键变量在“通过”全局clean_value()函数后返回,而其他变量不被检查。现在,既然我们对什么是SQL注入,它的注入原理,以及这种注入的漏洞有了大致的了解,那么下面我们就来讨论一下如何有效的防范它。幸运的是,PHP为我们提供了丰富的资源,因此我们可以有足够的信心预测,使用我们推荐的技术仔细彻底构建的应用程序将基本上消除脚本中SQL的任何可能性。注入-通过在用户数据造成任何损害之前“清理”用户数据来完成。
