
WinRAR Path Traversal | RCE | CVE-2025-6218 のシンプルな概念実証
詳細情報:
RARLAB WinRAR ディレクトリトラバーサル リモートコード実行脆弱性。この脆弱性により、リモート攻撃者が RARLAB WinRAR のインストール環境で任意のコードを実行できる可能性があります。この脆弱性を悪用するには、ターゲットが悪意のあるページにアクセスするか、悪意のあるファイルを開く必要があります。
具体的な欠陥は、アーカイブファイル内のファイルパスの処理に存在します。細工されたファイルパスにより、プロセスが意図しないディレクトリにトラバースする可能性があります。攻撃者はこの脆弱性を悪用して、現在のユーザーのコンテキストでコードを実行できます。ZDI-CAN-27198 として登録されていました。
公開日 2025-06-21 00:09:03 更新日 2025-06-23 20:16:22 提供元 Zero Day Initiative
脆弱性カテゴリ: ディレクトリトラバーサル | コード実行
CVE-2025-6218 WinRAR パストラバーサル脆弱性の非常に最小限かつシンプルな概念実証です。(また含まれています: RAR 形式を脆弱性テスト用に扱うためのツールセット)
パストラバーサルから RCE への連鎖は POC には含まれていませんが、Windows での任意のファイル書き込みから RCE への攻撃は簡単です。
概念実証を作成:
$ python3 cve-2025-6218.py
このアーカイブを展開すると、test.txt は現在のディレクトリの1階層外に展開されます。
問題は、WinRAR 実行ファイル バージョン 7.11 までの、空白のサニタイズ方法とパストラバーサルのスキャン方法の特定の競合に起因します:
少し簡略化して整理したバージョン:
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;
}
}
//...
}
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) );
}
//...
}