最近怠惰一段时间,昨天看到ph师傅发了一篇文章,就去学习了一波,水一篇笔记来蒙混蒙混自己Orz python http.server open redirect vulnerability
复现
这个漏洞复现起来还是方便的python3 -m http.server
然后在浏览器中输入http://127.0.0.1:8000//baidu.com/%2f%2e%2e就能跳转到百度了
简单分析
http.server模块用到几个比较重要的类,这几个类的关系就引用ph师傅的话来描述比较清楚
>1. HTTPServer这个类继承于socketserver.TCPServer,说明其实HTTP服务器本质是一个TCP服务器
>2. BaseHTTPRequestHandler,这是一个处理TCP协议内容的Handler,目的就是将从TCP流中获取的数据按照HTTP协议进行解析,并按照HTTP协议返回相应数据包。但这个类解析数据包后没有进行任何操作,不能直接使用。如果我们要写自己的Web应用,应该继承这个类,并实现其中的do_XXX等方法。
>3. SimpleHTTPRequestHandler,这个类继承于BaseHTTPRequestHandler,从父类中拿到解析好的数据包,并将用户请求的path返回给用户,等于实现了一个静态文件服务器。
>4. CGIHTTPRequestHandler,这个类继承于SimpleHTTPRequestHandler,在静态文件服务器的基础上,增加了执行CGI脚本的功能。
1 2 3 4 5 6 7 8 9 10 11 12 13 | +-----------+ +------------------------+
| TCPServer | | BaseHTTPRequestHandler |
+-----------+ +------------------------+
^ |
| v
| +--------------------------+
+----------------| SimpleHTTPRequestHandler |
| +--------------------------+
| |
| v
| +-----------------------+
+-----------------| CGIHTTPRequestHandler |
+-----------------------+ |
为什么会造成跳转就得去看SimpleHTTPRequestHandler的源码了
| |
如果path是一个目录,并且不是以/结尾,那send_head就会在结尾加上/并进行301跳转,这样看上去并没什么问题,如果目录不存在,就会返回404。但是在浏览器中,如果url以//开头,浏览器会默认认为这个url是当前数据包的协议。输入http://127.0.0.1:8000//baidu.com/%2f%2e%2e
1 2 | GET //baidu.com/%2f. HTTP/1.1 Host: 127.0.0.1:8000 |
所以send_head会在头里加入Location //baidu.com/%2f../
浏览器默认为http协议,所以就跳转到http://baidu.com/%2f../
虽然这个在生产环境中不会有人用python3 -m http.server,如果有别的代码引用了这个库,就可以造成漏洞了。
ph师傅也举了个web.py的例子
| |
这个文件引入了SimpleHTTPRequestHandler,并且在96行的时候调用了SimpleHTTPRequestHandler.do_GET(),但是请求必须由/static/开头,一般网站会将静态文件放入/static/文件夹中,所以一般都是存在的,所以直接访问http://127.0.0.1:8080////static%2fcss%2f@baidu.com/..%2f就能跳转
参考资料
https://www.leavesongs.com/PENETRATION/python-http-server-open-redirect-vulnerability.html https://www.zybuluo.com/wzhang1117/note/8226