访问控制、防火墙、入侵检测系统,以及入侵防御系统组成了一个完整的应用程序安全防线,向应用程序提供了全方位的保护。但是,这些机制并不能百分之百地防御网络应用程序攻击。因为这些应用程序是基于网络的,网络用户与应用程序进行的通讯支持直接的网络攻击,使得已建立的安全防线保护形同虚设。攻击者意识到了这一点,因此直接的网络应用程序攻击是当前大多数网络攻击类型。
为了平衡这种状况,应用程序开发人员必须有意识来建立防御攻击的策略。他们必须要考虑一些构成一系列网络攻击方式的因素:
大多数的网络应用程序开发人员都不是安全方面的专家,也不会意识到大多数存在的问题。
许多开发人员都不会意识到网络应用程序开发中的最佳安全实践方式。
功能通常最受人重视,而安全性问题都会在最后才会得到处理。
部署网络应用程序的环境通常都会发生变化,包括应用程序代码自身的更新,以及基础设施的变化。有一些更改没有受到安全领域专家的足够重视。
如果每一个应用程序开发人员都考虑以下因素的话,那么他们可以写出更好的代码。
得到培训。
查找建立的模式。
将测试集成到开发计划之中。
及早报告漏洞的存在。
本文旨在帮助一些开发人员和部署人员,处理一些影响到 Web 2.0 应用程序的常见网络应用程序安全问题。文中还提供了一些关于移动设备特定安全性问题的介绍。
常见的网络漏洞
移动网络应用程序所遇到的网络安全性问题与桌面网络应用程序所遇到的情形很类似。学习更多关于这些问题和反制措施的资源库是 Top 10 Project on the Open Web Application Security Project(OWASP)网站(参见 参考资料)。
接下来的部分介绍了开发人员必须理解的顶级问题。
跨网站脚本
在这种一般的攻击中,恶意代码会植入到第三方的受信网站之中。如果 HTTP 请求可以将其注入到最终 HTML 页面上的话,那么跨站点脚本漏洞就向这种攻击开放了。
例如,一项服务会接受名为 image 的参数,来接受来自于文件系统的图片,来执行一些处理:
http://somedomain/myImageProcessor?image=myimage.jpg
一个入侵者可以通过向 image 参数插入 JavaScript 代码,来占用该应用程序。其意图是耗尽错误处理系统的资源。如果一个包含恶意脚本的出错信息会被生成的话,那么入侵者就可以利用这一点了:
http://somedomain/myImageProcessor?image=myimage.jpg
如果出错信息返回图片参数的内容,而不用筛选的话,那么代码就会封闭到 作为搜索关键字输入时的结果。脚本代码会在搜索结果中显示出来,代码会得到执行,而警告窗口也会显示出来。
图 3. 输入“JavaScript”作为 JavaScript 执行中的搜索词语结果
反制措施
按照下面的方法来避免跨网站脚本(XSS):
不要向用户显示不受信任的输入。
采取措施预处理输入与输出,以删除恶意代码,例如筛选或者 白板列表(定义什么是允许输入的,什么是不允许输入的)。
Encode 输出以避免浏览器执行。
对于 Altoro Mutual 来说,一个简单的修复操作将不会返回搜索结果。
为了进一步深入讨论跨网站脚本以及预防措施,您可以阅读 developerWorks® 文章“IBM Rational AppScan:跨站点脚本攻击深入解析”,或者在 Open Web Application Security Project(OWASP)培训页面上了解到关于跨网站脚本的内容。(参见 参考资料 以得到资源的链接)。
SQL 注入
这种攻击同样关注于找到请求的缺点,然后向网络呈现的输入区域插入一个 SQL 条目。能够插入查询作为输入区域一部分的入侵者可以轻松绕过一个网站的认证机制,并访问数据库。这种攻击,与跨网站脚本一起已经泛滥了。
这种范例向您展示了怎样使用 SQL 注入来耗尽一个结构糟糕的登录应用程序:
一个网络应用程序会催促您输入一个用户名和密码来进行登录,而 SQL 语句是按照下面的方式组织的:
String query = "SELECT * FROM users WHERE user ='"username+"' AND password ='"passwd"'";
变量 username 以及 password 没有得到细致的处理,并分配给用户在应用程序中输入的值。这就使得一些恶意的用户可以输入 username 之类的值:
anything' OR 1=1 --
密码可以是任意值。在这种情况下,假设它是一个星号:*。
对于输入来说,当代码替换 username 以及 password 变量时,结构化的查询是:
SELECT * FROM users WHERE username ='anything' OR 1=1 -- AND password ='*'
该语句解释了密码需求,并插入状况 1=1,这条语句的值一直都是真的。就算没有相关的权限,攻击者也会被确认为一个有效的用户。
这种攻击在 Altoro Mutual 网络应用程序进行了演示(参见图 4)。切换至登录页面,并输入 anything' OR 1=1 -- 的用户名以及任意的字符作为密码,就可以作为管理员登录了(图 5)。该账户有控制其他用户账户的权限。
图 4. 尝试用任意的一个用户名以及一段 SQL 代码作为密码进行登录
图 5. 执行 SQL 注入攻击之后攻击者作为管理员登录
就像跨网站脚本一样,这种攻击是糟糕的或者根本不存在的输入检验和确认系统造成的结果。
反制措施
您可以执行以下操作以防御这种攻击:
不信任来自用户的所有输入。
采取措施来检验用户的输入,例如筛选或者白板列表。
在 Altoro Mutual 案例中,一个可能的解决方案是筛选来自 Username 与 Password 区域的非字母数字字符。
如果您想要得到更多关于 SQL 注入以及可能反制措施的信息,您可以阅读 OWASP 培训页面以了解 SQL 注入(参见 参考资料)。
信息泄露
一个有意志的攻击者可以通过识别缺点来研究一项应用程序。例如,一个攻击者可以按照不同的方式来获取信息:
手动研究应用程序以做到隐藏的目录
系统性地收集例外情况,以查看应用程序是否给出了详细的例外情况
扫描 HTML 以得到揭示应用程序基础及行为具体内容的注释
系统性地输入用户名以找出已存在的账户
Altoro Mutual 应用程序会在系统之中泄露已存在的用户名。例如,在图 6 中,输入一个不正确的用户名和密码会产生这种出错信息:“登录失败:抱歉,在我们的系统中找不到该用户名。请重新尝试。”
图 6. 应用程序清晰地声明系统中没有做到该用户
接下来,入侵者会尝试用户名 jsmith,而 Altoro Mutual 网络应用程序会收到以下的信息:“登录失败:您输入的密码无效,请确认后重新输入密码”。于是,入侵者从以上信息上了解到有一个用户账户名为 jsmith。在此基础之上,入侵者可以把注意力放到破解密码上面,或者使用暴力破解方法来发现密码。
图 7. Altoro Mutual 应用程序泄漏了用户名 jsmith 的存在
在这种情况之下,修复方法可以是产生一种通用的登录信息,不会精确地指出什么地方没有输对,例如:“登录失败:用户名或者密码无效。请确认后重新输入您的信息”。
反制措施
对于应用程序来说,信息泄漏需要受到人们的重视,开发人员的意识是最好的防御手段。记住这一点,开发人员可以考虑一些减轻问题的措施。
所有评论的清晰 HTML 代码会揭示应用程序的实际情况。
不要在浏览器中显示特定的例外。如果必须登录,将它们存储在服务器上,并显示常见的错误。
不要揭示哪一部分的认证错误。
同样,配置网络服务器和应用程序服务器设置,以避免在网站和应用程序上任意的导航。
这种类型的信息泄漏不会再耗费您的精力了。查找特定应用程序和运行环境存在的其他泄漏问题。
您可以在 OWASP 培训页面上找到关于信息泄漏的更多信息。
参数干扰
这些类型的攻击旨在控制传递给应用程序的参数。想象一下一段糟糕的应用程序让客户来设置要购买商品的价格。这一应用程序可以发送以下的请求:
http://somedomain/myStore?item=1234&price=$200
如果业务逻辑并不会在服务器端执行任何类型的双重-检查的话,那么入侵者可以更改价格,以更低的价格买到商品。在这种情况下,允许从客户端更改价格显然是一个 bug。
反制措施
为了解决这一特定示例中的问题,您可以更改代码以从服务器的数据库端获得价格的信息,避免价格控制问题的产生。