
Ein einfacher Proof of Concept für WinRAR Path Traversal | RCE | CVE-2025-6218
Weitere Informationen:
RARLAB WinRAR-Schwachstelle für Directory Traversal und Remote Code Execution. Diese Schwachstelle erlaubt es entfernten Angreifern, beliebigen Code auf betroffenen Installationen von RARLAB WinRAR auszuführen. Für die Ausnutzung dieser Schwachstelle ist eine Benutzerinteraktion erforderlich, da das Ziel eine schädliche Seite besuchen oder eine schädliche Datei öffnen muss.
Der spezifische Fehler liegt in der Verarbeitung von Dateipfaden in Archivdateien. Ein manipulter Dateipfad kann dazu führen, dass der Prozess in ungewollte Verzeichnisse wechselt. Ein Angreifer kann diese Schwachstelle ausnutzen, um Code im Kontext des aktuellen Benutzers auszuführen. War ZDI-CAN-27198.
Veröffentlicht 2025-06-21 00:09:03 Aktualisiert 2025-06-23 20:16:22 Quelle Zero Day Initiative
Schwachstellenkategorie: Directory Traversal | Code-Ausführung
Ein sehr minimaler und einfacher Proof of Concept für die WinRAR-Path-Traversal-Schwachstelle CVE-2025-6218. (Außerdem enthalten: mein Werkzeugsatz zum Experimentieren mit dem RAR-Format für Schwachstellentests)
Die Kette von Path Traversal zu RCE ist im POC nicht enthalten, aber das Schreiben beliebiger Dateien zu RCE ist unter Windows trivial.
Proof of Concept erstellen:
$ python3 cve-2025-6218.py
Wenn Sie dieses Archiv extrahieren, wird test.txt eine Ebene außerhalb des aktuellen Verzeichnisses extrahiert.
Das Problem rührt von einem spezifischen Konflikt zwischen der Bereinigung von Leerzeichen und der Prüfung von Pfad-Traversalen in der ausführbaren WinRAR-Datei bis Version 7.11 her:
Eine etwas vereinfachte und bereinigte Version:
void file_name_check(char *a1){
cur_filename = a1;
j = 0;
cur_pos = 0;
if ( *(a1 + 4) > 0 )
{
offset = 0;
while ( 1 )
{
if ( (cur_pos + 1) == cur_filename[2] )
goto BREAK;
str = cur_filename;
if ( cur_filename[3] > 7 )
str = *cur_filename;
if ( str[offset + 1] == '\\' || str[offset + 1] == '/' )
{
BREAK:
if ( cur_pos >= 0 )
break;
}
LOOP_START:
++cur_pos;
++offset;
if ( cur_pos >= *(cur_filename + 4) )
goto LABEL_47;
}
while ( 1 )
{
if ( str[offset] != '.' )
{
if ( str[offset] != ' ' )
goto LOOP_START;
}
if ( !cur_pos )
{
if ( str[offset] == ' ' )
{
str[offset] = '_';
goto LOOP_START;
}
}
if ( str[offset] == '.' )
{
if ( !cur_pos )
goto LOOP_START;
if ( str[offset - 1] == '\\' || str[offset - 1] == '/' )
goto LOOP_START;
if ( cur_pos == 2 )
{
if ( is_safe_character(cur_filename) )
goto LOOP_START;
}
else if ( cur_pos < 1 )
{
goto DELETE;
}
if ( str[offset - 1] == '.' )
{
if ( cur_pos == 1 )
goto LOOP_START;
if ( str[offset - 2] == '\\' || str[offset - 2] == '/' || cur_pos == 3 && is_safe_character(cur_filename) )
goto LOOP_START;
}
}
DELETE:
delete_char(cur_filename, cur_pos, 1u);
--offset;
if ( --cur_pos < 0 )
goto LOOP_START;
}
}
//...
}
Nach 7.12:
void __fastcall file_name_check(char **a1){
cur_filename = a1;
j = 0;
if ( *(a1 + 4) > 0 )
{
offset = 0;
fname_index = 1;
do
{
if ( fname_index == cur_filename[2] )
goto HANDLE_DIR_NEXT;
str = cur_filename;
if ( str[offset + 1] == '\\' || str[offset + 1] == '/' )
{
HANDLE_DIR_NEXT:
if ( offset >= 0 )
{
if ( str[offset] == '.' )
goto FILENAME_BEGINS;
if ( str[offset] == ' ' )
{
FILENAME_BEGINS:
if ( str[offset] != '.' )
goto CONT;
if ( offset )
{
if ( str[offset - 1] != '\\'
&& str[offset - 1] != '/'
&& (offset != 2 || !is_safe_character(cur_filename)) )
{
if ( str[offset - 1] != '.' )
goto CONT;
if ( offset != 1 )
{
if ( str[offset - 2] != '\\'
&& str[offset - 2] != '/'
&& (offset != 3 || !is_safe_character(cur_filename)) )
{
CONT:
str[offset] = '_';
}
}
}
}
}
}
}
++j;
++offset;
++fname_index;
}
while ( j < *(cur_filename + 4) );
}
//...
}