HTTP协议头攻击

本文已发于《黑客X档案》2010.12期

就在上周,互联网发生一件重大事件,腾讯和360这两大用户量极广的公司之间发生了一场惊心动魄的激烈的冲突,至使腾讯一方做出决定——360和QQ不兼容,如果用户机器上同时安装了360和QQ,将导致QQ强行关闭。不仅如此,倘若使用360浏览器访问QQ空间,将会被阻止。不过,针对360浏览器访问QQ空间的问题网上很快出现了突破方法,也正是和本文所要讲的User-Agent有关。

User-Agent是HTTP协议请求格式的一个头域。下面来简单了解下HTTP协议。以下 是我对 http://qzone.qq.com 发出的一个HTTP请求,内容如下:

GET HTTP/1.1
Accept: application/x-shockwave-flash, image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-ms-application,application/x-ms-xbap,application/vnd.ms-xpsdocument, application/xaml+xml, */*
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)
Host: qzone.qq.com
Connection: Keep-Alive

顶部由GET和HTTP/1.1组成,GET代表请求动作的方法,表示向服务器请求一个资源;HTTP/1.1代表使用的HTTP协议版本,现在绝大多数的浏览器都使用的是1.1版本。

第一个Accept消息头代表接受介质的类型,这里可以忽略不管;Accept-Language消息头代表接受的语言种类,zh-cn表示中文;Accept-Encoding消息头表示接受编码的方式,这里使用了gzip,deflate压缩编码;User-Agent消息头则是接下来将要讲到的;Host消息头代表请求的主机,这里是qzone.qq.com。Connection消息头的值为Keep-Alive表示了浏览器与服务器保持连接。

向目标主机发送请求后会收到来自服务器的响应,由于这里不是本文重点,将不作介绍返回给浏览器的HTTP消息,如需要,请查阅相关文献。我们的重点是User-Agent消息头,注意后面跟的值似乎包含操作系统和浏览器的信息。是的,User-Agent包含了客户端的浏览器和操作系统信息。

下面,来看一个典型的WEB访问过程如图1:

1.jpg

图1

当客户端的浏览器向服务器发送一个HTTP请求后,如果发送成功,服务器则响应这个请求。而刚才的例子中向QQ空间服务器发送了一条HTTP请求,请求的内容中包含了一些关键的信息,其中User-Agent中包含了来自客户端的浏览器信息,由于360浏览器有属于自己的User-Agent(大多数浏览器都有属于自己的),QQ空间服务器收到来自客户端的HTTP请求中如果包含360浏览器的User-Agent便可禁止用户其访问,这就是其中的原理,而网上流传的突破360浏览器访问QQ空间限制的最初方法正是修改User-Agent。

我在本地的PHP环境中用一段PHP代码输出User-Agent(如何搭建PHP环境在这里省略,详细请参考相关文档),文件test.php,代码如下:

<?
    echo $_SERVER['HTTP_USER_AGENT'];
?>

然后用IE浏览器访问 http://localhost/test.php ,得到的输出结果如下:

Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)

再用360浏览器访问,得到的结果如下:

Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; 360SE)

可以看出,360输出的结果中,最后多出一项 “360SE”,当QQ空间服务器程序接受到的请求中检测到360SE字样则禁止用户的访问了。

不过这里要注意,之后360浏览器似乎在浏览器选项——“其他”里默认勾选了“统一IE和360安全浏览器的User Agent标示”,如果勾选了它,得到的结果将和IE的一样,所以需要反选此选项才会得到以上的结果。

前面说了HTTP的请求内容是来自客户端,那么作为客户端,是可以随意改变请求的内容的。我们可以通过代理服务器的方式来改变请求内容。代理服务器是介于客户端和目的服务器之间的一台服务器,当客户端浏览器设置了代理服务器地址和端口后,浏览器首先将消息发送到代理服务器,然后由代理服务器向目的服务器发送HTTP请求的,代理服务器是通过客户端发送的HTTP消息中HOST消息头来确定将要发送到的目的服务器地址的。当目的服务器响应后并返回一个请求,请求也首先返回到代理服务器,然后由代理服务器将接受到请求转发给客户端浏览器。所以代理服务器在接受到来自客户端的请求内容后是可以随意修改消息内容的(事实上它的确对消息内容做了细微的修改)。其过程如图2:

2.jpg

了解了代理服务器的运作方式后,我们完全可以自己搭建一台本地代理服务器来修改请求内容。这里所讲的本地代理服务器是指在本地运行一个代理服务器程序,然后将浏览器的代理IP设置成本机地址和指定的端口号,在访问网页发出HTTP请求时,代理服务器软件首先捕获请求,然后再将请求发送给目标服务器,在捕获到浏览器发送来的HTTP消息后,完全可以修改消息头内容后再提交给目标服务器。

这里将使用WEB安全工具中大名鼎鼎的Burp-Suite来实现本地代理服务器,在其 官方网站( http://portswigger.net/burp/download.html )下载免费版本(单击Download now)。因为Burp-Suite是基于JAVA平台的,所以需要安装JRE(随光盘附带)。安装了JRE后,运行Brup-Suite目录下的suite.bat,即可启动Brup-Suite,程序界面如图3:

3.jpg

图3

运行后Brup-Suite默认使用的代理端口号是8080,所以就不设置而直接使用。然 后用360浏览器设置代理,选择360浏览器工具栏中的“代理服务器”——“代理服务 器设置”,填入127.0.0.1:8080并确定。设置以后,再在“代理服务器”选项中勾 选添加好的“127.0.0.1:8080”,此时本地代理服务器已经设置完毕。我们再来访 问刚才的建立的test.php,浏览器中输入 http://localhost/test.php ,此时浏览器一直处于等待状态,无任何显示。而Brup-Suite却有反应了,选择“proxy”选项卡,就可以看到浏览器发送的请求内容了,如图4:

4.jpg

这时可以修改消息的任何内容,我们将User-Agent可以修改成任何内容,比如将“360SE”字样删除(当时就可以通过此方法绕过QQ空间的访问限制)。但是如果我们提交一串跨站字符呢?我们将User-Agent冒号后的内容修改成<script>alert("test")</script>后按“forward”按扭,浏览器将弹出内容为“test”的显示,如图5:

5.jpg

图5

现在很多网站(比如论坛程序)会将客户端浏览器信息写入数据库,倘若某站点没有对获得的UserAgent(PHP获得UserAgent的变量是:$SERVER['HTTPUSERAGENT'];ASP获得UserAgent对象的方法是:Request.ServerVariables("HTTPUSERAGENT")

)进行过滤而直接写入数据库并且显示在页面中,那么将存在一处攻击点。曾经动网论坛出现过一次User-Agent注入。

其实靠User-Agent来限制浏览器访问并达不到绝对效果的,因为HTTP请求的内容来自客户端,客户端是可以修改任何内容的。其次,在WEB安全编程中,应该严格过滤来自客户端数据,比如GET、POST、Cookie、User-Agent,任何来自客户端的输入不能保证是安全的,可以采用白名单的方法来验证请求的数据,即“只允许提交某些内容,其余的均为不允许”,而不是使用黑名单方式——将带有威胁的内容一一排除。比如上传漏洞中,用白名单方式过滤内容,只允许上传.jpg和.gif,其余格式均不允许的;如果用黑名单方式,将.asp、.php、.aspx等后缀列入危险黑名单中时,可能会忽略掉其中一种格式,导致漏洞产生。

同时,因为代理服务器可以接受来自客户端和服务器之间的消息,并且可以随意修改其内容,也证明了代理服务器的不安全性,那么在选择代理服务器时应该警惕代理服务器是否安全的。