Web应用的输入攻击及其防范

来源:互联网 发布:ubuntu终端中文乱码 编辑:程序博客网 时间:2024/04/30 19:22
一、攻击者绕过身份验证的方法

  设想有这样一个简单的用户登录程序:它通过表单获取用户名字和密码,然而把这些数据发送到服务器端,服务器端程序查找数据库并验证用户身份。这种用户身份验证方法非常常见。检查用户名字和密码时,许多开发者使用的是类如下面的代码:










  注意,在上面的代码中,程序从表单数据中提取出用户名字和密码,然后直接传递给了进行验证的函数isPasswordOK。查询数据库的SQL命令直接利用表单输入数据构造,这是一个不安全的过程。假设用户名字是“mikey”,密码是“&y-)4Hi=Qw8”,则实际查询数据库的SQL命令是:


SELECT count(*) FROM client WHERE (name='mikey') and
(pwd='&y-)4Hi=Qw8')




  当查询结果中count(*)返回合适的数值时,用户“mikey”的身份验证通过。如果count(*)返回的结果是0,则查询未能找到匹配的记录,用户被拒绝访问。

  那么,攻击者如何绕过这个验证过程呢?首先,攻击者会假定验证过程使用上面这种SQL命令进行验证,然后他们就发送伪造的用户名字和密码,改变SQL命令的判断逻辑。例如,如果攻击者输入的用户名字是“x' or 1) or ('1”,密码是“anyoldpassword”,则实际查询数据库的SQL命令将变成:


SELECT count(*) FROM client WHERE (name='x' or 1) or ('1')
and (pwd='anyoldpassword')




  可以看出,这个查询选出的行数量总是大于或等于1,即count(*)的返回结果总是1或者更大。由此,虽然攻击者并不知道合法的用户名字和密码,他总是能够通过身份验证!

  注意下面5点有助于防止攻击者绕过Web应用的身份验证过程。

二、防止错误信息泄密


  不要向浏览器返回带有出错SQL命令的错误信息。出现脚本错误时,默认情况下IIS会返回一个500-100错误信息。事实上,返回不带调试信息的错误信息更有利于安全。例如,当我们在登录表单输入伪造的用户名字和密码时,服务器返回的错误信息可能如下:


Error Type:
Microsoft JET Database Engine (0x80040E14)
Syntax error (missing operator) in query expression
'(name='x' or 1) or ('1') and (pwd=''p')'.
/login.asp, line 24




  可以看到,错误信息中包含了部分SQL命令,它会帮助攻击者改正原先的错误,为攻击者快速构造出虽然伪造、但在SQL命令中合法的用户名字和密码带来了方便。

  要减少服务器返回的错误信息量,最简单的方法是修改%winnt%/help/iisHelp/500-100.asp;或者创建一个新的文件,同时设置IIS,使得500.100错误出现时服务器返回这个新的文件。设置IIS服务器的步骤如下:


1.打开IIS管理工具
2.右击要设置的Web服务器
3.选择“属性”
4.选择定制错误的选项卡
5.输入定制的500.100错误页面文件的名字
  对于安全来说,错误信息中最好永远不要出现服务器上的物理路径。例如,返回“不能在c:/wwwroot/secretlocation目录下找到foo.doc文件”这种错误信息并不有利于安全,一个简单的404提示已经足够了。

三、确定合法性规则

  利用VBScript、JScript以及Perl语言的正则表达式,我们可以为用户输入数据定义合法性规则。不要去分析哪些输入数据非法,因为攻击者会找出绕过非法数据检查规则的办法。例如,假设为了防止用户向网站发送HTML数据,我们要替换输入数据中的“<”和“>”符号:



strInput = strInput.replace(/[<>]/,"");





  上面这个语句把“<”和“>”符号替换成空字符串。那么,是否这样一来攻击者所发送的HTML就不能再发送到服务器上了呢?答案是否定的。攻击者只需把“<”和“>”替换为相应的HTML实体符号,上述分析用户输入的代码就不能再找出HTML。由此我们认识到,正确的方法应该是先确定什么是合法的,然后验证用户输入的合法性,拒绝所有不符合合法性规则的输入:



if (strName.search(/[^A-Za-z 0-9]/) != -1) return false;





  这行代码搜索strName,如果strName包含除了大写字母、小写字母、数字和空白字符之外的(这就是^的含义)字符,则输入数据被拒绝。


  进行输入检验时还要注意伪造的文件名字。攻击者可能尝试把数据发送到某些敏感的位置,或者可能发出请求试图得到源文件,等等。下面这个正则表达式对文件名字作严格的限制。合法文件名字的规则描述如下:



●一个或者多个0-9a-zA-Z或_,再加上

●一个或者多个0-9a-zA-Z、-、/、/和_,再加上

●一个句点,再加上

●’’、’txt’、’jpg’、’jpeg’、’gif’、’htm’、’html’、’png’、’bmp’或’zip’

  所有不符合上述规则的文件名字都非法。这个文件名字规则非常严格,但确实有效。你可以看到,文件名字不能以斜杠开头,因为斜杠是磁盘的根目录。除了攻击者之外,另外还有谁需要从磁盘的根目录开始访问呢?所有对文件的访问都应该相对于Web网站的根进行:



var strInput = Request.form("filename");

var re = /^[/w]{1,}[/w/-////]{1,}/.(txt|jpg|jpeg|gif|htm|html|png|bmp|zip)

{0,1}$/i;

var fIsFilenameValid = (re.test(strInput)) ? true : false;
四、正确处理引号

  引号有时候很难处理,因为它们会干扰SQL命令。如本文开头的例子,攻击者利用引号改变SQL命令的逻辑,使得不具备合法用户名字和密码的人也能够登录系统。防止利用引号攻击的另外一种方法是事先转义引号字符。下面这个正则表达式将把所有单引号和双引号分别替换为两个单引号和两个双引号。替换得到的SQL命令完全合乎SQL语法,而且它使得许多攻击更难进行。



strPwd = strPwd.replace(/([/’/"])/g,"$1$1");





  这个语句可以替换前面加上的正则表达式。但也可以两者一起使用,加强防卫力量!

当前位置 > 技术首页 > 网站开发 > WEB服务器



Web应用的输入攻击及其防范

时间:2001/05/15 15:28 作者:仙人掌工作室 eNet技术



 

五、检查SQL查询返回的数据

  一种完全防止这类攻击的方法是停止使用只能表示“赞成、反对”的count(*),改为检查用户名字、密码是否和SQL命令返回的用户名字、密码匹配。具体代码如下所示:



var strSQL = "SELECT name, pwd FROM client WHERE " +

"(name=’" + strName + "’) " +

" and " +

"(pwd=’" + strPwd + "’)";

var oRS = new ActiveXObject("ADODB.RecordSet");

oRS.Open(strSQL,oConn);

fAllowLogon = (oRS(0).Value == strName && oRS(1).Value == strPwd)

? true : false;





  如果SQL查询没有返回数据,程序将触发一个异常,随后这个异常就被catch()捕获。

六、禁用父路径

  确保文件名字中没有出现“..”。按照如下步骤禁用父路径:



右击Web网站的根,从菜单选择“属性”。

●选择“主目录”选项卡。

●点击“配置”。

●点击“应用程序选项”。

●取消“启用父路径”。

  如果要从命令行禁用父路径,请执行如下命令:



cscript adsutil.vbs set w3svc/1/root/AspEnableParentPaths false





  要真正做到对输入攻击的全面防范,你必须有一切输入数据都可能有危险的心理准备。检查合法的输入,而不是检查不合法的输入,因为攻击者很快就可以找出突破不合法规则的办法。同时,学习并正确地运用正则表达式。记住了这几点,你就能够大大减少Web应用被侵入的机会。  
原创粉丝点击