最近怠惰一段时间,昨天看到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