这是一次鸡肋的代码审计
Python 标准库中用来处理 HTTP 相关的模块是 urllib/urllib2,不过其中的 API 十分零碎,比如 urllib 库有 urlencode,但 urllib2 没有,经常需要混在一起使用,换个运行环境可能又无法正常运行,除了 urllib 和 urllib2 之外,会经常看到的还有一个 urllib3,该模块是服务于升级的 http 1.1 标准,且拥有高效 http 连接池管理及 http 代理服务的功能库,但其并非 python 内置,需要自行安装,使用起来仍很复杂,比如 urllib3 对于 POST 和 PUT 请求(request),需要手动对传入数据进行编码,然后再加在 URL 之后,非常麻烦。
【代码审计文档获取】
requests 是用基于 urllib3 封装的,继承了 urllib2 的所有特性,遵循 Apache2 Licensed 开源协议的 HTTP 库,支持 HTTP 连接保持和连接池,支持使用 cookie 保持会话,支持文件上传,支持自动响应内容的编码,支持国际化的 URL 和 POST 数据自动编码。如他的口号 HTTP for Humans 所说,这才是给人用的 HTTP 库,实际使用过程中更方便,能够大大的提高使用效率,缩短写代码的时间。
实战中遇到过这样一个案例,一个输入密码正确后会 302 跳转到后台页面的登录口存在盲注,但登录数据有加密,无法使用 sqlmap 完成自动注入的过程,于是想编写 python 脚本自动化完成这个过程。requests 是首选,实际编写过程中会发现默认属性下其无法获取到 30X 状态码的详情,分析其代码后发现 requests 的所有请求方法(GET/POST/HEAD/PUT/DELETE)均会默认跟随 30X 跳转,继承了 urlib3 默认跟随 30X 跳转的属性,并将 30X 连续跳转的次数上限从 3 次修改为 30 次,如果返回状态码是 304/305/306/309 会保持原来的请求方法,但不会跳转,返回状态码是 307/308 会保持原请求方法,并且跳转,其他 30x 状态码则会将请求方法转化为 GET。如需禁止跳转需将 allow_redirects 属性的值设置为 False。
下面将分享一个因为这个特性导致的从 ssrf 到 rce 的漏洞组合拳。
0x01 起
某系统的升级功能可配置自定义的站点, 点击升级按钮后会触发向特定路由发送文件, 也就是一个鸡肋的POST
类型的路由和参数均不可控的SSRF
。
如下图,**_update
是从用户自定义的配置中取的, 与固定的route
变量拼接后作为发送文件的url
利用上文提到的 requests 默认跟随状态码30X
跳转的特性, 可将这个鸡肋的SSRF
变成一个GET
类型的路由和参数均可控的SSRF
0x02 承
该软件的分层大致如下图, 鉴权在应用层, 涉及数据涉及敏感操作的均通过 api 调用另一个端口的上的服务, 该过程无鉴权。思路比较清晰, 可审计服务层的代码漏洞结合已有的SSRF
进一步扩大危害。
受这个SSRF
本身的限制, 寻找服务层漏洞时优先看请求方式为GET
的路由, 筛选后找到一个符合条件的漏洞点如下图所示, 传入的doc_file_path
参数可控, 如果文件名中能带入自己的恶意Payload
且文件能够存在的情况下, 拼接到cmd
变量中后有机会RCE
。
走到命令拼接的前置条件是文件存在, 故先查看上传部分代码, 如下图所示, mkstemp方法的作用是以最安全的方式创建一个临时文件, 该文件的文件名随机, 创建后不会自动删除, 需用户自行将其删除, suffixs
是指定的后缀, 也就是说文件虽然可以落地, 但文件名不可控, 无法拼接自己的Payload
。
此时只能作为一个任意文件删除的漏洞来使用, 配置升级链接301
跳转到http://127.0.0.1:8848/api/doc?doc_file_path=/etc/passwd
, 其中doc_file_path
参数为已知的存在的文件, 点击系统升级按钮即可触发删除操作。
0x03 转
继续分析代码,阅读大量代码后找到一处上传文件的功能点如下图所示, 其中file_pre
为源文件名, 拼接下划线,时间戳以及.txt
后保存并返回了完整的文件路径,正好符合上面的要求。
源文件名可控, 路径已知,SSRF
升级RCE
变得索然无味, 使用分号切割命令语句,带参数的命令可以使用${IFS}
绕一下空格问题, 涉及到的${;
均为 unix 系统文件名允许使用范围的字符。
0x04 合
参数及路由均不可控POST
类型的SSRF
-> requests
30X
跳转特性 -> 参数和路由均可控的GET
类型SSRF
-> 文件名部分可控的文件上传 -> 多点结合攻击本地服务
最终 Payload 如下:
配置完成手动点击一下升级功能即可触发命令执行。
评论