网络安全
当前位置: 首页 >> 网络安全 >> 安全事件 >> 正文
WinRAR目录穿越漏洞
作者:   来源:   日期:2019年03月15日 09:16

0×00 前言

2019 2 20 @Nadav Grossman 发表了一篇关于他如何发现一个在 WinRAR 中存在 19 年的逻辑问题以至成功实现代码执行的文章。

WinRAR 代码执行相关的 CVE 编号如下

CVE-2018-20250, CVE-2018-20251, CVE-2018-20252,CVE-2018-20253

0×01 本文结构概览

0×02 漏洞描述

该漏洞由Check Point团队爆出,是一个关于WinRAR存在了19年的漏洞,用它来可以获得受害者计算机的控制。攻击者只需利用此漏洞构造恶意的压缩文件,当受害者使用WinRAR解压该恶意文件时便会触发漏洞。

其实不只是WinRAR,凡是使用了UNACE2.dll动态链接库的解压软件就会受影响,具体可参考0×03中受该漏洞影响的解压软件及版本号。

该漏洞是由 WinRAR 所使用的一个陈旧的动态链接库UNACEV2.dll所造成的,该动态链接库在 2006 年被编译,没有任何的基础保护机制(ASLR, DEP )。动态链接库的作用是处理 ACE 格式文件。而WinRAR解压ACE文件时,由于没有对文件名进行充分过滤,导致其可实现目录穿越,将恶意文件写入任意目录,甚至可以写入文件至开机启动项,导致代码执行。

0×03 漏洞影响

WinRAR < 5.70 Beta 1

Bandizip < = 6.2.0.0(笔者没有测试Bandzip,有兴趣的师傅可以自行测试)

好压(2345压缩) <= 5.9.8.10907

360压缩 < = 4.0.0.1170

0×04 漏洞危害

通过该漏洞攻击者可以向用户的开机启动项中植入恶意程序,实现监控受害者主机的目的。

DLL劫持

0×05 漏洞原理浅析

0×05-1 CleanPath

先来看看Check Point团队发布的文章中给出的CleanPath的伪代码:

Bool CleanPath(PCHAR Path)

{

char *PathTraversalPos=NULL;

if(Path[1]==':' &&Path[2]=='\\')

 strcpy(Path,&Path[3]);

if(Path[1]==':' &&Path[2]!='\\')

 strcpy(Path,&Path[2]);

PathTraversalPos=strstr(Path,"..\\");

while(PathTraversalPos)

{

 if(PathTraversalPos==Path ||*(PathTraversalPos-1)=='\\')

 {

  strcpy(Path,&Path[3]);

 PathTraversalPos=strstr(Path,"..\\");

 }

 else

 {

  PathTraversalPos=strstr(Path+1,"..\\");

 }

}

return Path;

}

在执行GetDevicePathLen这个函数之前,CleanPath会清除path中的一些简单的目录遍历序列,比如:

\..\

盘符名:\

盘符名:

盘符名:\盘符名:

..\(只有它在path的开始处才会被清除)

这段伪代码的大概流程描述如下:

1.如果Path的第23个字符为”:””\”,那么将Path4个字符之前的部分清除。

2.如果Path的第2个字符为”:”,第3个字符不为”\”,那么将Path3个字符之前的部分清除。

3.Path中寻找”..\”出现的位置,PathTraversalPos将指向此位置。若找到,执行4;否则执行7

4.如果PathTraversalPos指向的位置正是Path开始的位置(e.g...\some_folder\some_file.ext)或者PathTraversalPos指向位置的前一个字符是”\”,执行5;否则,执行6

5.Path4个字符之前的部分清除,继续在Path中寻找”..\”出现的位置,若找到,执行4;否则,执行7

6.Path+1处向后寻找”..\”出现的位置,若找到,执行4;否则,执行7

7.返回Path

通过上述分析我们可以看出盘符名:\是在步骤1被清除掉的,盘符名:是在步骤2被清除掉的;盘符名:\盘符名:是通过步骤1和步骤2两个步骤清除掉的;而\..\是在步骤5被清除掉的。

0×05-2 GetDevicePathLen

GetDevicePathLen的伪代码:

INT GetDevicePathLen(PCHAR Path)

{

 PCHAR SlashPos;

 INT Result;

 Result=0;

 if(Path[0]=="\\")

 {

 if(Path[1]=="\\")

  {

  if(!(SlashPos=strchr(&Path[2],"\\")))

   {

    return 0;

   }

  if(!(SlashPos=strchr(SlashPos+1,"\\")))

   {

    return 0;

   }

  Result=(UINT)SlashPos-(UINT)Path+1;

  }

  else

  {

   Result=1;

  }

 }

 else

 {

  if(Path[1]=":";

  {

   Result=2;

  if(Path[2]="\\")

   {

    Result++;

   }

  }

 }

 return Result;

}

GetDevicePathLen会返回一个ResultResult取值有两种情况:非00。可以看看Check Point团队给出的例子:

C:\folder\file.extreturn:3

\folder\file.extreturn:1

\\LOCALHOST\C$\folder\file.extreturn:15

\\?\Harddisk0Volume1\folder\file.extreturn:21

folder\file.extreturn:0

这段伪代码的大概流程描述如下:

1.如果Path中第1个字符为”\”,执行2;否则,执行7

2.如果Path中第2个字符为”\”,执行3;否则,执行6

3.如果在Path3个字符之后没有找到”\”,返回0;否则将SlashPos指向此位置。

4.如果在SlashPos+1之后没有找到”\”,返回0;否则将SlashPos指向此位置。

5.SlashPos指向位置减去Path指向位置再加1赋值给Result(e.g.\\?\Harddisk0Volume1\folder\file.ext),然后执行9

6.Result赋值为1,然后执行9

7.如果Path2个字符为”:”Result赋值为2

8.如果Path3个字符为”\”Result值加1

9.返回Result

这样我们就可以知道例子中的返回值是如何计算出来的了。

0×05-3 WinRAR Validators / Callbacks

下载 (1).jpeg

这段伪代码的功能很简单,执行以下检查:

1.第一个字符不等于”\””/”

2.文件名不以以下字符串”..\””../”开头。

3.字符串中不存在:

\..\

\../

/../

/..\

0×05-4 触发目录遍历漏洞的sprintf

下载 (2).jpeg

如果调用GetDevicePathLen,返回的结果为0,则执行

sprintffinal_file_pathss”destination_folderfile_relative_path;

即图中蓝色箭头指向的部分。

如果调用GetDevicePathLen,返回的结果不为0,则执行

sprintffinal_file_pathss”“”file_relative_path;

即图中红色箭头指向的部分,这就是触发目录遍历漏洞的错误代码。

0×06 构造路径

思路如下所示:

1.GetDevicePathLen函数的结果应不为0

2.执行 sprintffinal_file_pathss”“”file_relative_path; 代替 sprintffinal_file_pathss”destination_folderfile_relative_path;

3.绕过CleanPath函数;

4.绕过WinRAR Validators / Callbacks

通过上述思路来分析Check Point团队给出的最强攻击向量:

C:\C:C:../AppData\Roaming\Microsoft\Windows\StartMenu\Programs\Startup\some_file.exe

1.开始字符不在WinRAR Validators / Callbacks的黑名单中;

2.CleanPath函数将清除掉开头的”C:\C:”

3.GetDevicePathLen函数的结果为2

4.执行 sprintffinal_file_pathss”“”file_relative_path;

成功!!最终路径为:

C../ AppData\Roaming\Microsoft\Windows\StartMenu\Programs\Startup\some_file.exe

如果我们在桌面解压文件,那么当前目录为:

C:\Users\<user name>\Desktop

下载 (3).jpeg下载 (4).jpeg

经过上面的操作我们的路径将会变为:

C:\Users\<username>\Desktop../AppData\Roaming\Microsoft\Windows\StartMenu\Programs\Startup\some_file.exe

这样”../”会返回到上一层文件夹,即

C:\Users\<user name>\AppData\Roaming\Microsoft\Windows\StartMenu\Programs\Startup\some_file.exe

这样就将some_file.exe添加到启动目录了。

其他当前目录的例子比如:C\Program Files\WinRARC:\Users\<user name>\Downloads就不再上图了。

0×07 UNACEV2.dll校验CRC引发漏洞

漏洞主要是由Winrar用来解压ACE文件时使用的动态链接库UNACEV2.dll引起的,UNACEV2.dll在处理filename时只校验了CRC。故我们可以通过使用HxD修改filename(也就0×06中的最强攻击向量,我们无法直接去修改filename,所以要用HxD去修改ACE二进制文件)将恶意文件解压到启动目录,但是在修改完成后,CRC校验会失败,所以我们还要再去修改CRC,具体过程请见下面的分析。

0×07-1 建立ACE文件

这里要使用WinACE这个工具:

下载 (5).jpeg

建立一个ACE格式文件:

下载 (6).jpeg

注意红色框中要选取”store full path”

下载 (7).jpeg

使用HxD工具来查看一下example.ace这个文件,可以看到下图中蓝色选中部分的路径是我们上图中绿色框中的路径:

下载 (8).jpeg0×07-2 ACE文件的header信息

使用github上的工具acefile.py来查看我们创建的ACE文件的header信息。

下载 (9).jpeg

结果中有两个header(红色划线部分),重点在第二个header

hdr _ crcCRC校验后的结果

filename:文件路径

hdr _ size:头部大小(我没有在图片中框出来,抱歉)

filename _ size:文件名的大小(acefile.py没有把这个列出来,可以见下图中我的标示)

修改filenameCRC校验的结果与hdr_size都会发生变化,所以我们还要再修改hdr_crchdr _ size

0×07-3 修改ACEheader

下载 (10).jpeg

绿色:hdr _ crc

红色:hdr _ size

紫色:filename _ size

P.S.filename没有标出,但在右侧可以看到:Users\Administrator\Desktop\example.txt

0×07-3.1 修改filename

在右侧选中Users\Administrator\Desktop\example.txt,将其修改为C:\ProgramData\Microsoft\Windows\Start Menu\Programs\example.txt

0×07-3.2 修改filename_size

下载 (1).jpg

将蓝色选中部分前面2字节的2700改为40 00,因为是小端序,所以是从后向前。

0×07-3.3 修改hdr_size

下载.jpg

将蓝色选中部分前面2字节的7100改为5F 00。(这一步的截图,由于我中间操作失误,所以与上面的图片不是一个文件,但修改的位置是正确的,hdr_crc后面接着的就2字节的hdr_size,所以比较好找。)

0×07-3.4 修改hdr_crc

这一步需要使用acefile.py重新查看一下这个文件,得到下图:

下载(2).jpg

可以看到给出的信息上面部分是正确的hdr_crc4766

而下面部分是现在的hdr_crccda9。在HxD中修改掉它(注意是小端序):

下载(3).jpg

0×07-3.5 再次查看头部信息

修改完成后再使用acefile.py去查看一下头部信息:

下载(4).jpg

修改成功。

0×08 修复建议

1.升级到最新版本的 WinRAR ,目前版本是 5.70 Beta 1。下载地址如下:

32 位:http://win-rar.com/fileadmin/winrar-versions/wrar57b1.exe

64 位:http://win-rar.com/fileadmin/winrar-versions/winrar-x64-57b1.exe

2.删除UNACEV2.dll

上一条:Weblogic反序列化远程代码执行漏洞 下一条:Windows DHCPServer远程代码执行漏洞

关闭

办公地点:第四教学楼东侧信息技术服务中心      办公时间:周一至周五 8:00-11:30   14:30-18:00(春夏)   14:00-17:30(秋冬)
*办理个人业务请携带本人身份证件
学校地址:山东省烟台市莱山区滨海中路191号
版权所有:山东工商学院信息技术服务中心