我们在做渗透测试使用AWVS对网站进行扫描时,经常会扫描出Session Cookie without Secure flag set漏洞。由于是低危,而且很难被利用,所以我们常常会忽略掉它,不去研究它的原理关心它的细节。当真正让我们要去修复这些小漏洞时,尴尬的事情就发生了:这么不起眼的漏洞,劳资都没能正确修复!!!

0x01叙事

  在研究该漏洞原理与修复之前,先聊聊最近被这个小小小漏洞的坑死的琐事。最近负责客户网站的漏洞复测,其中就有这个不起眼的小漏洞。因为不起眼,所以平时对其原理并未深究,导致了这次被坑死。我在复测的过程中使用了firebug去查看了漏洞地址的cookie,发现没有设置cookie的HTTPOnly属性。于是就在复测报告中写复测结果为未修复。结果开发人员打电话过来说: 你复测的是访问js,图片等前端页面的请求的cookie,这些cookie自然是没有HTTPOnly属性。但涉及后台数据交互的cookie的HTTPOnly属性,所以该漏洞算是已经修复。 现在想想这种表述本身就有问题,我TMD竟然信以为真!晚上回来狠心恶补了一下该漏洞原理,才知道: 要修复该漏洞,存储sessionID的cookie一定要设置HTTPOnly属性,其他cookie的设不设置该属性,得根据网站具体的业务来确定。

  现在我再来看看那位开发修复漏洞的方式我就想笑,他直接去百度经验copy了一段代码,就粘贴过去了。连cookiename都没有修改。这回到好了,目标cookie的HTTPOnly属性没有设置,到是加了一个无用的设置了HTTPOnly属性得cookie。
图1开发人员直接copy的修复代码

图2添加的无用cookie

其实正确的修复代码是将copy过来的代码中的cookiename修改为JSESSIONID

0x02漏洞原理

  大家都知道网站的会话控制,都是使用session和cookie来配合实现。一般cookie中都存在一个sessionID,每种语言使用存储sessionID的默认cookie名称都不太一样,具体如下表:

语言 cookie名
asp ASPSESSIONID
php PHPSESSIONID
jsp JSESSIONID

  服务器同时该sessionID来识别用户。如果一旦泄露sessionID就会导致身份被窃取。一般而言黑客会使用XSS漏洞来窃取cookie。在浏览器中的documnet对象中,就存储着cookie的信息。而通过XSS漏洞使用js读取受害者浏览器中的document对象里的cookie,然后在发送到黑客指定的收信地址。

  那么我们如何去进行防护呢?也许大家想到,在客户端禁止js执行。当然这完全可以抵御XSS。但是副作用也是很大哦。一旦js被禁用了,你访问到的网页的交互性大大的降低,甚至会严重影响体验。所谓杀敌一千自损八百,实属下下策。那么我们能不能将让浏览器中的document对象里的cookie设置为不可见呢?而cookie的HTTPOnly属性就能达到这样的效果。当cookie的HTTPOnly属性被设为True时(默认为false),document对象中就找不到该cookie了。自然js无法从document获取到cookie了。这样哪怕网站存在XSS漏洞,也能在大部分情况下杜绝cookie被劫持。
图3原理图
  其实我个人理解这个属性之所以叫HTTPOnly,是说只有在只有通过HTTP协议写才能访问cookie数据,其他方式不可以。因此设置了该属性,不会影响网站的交互,正常的HTTP请求(包括Ajax)都可以携带cookie发送到服务器。

0x03漏洞修复

  根据以上原理,我们已经知道了该漏洞的修复方式。那就是在http响应头设置cookie的HTTPOnly属性为True。Set-Cookie变量具体如下:

1
2
3
Set-Cookie: <name>=<value>[; <Max-Age>=<age>]
[; expires=<date>][; domain=<domain_name>]
[; path=<some_path>][; secure][; HttpOnly]

下面我们以php语言来演示一下如何修复该漏洞。

cookie全局HTTPOnly设置

  PHP5.2以上版本已支持HttpOnly参数的设置,同样也支持全局的HttpOnly的设置,在php.ini中设置如下:

1
session.cookie_httponly = True

或者通过脚本来设置

1
2
3
4
5
6
<?php
//第一种
ini_set("session.cookie_httponly", 1);
//第二种
session_set_cookie_params(0, NULL, NULL, NULL, TRUE);
?>

cookie部分设置HTTPOnly属性

  php中Cookie操作函数setcookie函数和setrawcookie函数也专门添加了第7个参数来做为HttpOnly的选项,开启方法为:

1
2
3
4
<?php
setcookie("cookiename", "cookievalue", NULL, NULL, NULL, NULL, TRUE);
setrawcookie("cookiename", "cookievalue", NULL, NULL, NULL, NULL, TRUE);
?>

对于PHP5.1以前版本以及PHP4版本的话,则需要通过header函数来变通下了

1
2
3
<?php
header("Set-Cookie: hidden=value; httpOnly");
?>

注意:如果你的浏览器不支持HTTPOnly,那么你就算为cookie设置了该属性也是无效的!

0x04最后的思考

所有的cookie都应该加上HTTPonly属性么?

  网站中存储sessionID的cookie一定要设置。这也是AWVS为何命名该漏洞为Session Cookie without Secure flag set的原因。一般网站应用也不会在js里操作这些敏感Cookie的,对于一些需要在应用程序中用JS操作的cookie我们就不予设置。这样就保障了Cookie信息的安全,同时的保证了网站的正常业务。

HTTPOnly是否百分之百防御XSS漏洞?

  设置HTTPOnly属性只能缓解XSS之痛,但是并不能根治。

参考文章