0x 01 简介
最近扫描工具扫到一个 Directory Listing,通过分析目录下的文件代码,结合上传覆盖 python 文件和代码中的 “dynamic import” ,获取到了服务器权限。文章没有什么高深的技术,个人觉得蛮有意思,整理了一下当时的利用过程,如有写不对或不准确的地方,欢迎大家指出
0x 02 环境搭建
因为涉及到漏洞,这里对代码做了一些脱敏和精简,环境使用 docker 搭建,代码文件在 github 上,运行以下命令启动环境
运行成功后,访问 http://127.0.0.1:30000/,可以看到有四个文件,分别是
httpServer.py:当前server的代码,是一个 python2 的 SimpleHTTPServer,除了列出目录文件外,还有一些其它接口,后面会分析
log.txt :server 输出日志文件
showDump.py:httpServer.py 中 import 到的文件
upload.html:一个可以上传文件页面
0x 03 接口分析
这里主要分析一下 httpServer.py 中的接口功能,主要代码在 类中的 和 方法中
GET /reload
精简代码:
访问接口会执行 server_path 的 bin 目录下的 脚本,并将执行结果输出到页面
GET /real_time_log?
精简代码:
访问接口,代码会读取 server_path 的 log 目录下,以 为后缀的 log文件内容, 的值为使用 分割 path 后的第一个元素,然后将文件内容输出到页面
GET /del_file_list?
精简代码:
取 path 中 之后的部分,列出目录下的文件,若是目录则显示进入和删除目录链接,若是文件,则显示删除链接
GET /del_file?
精简代码:
取 path 中 之后的部分作为路径(目录或文件),将其删除
GET /show_dump
精简代码:
从 文件中 import 函数 ,并调用执行
do_POST
精简代码:
对应的上传文件接口,使用 和 ,然后写入上传文件
0x 04 利用分析
先理一下环境和现有功能:
后端是一个 python2 的 SimpleHTTPServer
接口能够执行 shell script,但执行的文件路径不可控
接口能够读取文件内容,路径部分可控
能够列出目录下的文件,但无法看到内容
能够删除目录和文件
能够上传文件,上传目录和文件名都可控
从另一个py文件中 import 函数,并执行
因为无法通过直接上传python文件,然后访问url来执行代码,所以需要通过其它方式,这里列举一些当时想到的方式
覆盖shell文件
接口中,虽然执行的shell文件路径不可控,但 可以上传文件,且路径完全可控,可以尝试通过覆盖 shell 文件,再访问 接口来执行自己的 shell 脚本
But,经过尝试后,无法成功,查看 中会有如下错误
因为当前用户是,而 是在 ( 值为 ) 下,属于 用户, 用户没有写权限,所以无法成功
读取文件内容
接口中,读取文件的后缀是可控的,是否可以通过相对路径 ( ) 的方式来进入其他目录?
But,经过尝试后,使用 的方式在这里是不行的,因为 之前的路径必须是目录,且每一个目录都需要存在,可能说的有点不好理解
首先看一下文件目录
再来看几个例子,应该就能理解了
例一: 目录不存在
例二: 文件存在,但不是目录
例三:成功
那么有没办法创建 目录呢?
目录是在 下,没有写权限…
还有就是即使这里可以使用 的方式,细看一下代码,发现是以 的方式读取文件内容,然后输出到页面,所以只能读取到新写入的文件内容。
覆盖py文件
如果是修改 ,然后上传覆盖原有文件呢?
But,并不行,因为代码已经载入内存了,要想让修改后的新代码生效,需要重启 server。
想到覆盖文件,之前 接口中会从 文件 import 函数并执行,与顶层import 的只载入一次不同,这里每次访问接口都会重新从 文件中 import 函数,也就是说,我们可以通过上传覆盖这个文件,只要保持 函数的定义不变,函数内可以执行我们任意的 python代码
反弹 POC
将上述文件保存,然后通过 上传,新文件名填写 ,然后访问 接口
测试成功