HTTP请求走私-新方法

2019年10月7日,PortSwigger研究总监(BurpSuite制造商)发布了有关HTTP请求走私的新方法的研究 。 在他们的帮助下,他获得了大约7万美元的漏洞奖金。 在本文中,我们简要地找出了攻击的本质,工具以及研究易受此漏洞攻击的Web服务器的方法。


什么是HTTP请求走私


HTTP请求走私-一种旨在使Web服务器的前端与Web服务器的后端不同步的攻击,从而攻击者可能通过走私服务器将HTTP请求走私。 原始文章中的图片很好地演示了这一点:


图片


此类攻击可能导致多种后果-在其他用户的会话中引入XSS,将用户重定向到第三方资源,毒害服务器缓存,与SSRF的相似性以及许多其他问题。


在2019年的2019走私化身中,James Kettle利用了错误的Web服务器头处理


Transfer-Encoding: chunked 

指示消息正文将分部分传输( RFC )。 由于某些Web服务器不支持分块传输或以不同方式处理标头,因此前端将仅“看到”一个请求,而后端会将其识别为两个请求。 有关攻击详细信息的更多详细信息可以在原始文章中找到,还有一项实际任务,您可以在该任务上练习手动查找漏洞。


为了快速搜索,James开发了BurpSuit 插件 ,该插件接收输入请求,并在输出处创建有关服务漏洞(如果有)的注释。


易受攻击的Web服务器的示例


我必须说,与Web服务器操作相关的走私和其他漏洞问题早已由另一个研究人员以昵称regilero来解决 。 在过去的三年中,他发表了三篇文章,描述了他在流行的Web服务器中发现的漏洞,其中大部分都被分配了中高危CVE。 易受攻击的服务器包括Apache Traffic Server,Jetty,Apsis。


在对该问题产生兴趣之后,另一位研究人员Nathan Davison 发现了 HAProxy中的一个漏洞,该漏洞忽略了格式错误的标头。


 Transfer-Encoding:[\x0b]chunked 

并将其转换为以下形式:


 Transfer-Encoding: chunked 

但是后端服务器-gunicorn,在Flask上代理应用程序,读取了标头,这激起了该漏洞。


不久之后,许多其他研究人员在http服务器golang的实现中发现了一个漏洞 (分配为CVE-2019-16276)-如果prelet前面有空格,则服务器会对标头进行标准化。
要求:


图片


由服务器处理后:


图片


如果前端服务器忽略带有空格的标头,并使用Content-Length来计算请求的大小,则可以利用此漏洞。


用Go语言编写的Caddy Web服务器也很容易受到攻击,因为它使用了相同的net / http库。 开发人员确认 ,在更新GO并重建软件包后,问题消失了。


本文的作者在lighthttpd服务器中发现了类似的问题 (未分配CVE)。 屏幕快照显示服务器接受并处理包含空格的标头:


图片


开发人员不太同意RFC 7230(作者也是如此),并且认为对标头进行不正确处理的责任在于代理,这些代理转发请求而不进行规范和检查。 但是,该错误将在新版本中修复:


默认情况下,lighttpd解析(并规范化)请求,然后再将其反向代理到后端。 这样做可以阻止https://portswigger.net/research/http-desync-attacks-request-smuggling-reborn中提到的针对lighttpd上游服务器的攻击。
但是,如上面的stbuehler所述,lighttpd下游的代理可能会将任何内容传递给lighttpd。
在下一版的lighttpd中所做的更改将是拒绝在字段名之后和冒号之前使用空格或制表符的请求,但仅当在严格的HTTP标头解析的(默认)模式下配置了lighttpd时。

在cherrypy框架使用的cheroot Web服务器中发现了相同的错误。 这种微型框架可在初创公司中找到,通常用于编写API。 错误报告挂起处于打开状态。


脆弱性的充要条件


因此,检查和利用此漏洞的必要条件是什么:


  • POST请求。 尽管RFC没有明确禁止对GET请求使用Content-Length和Transfer-Encoding头,但实际上它们仅在POST请求中使用。
  • 前端和后端服务器的存在-如果没有,则没有任何要同步的内容。
  • Web服务器必须以不同的方式解析Transfer-Encoding标头,即,一个必须“读取”它,而第二个应被忽略。

实验室测试


为了更好地理解现有Web服务器和代理并对其进行故障排除,明智的是使用Docker在本地部署测试环境。


测试环境图的示例:


图片


申请代码:


 from flask import Flask, request, jsonify app = Flask(__name__) @app.route('/', methods=['GET', 'POST']) def main(): # the next line is required for Transfer-Encoding support in the request request.environ['wsgi.input_terminated'] = True headers = {} for header in request.headers: headers[header[0]] = header[1] print (request.data) print (headers) return jsonify(body=str(request.data), headers=headers) 

具有前端设置的文件,例如caddy:


 localhost:80 log ../access.log proxy / host.docker.internal:8888 

然后一切都变得简单,运行应用程序:


 gunicorn --keep-alive 10 -k gevent --bind 0.0.0.0:8888 -w 4 backend:app 

和容器:


 docker run -d -t --name caddy -p 80:80 -p 443:443 -v /Users/sun/work/caddyfile:/etc/Caddyfile abiosoft/caddy:latest 

为了方便调试,我们从Burp商店安装了HTTP Request Smuggler和Logger ++。 接下来在Repeater中,我们形成一个简单的请求,例如:


 POST / HTTP/1.1 Host: localhost Content-Length: 8 Connection: close body=123 

并将其发送以检查所有配置是否正确:


 HTTP/1.1 200 OK Content-Length: 202 Content-Type: application/json Date: Mon, 07 Oct 2019 13:17:18 GMT Server: Caddy Server: gunicorn/19.9.0 Connection: close {"body":"b'body=123'","headers":{"Accept-Encoding":"gzip","Connection":"close","Content-Length":"8","Host":"host.docker.internal:8888","User-Agent":"Go-http-client/1.1","X-Forwarded-For":"172.17.0.1"}} 

现在启动Launch Smuggle Probe并查看答案。


图片


最有趣的是此刻开始。 有必要分析请求和响应以了解服务是否易受攻击。 这部分留给好奇的读者。

Source: https://habr.com/ru/post/zh-CN468489/


All Articles