De Prototipo a Root
Prototype Pollution → RCE
// OBJETIVO
Encadenar la contaminación de Object.prototype con un sink que ejecute comandos, para lograr ejecución remota de código en el servidor del lab.
// ZONA DE ATAQUE
Lab en construcción
Este reto ejecuta código de servidor real, así que corre en un lab Docker que todavía no está publicado. Mientras tanto, el código vulnerable y su remediación de al lado son material completo para estudiar la vulnerabilidad.
// CONSULTÁ
Pistas
Código vulnerable
La contaminación llega a un sink que compila código. El motor de plantillas lee una opción que, por herencia, ahora controla el atacante:
// 1) Primitiva: mismo deep merge inseguro del reto anterior.
deepMerge(settings, req.body);
// 2) Sink: se renderiza una plantilla usando opciones "por defecto".
const render = template.compile(view.source, view.options);
res.send(render(data)); // view.options.escape viene del prototipo contaminado
Contaminando la opción que el compilador inserta literalmente en la función
generada (por ejemplo escape o el sourceURL del template), el string
controlado por el atacante pasa a ejecutarse cuando se compila la plantilla,
llegando a child_process y a ejecución de comandos.
Remediación
Cortá la primitiva y no dejes que las opciones del motor se resuelvan por herencia:
- deepMerge(settings, req.body);
+ deepMerge(settings, req.body); // ya endurecido: descarta __proto__/constructor/prototype
+
- const render = template.compile(view.source, view.options);
+ const options = Object.assign(Object.create(null), SAFE_DEFAULTS, view.ownOptions);
+ const render = template.compile(view.source, options);
Por qué funciona: una vez que el merge no puede tocar Object.prototype, el
sink deja de heredar opciones ajenas; y construir las opciones sobre
Object.create(null) con defaults explícitos garantiza que ninguna propiedad
provenga del prototipo. Sin la opción contaminada no hay código que compilar, y la
cadena hacia RCE se rompe en su primer eslabón.
Reto descargable. Permite ejecución de código: nunca lo expongas a internet. Descargá el lab Docker y corrélo aislado en tu propia máquina.
Verificación
La verificación de flag se habilita cuando se publique el lab de este reto.