一般Web程序在设计时,开发者对HTTP请求中包含的信息过份信息,没有进行相关验证处理导致攻击者可在HTTP请求中添加各种攻击向量,对正常请求参数进行污染等。
1. HTTP响应分割
1.1. 漏洞描述
HTTP响应头拆分攻击是一种新型的Web攻击方式,它产生了很多安全漏洞,如Web缓存感染、用户信息涂改、窃取敏感用户页面、跨站脚本漏洞等。
1.2. 漏洞成因
这种攻击方式与其衍生的一系列技术的产生,是由于Web应用程序未对用户提交的数据进行严格过滤和检查,导致攻击者可以提交一些恶意字符,如对用户输入的CR 和LF字符没有进行严格的过滤。
1.3. 风险评估
HTTP响应头拆分攻击本质是:攻击者可以发送一个或几个HTTP指令使服务器产生攻击者想得到的输出。攻击者构造的HTTP指令使服务器误把几条HTTP请求看成一条完整的HTTP请求来解释。如果攻击者可以控制第一条请求的部分内容,而且完全控制着第二条及后面的HTTP请求,即从HTTP状态行一直到HTTP请求的尾部,攻击者会发送多个HTTP请求指令到目标系统,例如第一条请求指令使得服务器完全接受两个HTTP请求,第二条请求通常是在服务器上请求一些非法资源,而服务器将会自动匹配到第二条请求的响应,并输出攻击者想要请求的资源,从而达到攻击目的。
漏洞风险等级:建议中
1.4. 测试方法
CR和LF两个字符的编码如下:
CR = %0d = r
LF = %0a = n
下面以java为例分析HTTP响应头拆分攻击的原理,如jsp页面(/test.jsp),如下:
<%
response.sendRedirect("index.jsp?lang="+request.getParameter("lang"));
%>
定义lang=en,访问test.jsp,服务器返回302,重定向到另一个地址,HTTP响应内容如下:
HTTP/1.1 302 Moved Temporarilyrn Date: Wed, 1 Mar 2005 12:53:28 GMTrn Location: http://192.168.0.1/index.jsp?lang=enrn Content-Type: text/htmlrn Connection: Closern <html><head><title>302 Moved Temporarily</title></head>rn <body>rn <p>This document you requested has moved temporarily.</p>rn </body></html>rn |
lang所赋的值被嵌入在Location响应头中。如果服务器未限制lang参数或者校验,攻击者可以修改en参数来迫使服务器返回两个响应,将lang赋值成以下内容:
en%0d%0aContent-Length:%200%0d%0a%0d%0aHTTP/1.1%20200%20OK%0d%0aContent-Type:%20text/html%0d%0aContent-Length:%2024%0d%0a%0d%0a<html>Test page</html> |
再次访问test.jsp页面时,HTTP响应内容如下:
HTTP/1.1 302 Moved Temporarilyrn Date: Wed, 1 Mar 2005 15:26:41 GMTrn Location: http://192.168.0.1/index.jsp?lang=enrn Content-Length: 0rn
HTTP/1.1 200 OKrn Content-Type: text/htmlrn Content-Length: 24rn
<html>Test page</html>rn Content-Type: text/htmlrn Connection: Closern <html><head><title>302 Moved Temporarily</title></head>rn <body bgcolor="#FFFFFF">rn <p>This document you requested has moved temporarily.</p>rn </body></html>rn |
标红部分是lang参数的值,从上述HTTP响应中可以看出,该响应包含了两条HTTP响应,一个是302,一个是200,请求test.jsp页面,浏览器匹配HTTP/1.1 302响应。
浏览器接收到HTTP响应后解析到Content-Length: 0,认为响应内容已经结束,然后请求重定向URL地址http://192.168.0.1/index.jsp?lang=en,HTTP请求内容如下:
GET http://192.168.0.1/index.jsp?lang=en HTTP/1.1 Host: 192.168.0.1 User-Agent: Mozilla/5.0 (Windows NT 6.2; rv:20.0) Gecko/20100101 Firefox/20.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate Referer: http://192.168.0.1/index.jsp Connection: keep-alive |
针对上述的HTTP请求,浏览器会自动匹配之前收到的第二个响应HTTP/1.1 200,攻击者利用此漏洞可控制第二条响应的内容,从而达到欺骗用户的目的。
1.5. 加固方法
1.限制用户输入的CR和LF,对CR和LF字符正确编码后再输出,以防止攻击者注入自定义的HTTP头;
2.限制输入URL的长度。
2. HTTP参数污染
2.1. 漏洞描述
依据不同Web服务器对同名参数的处理方式攻击者可根据其特性对参数进行覆盖,绕过应用检测。
2.2. 漏洞成因
使用同名参数对原参数进行污染,应用在检测时只检测第一个参数是否符号要求,因此可利用同名参数构造攻击脚本,参数污染通常用于sql注入绕过WAF检测。
2.3. 风险分析
不同Web服务器对同名参数的处理方式如下图所示:
攻击者可根据其特性对参数进行覆盖,绕过应用检测。
漏洞风险等级:建议高
2.4. 测试方法
在请求中添加同名参数,并在添加的参数中输入恶意构造的语句。例如:
http://www.xx.com/index.php?id=1&id=2%20union%20select%201,2,3,current_user,
利用该漏洞进行sql注入绕过可参考80sec发布的《浅谈绕过waf的数种方法》。
2.5. 加固方法
应用程序应正确过滤用户输入(过滤所有参数),以防止此漏洞。
3. Host头攻击
3.1. 漏洞描述
Web应用程序获取网站域名一般是依赖HTTP Host header(比如在JSP里通过request.getHeader()获取),这里的header很多情况下是不可靠的。攻击者恶意利用HTTP Host header会导致HTTP Host头攻击发生。
3.2. 漏洞成因
系统未对Host头进行相关检测验证,无条件信息
3.3. 风险评估
大部分的Web应用程序未经html编码直接把header输出到了页面中。比如:<link href=http://request.getHeader(“Host”) >。
有些URL中还包含有secret key和token,如:
<ahref="http://request.getHeader(“Host”)token=topsecret">。
这样处理header一般会产生两种常见的攻击:缓存污染和密码重置。缓存污染是指攻击者通过控制一个缓存系统来将一个恶意站点的页面返回给用户。密码重置这种攻击主要是因为发送给用户的内容是被污染的,即间接的劫持邮件。
漏洞风险等级:建议中
3.4. 测试方法
.密码重置污染攻击,点击重置密码的链接时,url::abs_site 这一部分使用的Host header是来自用户重置密码的请求,那么可以通过一个受他控制的链接来污染密码重置的邮件,例如替换host:当然这种攻击方式一定要能骗取用户点击访问这个受污染的链接,如果用户警觉了没有点击,那么攻击就会失败
> POST /password/reset HTTP/1.1 > Host: evil.com > ... > csrf=1e8d5c9bceb16667b1b330cc5fd48663&name=admin |
通过Host header来污染缓存的攻击方法:
因此为了能使缓存能将污染后的response返回给用户,我们还必须让缓存服务器看到的host header 和应用看到的host header 不一样, 比如说对于Varnish(一个很有名的缓存服务软件),可以使用一个复制的Host header。Varnish是通过最先到达的请求的host header来辨别host的,而Apache则是看所有请求的host,Nginx则只是看最后一个请求的host。
这就意味着你可以通过下面这个请求来欺骗Varnish达到污染的目的
> GET / HTTP/1.1 > Host: example.com > Host: evil.com |
利用web漏洞扫描工具进行检测。
如果是php的话不要用SERVER_NAME,apache和Nginx通过设置虚拟机来纪要非法header
3.5. 加固方法
1.服务器方面:
由于http请求的特点,host header的值其实是不可信的。唯一可信的只有SERVER_NAME,这个在Apache和Nginx里可以通过设置一个虚拟机来记录所有的非法host header。在Nginx里还可以通过指定一个SERVER_NAME名单,Apache也可以通过指定一个SERVER_NAME名单并开启UseCanonicalName选项。建议两种方法同时使用。
Varnish很快会发布一个补丁。在官方补丁出来前,可以通过在配置文件里加入:
import std; sub vcl_recv { std.collect(req.http.host); } |
2.应用方面:
在网站安装和初始化的时候,要求管理员提供一个可信任的域名白名单。如果这个实现起来比较困难,那至少也要保证使用使用getServerName()代替getHeader(“Host”)。
http://shop.cib.com.cn//?m=product&s=detail&id=457 存在注入
原文始发于微信公众号(LSCteam):HTTP攻击
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论