10大最重要的Web安全风险之五:A5-伪造跨站请求(CSRF)
A1-注入
A2-跨站脚本(XSS)
A3-错误的认证和会话管理
A4-不正确的直接对象引用
A5-伪造跨站请求(CSRF) -- Cross-Site Request Forgery
A7-限制远程访问失败
A8-未验证的重定向和传递
A9-不安全的加密存储
A10-不足的传输层保护
一个跨站请求伪造攻击会强制一个已登录的受害者的浏览器向服务器(有缺陷站点)发送一个伪造的HTTP请求,这个请求会包括受害者的session cookie以及其他自动产生的认证信息,这会使得服务器(有缺陷站点)认为收到的受害者请求是合法请求。
攻击者:任何可能诱骗用户向系统提交请求的人。合法用户访问的任何站点或HTML页面都可能有此行为。
漏洞利用手段:利用难度一般。攻击者创建一个伪造的HTTP请求并且诱骗受害者通过图片标记(image tags)、XSS或者其他技术提交这些请求。如果受害者本身已经在系统中登录(已认证),则攻击成功。。
保护和检测机制:通过入侵检测或者代码分析可以较为容易的发现CSRF漏洞。
影响: 危害中等。存在这种缺陷的情况下,攻击者可以改变受害者有权限改变的任何数据或调用受害者有权限使用的任何功能。
如果一个Web应用允许用户提交一个未包含任何秘密(不可预测内容)的状态变更(本例中是转账)请求,如:
http://example.com/app/transferFunds?amount=1500&destinationAccount=4673243243
当攻击者构造一个请求,将受害者的帐号中的金钱进行转账,并将这个请求包含在一个其他站点的图片请求或iframe请求中,如下:
.<imgsrc="http://example.com/app/transferFunds?amount=1500&destinationAccount=attackersAcct#“width="0" height="0" />
如果受害者已经登录转账系统,并且访问了这个包含了恶意请求的链接,则这个伪造请求会包含受害者的session会话信息及其他认证信息。
最简单的检查是否应用存在CSRF缺陷的办法是,检查是否每个link或form为每个用户包含了不可预测的标记(unpredictable token)。如果没有这个不可预测标记,攻击者就可以构造恶意请求。
注意session cookie、源IP地址或其他自动产生并被浏览器发出的标记并不属于不可预测标记。因为这些信息在伪造请求中仍然存在(被浏览器自动生成发出)。
一个CSRF漏洞测试工具:
使用帮助:
https://www.owasp.org/index.php/CSRFTester
阻止CSRF的办法是,在每一个请求(body或URL)中包括不可预测的标记。标记至少应该是对每个用户的每个session是不同的,也可以是每个请求中不同。
优先选择在隐藏字段(hidden field)中传递这些标记。这样这些值就会在请求体(body of the request)中传递,避免暴露在URL中。
也可以在URL中传递,但这种方法的风险在于这些值可能因为暴露在URL中而被攻击者获取。
OWASP的 CSRF Guardcan可以用来在Java EE、.NET或者PHP应用中包含这些标记:
https://www.owasp.org/index.php/CSRFGuard
OWASP的ESAPI包括了产生和验证这些标记的API。
http://owasp-esapi-java.googlecode.com/svn/trunk_doc/latest/org/owasp/esapi/HTTPUtilities.html
https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29_Prevention_Cheat_Sheet
https://www.owasp.org/index.php/CSRFTester
跨站请求伪造,也被称成为“one click attack”或者session riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。尽管听起来像跨站脚本(XSS),但它与XSS非常不同,并且攻击方式几乎相左。XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。与XSS攻击相比,CSRF攻击往往不大流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比XSS更具危险性。
CSRF攻击通过在授权用户访问的页面中包含链接或者脚本的方式工作。例如:一个网站用户Bob可能正在浏览聊天论坛,而同时另一个用户Alice也在此论坛中,并且后刚刚发布了一个具有Bob银行链接的图片消息。设想一下,Alice编写了一个在Bob的银行站点上进行取款的form提交的链接,并将此链接作为图片tag。如果Bob的银行在cookie中保存他的授权信息,并且此cookie没有过期,那么当Bob的浏览器尝试装载图片时将提交这个取款form和他的cookie,这样在没经Bob同意的情况下便授权了这次事务。
CSRF是一种依赖web浏览器的、被混淆过的代理人攻击(deputy attack)。在上面银行示例中的代理人是Bob的web浏览器,它被混淆后误将Bob的授权直接交给了Alice使用。
下面是CSRF的常见特性:
l 依靠用户标识危害网站
l 利用网站对用户标识的信任
l 欺骗用户的浏览器发送HTTP请求给目标站点
风险在于那些通过基于受信任的输入form和对特定行为无需授权的已认证的用户来执行某些行为的web应用。已经通过被保存在用户浏览器中的cookie进行认证的用户将在完全无知的情况下发送HTTP请求到那个信任他的站点,进而进行用户不愿做的行为。
使用图片的CSRF攻击常常出现在网络论坛中,因为那里允许用户发布图片而不能使用JavaScript。
防范措施
对于web站点,将持久化的授权方法(例如cookie或者HTTP授权)切换为瞬时的授权方法(在每个form中提供隐藏field),这将帮助网站防止这些攻击。一种类似的方式是在form中包含秘密信息、用户指定的代号作为cookie之外的验证。
另一个可选的方法是“双提交”cookie。此方法只工作于Ajax请求,但它能够作为无需改变大量form的全局修正方法。如果某个授权的cookie在form. post之前正被JavaScript代码读取,那么限制跨域规则将被应用。如果服务器需要在Post请求体或者URL中包含授权cookie的请求,那么这个请求必须来自于受信任的域,因为其它域是不能从信任域读取cookie的。
与通常的信任想法相反,使用Post代替Get方法并不能提供卓有成效的保护。因为JavaScript能使用伪造的POST请求。尽管如此,那些导致对安全产生“副作用”的请求应该总使用Post方式发送。Post方式不会在web服务器和代理服务器日志中留下数据尾巴,然而Get方式却会留下数据尾巴。
尽管CSRF是web应用的基本问题,而不是用户的问题,但用户能够在缺乏安全设计的网站上保护他们的帐户:通过在浏览其它站点前登出站点或者在浏览器会话结束后清理浏览器的cookie。
影响CSRF的因素
CSRF攻击依赖下面的假定:
l 攻击者了解受害者所在的站点
l 攻击者的目标站点具有持久化授权cookie或者受害者具有当前会话cookie
l 目标站点没有对用户在网站行为的第二授权
CSRF(Cross Site Request Forgey)跨站点伪造请求,是排在OWASP Top10第5位的漏洞,它迫使已被认证的用户在Web系统上执行其所不欲的操作。这种攻击依赖于以下:
1) Web浏览器对会话相关信息的处理方式(如cookie或Http认证信息)
2) 攻击者对正确的Web系统的URL的了解;
3) 应用会话管理仅依赖于浏览器所了解的信息;
4) 一些HTML的tag会导致对http(s)资源的直接访问其中,前3点是确认系统是否存在该漏洞的主要前提,第4点则是用来帮助攻击者利用该漏洞的。
第1点:浏览器自动发送用于识别用户会话的信息,假设site是一个Web应用站点,victim是一个已经在该系统上经过认证的用户。在server的响应中,site发送一个带有代表victim身份的cookie给victim,原则上,一旦浏览器接收到了服务器发送的cookie,就会在后面对站点的访问中都带上这个cookie;
第2点:如果应用在URL中没有使用会话相关的信息,那就意味着应用的URL,它们的参数,相应的值可以被识别。
第3点:是指诸如cookie、或者是基于http的认证信息,存放在浏览器中后,就会包含在后面的每次请求中。
下面,我们用Get方法在做个例子,如果用户已经通过了认证,那么在他做下一次请求时,请求数据中会自动加上cookie
GET请求一般会有多种原因产生,
* 用户真正在访问Web系统;
* 用户在访问地址栏中切实敲入了URL;
* 用户点击了一个连接指向了这个URL;
这些调用对于系统来说是无法区别的,特别的,第三种方式相对来说是极为危险的,有很多种方法可以用来仿造连接的真实属性,连接可以被嵌入到一封邮件中,或者在某个恶意网站上,看上去这个连接好像是在访问另一个网站,而事实上却是被引到了Web系统的访问上。如果用户点击了连接,由于它已经被系统认证通过了,浏览器就会对系统提交一个待用认证信息的GET请求。这就在系统上完成了一个操作(尽管这个操作不是用户本身所期望做的)。
攻击者还可以通过Web的一些标记,注入img来达到这个目的。举个例子,假设攻击者发给用户一封邮件,引诱用户访问了一个URL,而这个URL的页面含有下面的HTML:
<html><body> |
那么用户在点击这个URL时,浏览器将会做什么呢,它将会尝试显示一个宽度为0的图片,而事实上这是访问了www.company.example/action,显然如果浏览器并没有阻断下载img的图片,那么该动作就会执行了。
该问题的存在是基于以下一些事实:
* 有一些HTML的tags可能会执行一些脚本(如img)
* 浏览器本身并不能识别img这个tag里的值是否是真实合法的图片
* 不管图片是否是在网站本地或是其他网站,图片都会被下载
举个例子:
假设用户要登录到某个防火墙web管理系统,登录时,用户必须对系统进行身份验证,所以用户的会话信息会保存在cookie中。假设我们的防火墙管理系统允许认证过的用户根据防火墙规则的排号来删除规则(甚至允许用户输入“*”来删除所有的规则),那么下一步显示的就是删除页面,假定表单下面就会提交一个GET请求,是以如下的格式:
https://[target]/fwmgt/delete?rule=1
或https://[target]/fwmgt/delete?rule=*
我们举的例子很简单,仅仅是为了说明CSRF的存在。
那么,如果用户输入了“*”,然后按取了Delete键,那么就提交了如下的GET请求,
https://www.company.example/fwmgt/delete?rule=*
同时就删除了所有的防火墙规则。
显然,如果用户直接在地址栏中输入https://[target]/fwmgt/delete?rule=*,或者通过某个链接转接到这个url,或者如上面所说,把链接隐藏在img这个tag后面,诸如此种方法,如果用户在点击这个连接的时候,已经登录进了防火墙管理系统,显然这个访问就能成功奏效,从而达到了删除所有规则的目的。
让我们想象一下,如果这样的攻击用于一些敏感系统,竞拍系统,或者是银行转账等等,所造成的后果将会多大。
应对方法:
对于用户来说,由于CSRF漏洞极为普遍,所以在我们的日常使用中要注意以下几点:
* 保证系统使用完就注销登录的习惯;
* 不要使用浏览器的保存用户名/密码的功能,不要使用网站的“记住我”功能
* 不要使用同一个浏览器浏览普通网页和你的关键性Web系统
对于开发人员来说,如上所述,由于将会话相关的信息放入了URL才造成了上述的问题,那么如果我们在URL层面增加会话特定的信息,那么对攻击者来说就增加了了解URL结构的难度。另外,我们还可以尽可能的使用POST,而不是GET;尽可能多的增加一些诸如“你确定要这样做吗?”的页面等……
说到这,想必大家都已明白CSRF是什么了,下面我们来看下针对这个漏洞,作为测试人员该如何去测试。
一般的测试用例应该如下构建:
1. 假设u是需要被测试的URL,例如u =http://www.example.com/action;
2. 构建一个包含了访问上述URL信息的html页面;
3. 确保合法用户已经登录了系统;
4. 诱使该用户在自己不知情的情况下访问上述URL;
5. 确认是否执行了该操作。