10.6.3  常见安全漏洞及防护

10.6.3 常见安全漏洞及防护

软件安全漏洞的种类繁多,为提高所介绍漏洞的代表性,下面以OWASP Top 10为例进行常见安全漏洞及防护知识的介绍。

OWASP(Open Web Application Security Project,开源Web应用安全项目)是一个开源的、非盈利的全球性安全组织,致力于应用软件的安全研究,使企业和组织能够对应用安全风险作出更清晰的决策。OWASP被视为Web应用安全领域的权威参考,被美国国家和国际立法、标准、准则、委员会和行业实务守则参考引用,同时也是国际信用卡数据安全技术PCI标准的必要组件,为欧洲网络与信息安全局(ENISA)云计算风险提供参考。此外,OWASP还是IBMAPPSCAN、HPFORTIFY等扫描器漏洞参考的主要标准。

众所周知,OWASP关注Web应用程序的安全。OWASPTop10(十大安全隐患列表)是OWASP最具权威的项目。该列表总结了Web应用程序最可能、最常见、最危险的十大安全隐患,能够帮助IT公司和开发团队规范其应用程序开发流程和测试流程,提高软件的安全性[77]。

OWASP Top 10以3年为一个周期更新一次,最新版本为2013年版,相对于2010年版的主要变化见表10-4。

10-4 OWASPTop10新旧版本比较[109]

978-7-111-51949-2-Part03-35.jpg

1.注入(Injection)

注入攻击指不可信数据作为命令或者查询语句的一部分,发送并欺骗解释器,以执行计划外的命令或未授权访问数据等,有SQL、OS、XPATH、LDAP注入等多种形式。注入攻击可导致数据丢失、崩溃、无法解释、访问拒绝和主机崩溃等,从而造成业务信息被泄露、修改和删除等损害。注入漏洞可以通过检查代码发现,但是通过测试却很难发现。

案例:SQL调用不信任数据。例如,一条查询某id用户信息的SQL语句为:String query=978-7-111-51949-2-Part03-36.jpgSELECT∗FROM accounts WHEREcustID=978-7-111-51949-2-Part03-37.jpg978-7-111-51949-2-Part03-38.jpg+request.getParameter(978-7-111-51949-2-Part03-39.jpgid978-7-111-51949-2-Part03-40.jpg)+978-7-111-51949-2-Part03-41.jpg978-7-111-51949-2-Part03-42.jpg。攻击者可在浏览器将查询“id”的值修改为“a978-7-111-51949-2-Part03-43.jpgor978-7-111-51949-2-Part03-44.jpg1978-7-111-51949-2-Part03-45.jpg=978-7-111-51949-2-Part03-46.jpg1”,如:http://example.com/app/accountView?id=978-7-111-51949-2-Part03-47.jpgor978-7-111-51949-2-Part03-48.jpg1978-7-111-51949-2-Part03-49.jpg=978-7-111-51949-2-Part03-50.jpg1;这样SQL语句中的request.getParameter(978-7-111-51949-2-Part03-51.jpgid978-7-111-51949-2-Part03-52.jpg)执行值为978-7-111-51949-2-Part03-53.jpgor978-7-111-51949-2-Part03-54.jpg1978-7-111-51949-2-Part03-55.jpg=978-7-111-51949-2-Part03-56.jpg1。上述查询语句就拼接为String query=978-7-111-51949-2-Part03-57.jpgSELECT∗FROM accounts WHERE custID=978-7-111-51949-2-Part03-58.jpga978-7-111-51949-2-Part03-59.jpgor978-7-111-51949-2-Part03-60.jpg1978-7-111-51949-2-Part03-61.jpg=978-7-111-51949-2-Part03-62.jpg1978-7-111-51949-2-Part03-63.jpg,其意义变成了从accounts表中返回所有的记录。

防护措施如下:

1)使用安全的API。避免使用解释器或者提供参数化界面的API。

2)无法使用参数化API时,使用解释器的ESCAPE语法避免特殊字符。

3)使用白名单或下拉菜单等形式,对用户输入进行规范化,加强输入数据有效性验证。

注入攻击的现象和解决方法见表10-5。

10-5 注入攻击现象和解决方法

978-7-111-51949-2-Part03-64.jpg

(续)

978-7-111-51949-2-Part03-65.jpg

2.失效的认证和会话管理(Broken Authentication and Session Management)

与身份认证和会话管理相关的应用程序功能往往实现不准确。这就导致攻击者可以采用破坏密码、密钥、会话令牌或攻击其他的漏洞去冒充其他用户的身份。

案例1:机票预订应用程序支持URL重写,把会话ID放在URL里:http://exam-ple.com/sale/saleitems;jsessionid=2P0OC2JDPXM0OQSNDLPSKHCJUN2JV?dest=ha-waii。假如该网站一个已登录的用户希望让他朋友知道这个机票的打折信息。他将此链接通过邮件发给他的朋友。如果该网站的认证和会话管理较弱,那么当他的朋友单击上面的链接时,他们也登录了该用户的账号,可以像使用自己的账号一样使用里面的信用卡付费等一切业务功能。

案例2:应用程序超时设置不当。用户使用公共计算机访问某一网站,但是离开时没有退出账号,而是直接关闭浏览器。如果该网站没有设置登录超时限制,或者超时时间限制较长,那么当另一个用户使用这台计算机访问该网站时,会发现前一用户还是登陆状态。

形成原因:

1)用户身份验证凭证没有使用加密保护。

2)用户身份验证凭证可猜测。

3)会话ID暴露在URL里。

4)会话ID没有超时限制,或者用户会话、身份验证在用户注销时未失效。

5)密码、会话ID和其他认证凭据使用未加密连接传输。

防护措施1:保护身份验证Cookie。

减少Cookie超时时间虽然不能阻止重放攻击,但确实能限制攻击者利用窃取的Cookie来访问站点的时间;使用SSL保护和传递会话身份验证Cookie,而不要通过HT- TP连接传递身份验证Cookie;对身份验证Cookie的内容进行加密,可以防止攻击者查看和修改该Cookie。

Cookie是网站为辨别用户身份,进行Session跟踪而存储在用户本地终端上的数据(通常经过加密)。使用Cookie可以完成很多功能,例如:保存用户名、密码,在一定时间内不用重复登录;记录用户访问网站的喜好(例如背景音乐、网页背景色等);网站的个性化,比如定制网站的服务等。Cookie的功能如图10-19所示。

978-7-111-51949-2-Part03-66.jpg

图10-19 Cookie功能示意图

Session在网络应用中指的是会话,是用户在浏览某个网站时从进入网站到关闭网站这段时间的会话连接。当用户打开浏览器访问网站时,服务器就会在内存中为该浏览器分配一个空间。这个空间就是Session空间,被这个浏览器独占。Session空间的默认存在时间为30min,网站也可以根据需要设定合理的存在时间。

防护措施2:限制会话寿命。

缩短会话寿命可以降低会话劫持和重复攻击的风险。会话寿命越短,攻击者捕获会话Cookie并利用它访问应用程序的时间越有限。

3.跨站脚本(Cross Site Script,也称为XSS)

跨站脚本(Cross Site Script)指的是攻击者在动态Web页面插入恶意的html代码,在用户浏览该页时,插入代码被执行,达到攻击者的特殊目的。跨站脚本分为三种类型:反射型、存储型、基于DOM型。下面用一个反射型案例来说明跨站脚本攻击的过程。

案例(反射型):某网站存在反射型跨站脚本漏洞,黑客构造一个URL:www.myemailserver.tld/cgi-bin/news.cgi?article=<script>偷取并保存cookie的脚本</script>,然后在该网站上以用户感兴趣的新闻连接为题目发布该URL,诱使受害者点击,以获取受害者Cookie,如图10-20所示。

反射型XSS的主要原因是网站对用户提交的数据检查不严,未能过滤攻击者恶意插入的html代码导致,如图10-21所示。

防护措施:

1)防范XSS的基本原则是将不可信数据和动态浏览器内容分离。

2)最佳措施是分离所有用户提交的基于html的不可信数据。

3)至少应实施完善的输入和输出检查,建议采用“白名单”方式过滤非法字符。

4.不正确的直接对象引用(Insecure Direct Object References)

所谓不安全的直接对象引用,是指已授权用户通过更改访问参数,可访问原本未授权的对象。攻击者利用该漏洞可轻易访问被参数引用的所有可用数据。

978-7-111-51949-2-Part03-67.jpg

图10-20 XSS案例(反射型)

978-7-111-51949-2-Part03-68.jpg

图10-21 反射型XSS形成原因

不正确的直接对象引用案例如图10-22所示。

在该案例中,一名恶意用户登录自己的网上银行以后,发现用户参数是6065,即上图中“acct=6065”,该用户尝试将参数更改为6066,即“acct=6066”。假如该网站对用户权限检查不严格,该恶意用户就可直接看到6066用户的账户信息了。

978-7-111-51949-2-Part03-69.jpg

图10-22 不正确的直接对象引用案例

形成原因:Web应用在生成Web页面时往往使用资源的真实命名,且不会对所有的目标访问对象检查用户权限。

防护措施:

1)使用非直接的对象引用,防止攻击者直接访问未授权的对象。可以使用下拉菜单,或将url参数进行编码,例如:http://www.a.com/userdetail.aspx?userId=ABAWEFRA,其中的“ABAWEFRA”为已经编码后的userID,攻击者无法解读其含义,也就无法尝试越权访问。

2)检查访问,对所有来自不信任源的直接对象引用必须进行访问控制检查,确认用户对对象的访问权。

5.安全配置错误(Security Misconfiguration)

安全配置是指定义、实施和维护应用程序、框架、应用程序服务器、数据库服务器、平台等的安全策略。安全配置错误可造成系统业务数据泄露、篡改,或者程序功能遭到未授权访问,甚至整个系统遭到损坏。

案例1:应用程序服务器会自动安装管理员控制台,但不会自动删除。假如默认帐户也没有改变,那么攻击者在服务器发现标准管理员页面后,会直接通过默认密码登陆,从而接管服务器。

案例2:服务器未禁用目录列表。攻击者可按目录下载编译Java类,反编译获得代码,获得访问控制漏洞。

形成原因:应用程序、框架、应用程序服务器、数据库服务器、平台等的安全配置错误。

防护措施:

1)及时修改应用程序、框架、应用程序服务器、数据库服务器、平台等设置的默认值。

2)正确处理堆栈跟踪和错误信息,保持软件更新到最新版本。

6.关键数据暴露(Sensitive Data Exposure)

许多Web应用程序没有正确保护敏感数据,如信用卡、身份证号码、手机号码等。攻击者可能会窃取或篡改这些数据以进行信用卡诈骗、身份冒用或其他犯罪。敏感数据在存放或传输过程中需要加密,在与浏览器交换时也需要采取特殊的保护措施。

案例1:密码数据库明文存储每个用户的密码。

案例2:没有对所有的页面使用SSL,尤其是用户通过验证后访问的页面。攻击者仅仅通过监视网络中传输的数据即可窃取用户的会话Cookie。然后,攻击者重放这个Cookie劫持用户的会话,访问他们的私人数据。

形成原因:处理敏感信息过程中未做到加密保存、加密传输、不缓存。

防护措施:

1)根据安全策略,明确敏感数据范围。

2)对所有的敏感数据不管在什么地方存储,包括内存、数据库、客户端等,都需要进行加密。

3)这些数据在传输时要加密,理想状况下,内部传输和外部传输都需要加密。

4)所有的加密都应采用强大的加密算法和高复杂度的密钥,并且妥善管理密钥。

7.缺少功能层面的访问控制(Missing Function Level Access Control)

大多数Web应用程序根据用户权限显示功能菜单。但实际上,应用程序的每个功能被访问时,都应在服务器端执行用户访问权限检查。如果没有这种检查,攻击者就可以伪造请求,以实现在未经适当授权时使用某些功能,尤其是有管理员权限才能使用的功能。

案例:权限蔓延。下面第一个URL需要经过授权后才能访问,第二个URL需要授权为管理员后才能访问。

http://example.com/app/getappInfo

http://example.com/app/admin_getappInfo

如果一个未授权的用户能够访问以上任意一个页面,这就是一个缺陷。如果一个用户虽然不是管理员却能够访问第二个页面,那么这也是一个缺陷。这些缺陷可能帮助攻击者去非法访问更多的管理员页面。

形成原因:

1)UI中显示了当前用户不能进行的操作,比如仅仅是禁用了某个按钮,但仍将其显示出来。

2)权限验证未覆盖到具体的功能和UI。

3)未从服务器端进行权限验证。

防护措施:

1)自动化工具不可能发现此类问题,因此,必须靠加强安全设计解决。在架构设计过程中,应建立一致的、易于分析的、能被所有业务功能调用的、业务逻辑合理的授权模块。

2)对于用户没有权限的功能菜单或按钮,不要显示给用户,也不要disable后显示给用户。在功能被执行前加入权限判断代码。

3)对主要业务函数贴上tag。例如,以下代码限制了只有“Admin”才能执行该功能。

[PrincipalPermission(Security Action.Demand,Role=978-7-111-51949-2-Part03-70.jpgAdmin978-7-111-51949-2-Part03-71.jpg)]

public void RemoveUserFromRole(string userName,string role)

{

Roles.RemoveUserFromRole(userName,role);

}

8.跨站请求伪造(Cross-Site Request Forgery,简称CSRF)

跨站请求伪造攻击迫使登录用户的浏览器将伪造的HTTP请求发送到一个存在漏洞的Web应用程序,其中包括了该用户的会话Cookie和其他认证信息,因此这些请求会被应用程序认为是用户的合法请求。

跨站请求伪造案例如图10-23所示。

978-7-111-51949-2-Part03-72.jpg

图10-23 跨站请求伪造案例

在该案例中,用户C登录了网站A并且在本地生成了该网站的Cookie。用户C在还没有退出网站A的情况下,浏览了网站B的一张图片。而这张图片已经被攻击者加入了以下恶意代码:

http://example.com/app/transferFunds?amount=1500&destinationAccount=4673243243

该恶意代码是攻击者构造的一个请求,将钱从受害者的帐户转移到他的帐户。这段代码嵌入在图像中或者是存储在各种受攻击者控制的网站iframe中,如下所示:

<imgsrc=978-7-111-51949-2-Part03-73.jpghttp://WebA.com/app/transferFunds?amount=1500&destinationAccount=4673243243978-7-111-51949-2-Part03-74.jpgwidth=978-7-111-51949-2-Part03-75.jpg0978-7-111-51949-2-Part03-76.jpgheight=978-7-111-51949-2-Part03-77.jpg0978-7-111-51949-2-Part03-78.jpg/>

用户C打开了该图片后,将自动执行这个伪造请求,从网站A的账户中将资金转账到攻击者账户中。

跨站请求伪造的形成原因如图10-24所示。

978-7-111-51949-2-Part03-79.jpg

图10-24 跨站请求伪造攻击流程图

可以看出,跨站请求伪造攻击成功的三个条件如下:

1)用户登录易受攻击网站A,会话状态[A]的保持,即用户已经获取了易受攻击网站A的信任授权。

2)用户在依然保持没有登出易受攻击网站A的情况下,访问了“第三方网站”。

3)提交的“操作”数据包(恶意代码)有效。

跨站请求伪造攻击的防护措施有四种。

1)防护措施1:验证Referer字段。在HTTP头的Referer字段记录了该HTTP请求的来源地址。比如某银行的转账是通过用户访问http://bank.test/test?page=10&userID=101 &money=10000页面完成。用户必须先登录bank.test,然后通过点击页面上的按钮来触发转账事件。当用户提交请求时,该转账请求的Referer值就会是转账按钮所在页面的URL。本例中,通常是以bank.test域名开头的地址。

如果攻击者要对银行网站实施CSRF攻击,他只能在自己的网站构造请求,当用户通过攻击者的网站发送请求到银行时,该请求的Referer是指向攻击者的网站。

要防御CSRF攻击,银行网站只需要对于每一个转账请求验证其Referer值,如果是以bank.test开头的域名,则说明该请求是来自银行网站自己的请求,是合法的。如果Referer是其他网站的话,就有可能是CSRF攻击,则拒绝该请求。

2)防护措施2:在请求地址中添加token并验证。CSRF攻击之所以能够成功,是因为攻击者可以伪造用户的请求,该请求中所有的用户验证信息都存在于Cookie中,因此攻击者可以在不知道这些验证信息的情况下直接利用用户的Cookie来通过安全验证。

抵御CSRF攻击的关键在于:在请求中放入攻击者所不能伪造的信息,并且该信息不存在于Cookie之中。

可以在HTTP请求中以参数的形式加入一个随机产生的token,并在服务器端建立一个拦截器来验证这个token,如果请求中没有token或者token内容不正确,则认为可能是CSRF攻击而拒绝该请求。

3)防护措施3:及时清除认证Cookie。CSRF攻击是有条件的,当用户访问恶意链接时,认证的Cookie仍然有效,所以当用户关闭页面时要及时清除认证Cookie,对支持TAB模式(新标签打开网页)的浏览器尤为重要。

4)防护措施4:用post替代get。重要操作不要使用get方式,要使用post方式;通过get提交的数据,用户名和密码将明文出现在URL上。

9.应用已知脆弱性的组件(Using Known Vulnerable Components)

组件(比如库文件、框架和其他软件模块)几乎总是以系统的全部权限在运行。如果一个带有漏洞的组件被利用,那么可能会造成十分严重的后果,如数据丢失或服务器接管等。应用程序使用带有已知漏洞的组件会破坏系统整体安全防护能力,可能导致由低到高的全系列漏洞,包括注入、跨站脚本等。

案例:

下面的两个存在缺陷的组件在2011年被下载220万次。攻击者通过扫描或手工分析能够识别出脆弱的组件,并加以利用。

1)Apache CXF Authentication Bypass,未能提供身份令牌,攻击者可以调用任何Web服务的完整权限。

2)Spring Remote Code Execution,在Spring表达式语言的问题允许攻击者执行任意代码、轻松地接管服务器。

形成原因:

由于系统有意无意间使用了存在缺陷的组件(自己的组件或第三方的组件,范围没有限制),导致了不可预料的各类安全问题。

防护措施:

1)识别正在使用的组件和版本(例如,插件的版本),及其所有的依赖。对于自己的组件,要加强质量管理、版本管理;对于第三方的组件,要选择知名的提供商。

2)监控这些组件的安全性(例如,随时关注CVE等漏洞公开平台),并保证他们更新到最新版本。

3)建立安全策略来管理组件的使用,如需要基于组件进行软件开发,则需要通过许可,并进行严格的安全测试。

10.未验证的重定向和转发(Unvalidated Redirects and Forwards)

Web应用程序经常将用户重定向和转发到其他网页和网站。如果程序没有对所去往的网页和网站进行适当验证,那么攻击者可以将用户重定向到钓鱼软件或恶意网站,或者使用转发去访问未授权的页面。

案例1:应用程序有一个页面称为“redirect.jsp”,它接受一个名为“URL参数”。攻击者制造以下恶意URL将用户重定向到一个恶意网站,进行网络钓鱼和安装恶意软件。

http://www.example.com/redirect.jsp?url=www.evil.com

粗心的用户会以为以上URL为www.example.com的访问链接,但实际上一旦点击后就被重定向到钓鱼网站www.evil.com。由于两个网站一模一样,用户很难发现自己实际上是在访问钓鱼网站。用户输入用户名、密码后,钓鱼网站就将其保存起来,留给后台的黑客使用。

案例2:应用程序使用路由将请求转发给该网站之间的不同部分。为此,当某个业务操作完成后,一些网页使用参数来表示用户应向哪里发送请求。在这种机制下,假如应用程序的检查机制不完善,攻击者就可以制造一个能够绕过应用程序访问控制检查的URL,到达管理员页面。例如:

http://www.example.com/boring.jsp?fwd=admin.jsp

防护措施:

1)避免使用重定向和转发。

2)如果使用,则不要涉及用户目标参数(URL)。

3)如果不能避免目标参数,确保目标参数值是有效的、授权的用户。

4)建议采用URL映射表,或者采用白名单方式。