■ 河南 郭建伟
编者按:在Web应用环境中,当用户登录后会执行一些关键性的处理操作(一旦完成则无法撤销),如在线支付、修改密码、发送E-mail等。如果在这些关键处理中存在安全问题,其危害是不可小视的。例如,跨站请求伪造(CSRF)就是针对关键处理环节进行攻击的。
对于XSS攻击来说,黑客可以盗取用户的Cookie信息,并利用其登录网站,执行常规操作(例如浏览、添加购物车等),但是却无法执行付款等关键操作。
为了防御上述攻击,在执行关键操作之前,必须确认请求是由真正的用户自愿发起的才行。如果该环节被忽视,就很容易引发安全问题。例如,当用户误入某个恶意网站后,浏览器就擅自执行修改邮箱密码等关键操作,对于此类非法操作要必须禁止。
一旦黑客利用CSRF漏洞攻击得手的话,就会利用用户账号进行在线购物、删除用户账号、随意发布信息以及非法修改用户密码等操作,给用户造成不小的危害。当然,CSRF漏洞影响仅仅限于Web应用的关键处理被恶意利用而已,对于用户的隐私信息等内容是无法盗取的。
任意网站都可能存在执行关键处理的Web页面。例如,仅仅使用Cookie进行会话管理,仅仅使用HTTP认证,SSL客户端认证以及手机移动ID来识别用户身份等网站来说,都有可能遭到黑客的CSRF攻击。
必须在关键页面添加关键性的认证,才可以有效抵御此类攻击。黑客在实施此类攻击时,经常会使用钓鱼等手法,来引诱用户点击恶意链接,使其进入恶意站点,触发黑客预设的恶意程序进行攻击。
最有效的应对策略其实很简单,就是在执行关键处理之前,一定要确认这是合法用户发起的请求。
CSRF攻击常见的有两种攻击方式,第一种攻击是输入特定的数据(例如密码)后,执行攻击操作。例如,某个合法用户已经登录了某个网站,在用户本机中就会保存相应的Cookie信息,可以保持登录的状态。黑客只需“精心”编辑一个网页,在其中内嵌访问该网站特定的页面(例如修改密码等)的语句,并将其伪装成看似合法的链接,来引诱用户点击,当合法的用户误击该链接后,黑客就可以毫不费力的自动向目标网站发送相应的POST请求,来顺利完成特定的操作(例如修改用户密码等)。
当然,黑客在发送时会附带包含会话ID的Cookie信息。应该指出,根据同源策略,从恶意网页所在iFrame的外层是无法读取到目标网站内层的信息的。
所以CSRF攻击虽然能够以合法用户的身份恶意使用目标网站的关键处理程序,但是却无法显示目标网页的内容。即便如此,如果黑客攻击得手,例如修改了用户的密码后,是可以据此登录网站,来获取更多的用户信息的。
第二种攻击方式是在上述基础上包含确认页面的攻击行为,例如,在修改密码时显示确认页面等。对于确认页面来说,将数据传送给执行页面有两种方式,即使用hidden参数和使用会话变量。所谓hidden参数,指的是类型为hidden的input元素。黑客在恶意页面中内嵌了“onload”“action”等语句,将隐藏参数通过Post方法,传递给执行页面。该隐含参数是由客户发送给目标服务器的。
为了防止上述隐含参数被修改,黑客还会使用会话变量的方式进行攻击,因为会话变量的内容是保存在服务器端的,无法被用户修改,即先让用户确认要修改的内容(例如邮箱等),之后将其内容存储到指定的会话变量中。
当用户点击了恶意链接执行提交操作时,恶意程序就可以根据用户的会话ID,从服务器端读取该变量的值,来执行关键处理操作。例如修改用户的邮箱密码等。
这种攻击手法实际上是比较狡猾的,现在逐渐成为了CSRF攻击的主要形式。黑客会在恶意网站中嵌入两个iFrame框架,其中一个的随着恶意页面的打开立即执行,会向确认页面发送包含要更改信息(例如密码)的Post请求,只要该信息就会保存到会话变量中,稍后另外一个iFrame会自动打开执行页面完成CSRF攻击动作,因为需要更改的信息已经保存到了会话变量中,所以黑客可以毫不费力的对其进行更改。
有些网站在执行更改操作时,可能会使用向导的方式,经过一系列步骤才能执行关键动作。黑客只需增加iFrame的数量,就可以很轻松的完成攻击操作。
从这个意义上说,CSRF攻击所恶意使用的关键处理程序是目标服务器提供的,XSS攻击的情形与之是不同的。
对于XSS攻击来说,当用户误入恶意站点后,其会推送恶意脚本给用户,该恶意脚本是在用户的浏览器中执行的,这样黑客就可以利用用户的浏览器执行各种非法操作。黑客甚至还可以借此向目标服务器发出恶意请求,并且将包含恶意信息的内容名反弹给黑客。
因此说,XSS攻击的危害性要比CSRF要大。要想防御CSRF攻击,最关键的方法是确认关键处理的请求是有合法的用户自愿发起的。应对方法包括筛选出需要防范CSFR攻击的页面,以及让程序具有辨认是否由合规用户资源发起的能力等。
当然,并非所有的页面都需要防御CSRF攻击,实际上大多数的页面无需防范这类攻击。例如,对在线购物网站来说,其可以通过各种链接进入网站,这便于用户自由出入,对于这些外部链接来说,是无需实施CSRF防护的。
只能对网站中诸如付款页面、用户登录、密码修改等重要环节,不能任由来历不明的用户随意操作,必须对其进行CSRF防护处理。例如,对于修改信息页面来说,常常的操作是由合法的用户输入各种信息,之后点击确认按钮执行修改动作。
CSRF攻击实际上没有经历以上操作,只是通过iFrame发送非法请求,来完成信息的修改。判断其是否合规的方法有多种,包括嵌入机密信息利用令牌进行判断,多次输入密码以及检验Referer信息等。
对于这三种攻击的防御方式来说,可谓各具特点。第一种方法对用户的操作是没有影响的,是最基本的防御策略。第二种方法增加了用户操作的复杂度,具有安全性最高的特点。这两种方式对手机网站均可以支持。对于第三种来说,如果用户的浏览器关闭了Referer功能的话,就无法发挥作用了,而且其不可应用于手机网站,只能作为辅助方式使用。
上面谈到,根据同源策略,从恶意网页所在iFrame的外层是无法读取到目标网站内层的信息的,因此可以给合法客户发送一次性的令牌(即随机数),黑客就无法读取该令牌,据此可以判断请求是否合法。
利用再次输入密码,或发送随机密码进行确认等操作,也可以有效防御CSRF攻击。因为黑客诱使用户进入恶意页面,之后才能发起CSRF攻击,从一个页面链接到另外的页面,客户浏览器会产生Referer属性值,包含源页面信息。对Referer的值进行检测,可以准确判断出是否有恶意站点链接过来的。
当访问需要保护的关键处理页面时,处于安全性考虑,需要提供第三方无法知晓的机密信息,那么即使黑客冒充合法用户发送请求的话,应用端也可以据此判断该请求的合法性。实现上述功能的机密信息就成为令牌,例如,可以将会话ID作为令牌。
例如,在页面中添加“”等语句,将会话ID作为令牌使用。这样,黑客是无法读取该令牌内容的。在接收令牌时,必须使用POST方法,例如使用“if (session_id() !==$_POST['token'])”,“{die ('该请求不合法,是可疑的攻击行为')}”等语句来读取令牌。
如果使用了GET方法发送令牌的话,就会通过客户端浏览器的Referer参数泄露出去。这样,当黑客试图发起CSRF攻击时,就会因为无法提供令牌信息就服务器拒绝。
对于合法的用户操作来说,因为可以提供正确的令牌值,所以是不会进行拦截的。对于要求不高的场合,该方法是可以满足需求的。
对于安全性要求比较高的网站来说,可以使用再次要求用户输入密码,或者向其手机发送一次性验证码的方式,来确认用户的真实身份,而且可以再次确定用户是否执行提交订单等操作。当然,不管应对哪一种CSRF攻击方式,再次输入密码进行验证必须在最后的执行页面前的那一刻进行方可,即再次要求数据密码的时机是很重要的。因为仅仅在之前的某个页面进行验证,依然可能存在CSRF漏洞的。
利用检验Referer值的方法,可以有效检测请求的原来是否合法,例如,从上一个合法页面转过来的话,是可以进行处理的。如果是从恶意网站链接过来的,则使其为非法。
在网页中嵌入诸如“if(preg_match('#/Ahttp://www.xxx.com/reque/hefa.php#',@$_SERVER['HTTP_REFERER']) !==1){die ('非法的请求');}”之类的语句,确认当前的请求中的Referer的值必须为执行页面上一个页面的地址。这里 的“www.xxx.com/reque/hefa”为假设的页面地址,表示请求必须从该地址中来的才行。在实际应用中可以根据需要进行调整,在其地址中保存了所需的PHP文件。
当然,如果将检测Referer值和检测上述令牌值的方法结合起来使用,就可以大大提高防范CSRF攻击的能力。
仅仅采用以上防御方式还是不能完全满足实际需要,在执行了关键处理操作后,最好向用户的邮箱或手机发送有关处理内容的通知信息,让用户可以在第一时间知晓相关信息,即使黑客利用XSS或CSRF方式攻击得手,用户也可以及时洞察并采取各种措施(例如冻结账户等),将损失将至最低。
注意,在通知中不要包含敏感信息,因为发送的方式(例如邮件等)可能是不加密的,让用户登录到指定的Web页面,来详细查看诸如购买记录、密码变更等详细情况。