Tar解压漏洞的验证方法及其临时修复方案

        2019-03-21 393811人围观 ,发现 10 个不明物体 漏洞

        *本文作者:LEdge1,本文属 FreeBuf 原创奖励计划,未经许可禁止转载。

        之前WinRAR出现的漏洞,没几天网上就出现了各种利用这种漏洞的攻击了,想到这,我突然想起来Linux下也有这么一款解压软件也是有漏洞的。今天给大家说一说吧 !

        我们在Linux下使用最多的压缩和解压工具就是tar了。如果说这款工具出现了漏洞,那么危害还是很大的。不过还真的出现了一个解压路径的漏洞:这个漏洞出现在tar解压命令上,如果恶意者提前构造好这种有害的压缩包。当我们在使用tar命令解压的时候导致压缩包解压到不是我们指定的目录下面,导致了文件覆盖,更有甚者进行远程的代码执行!

        影响范围

        GNU tar :1.14 ~1.29 (包含1.29)

        影响系统包括所以使用GNU tar命令的linux系统

        实验环境

        操作机 : Kali Linux

        实验工具

        tar-poc.tar :这个文件是本次漏洞试验的POC,我们将使用本文件验证漏洞

        tar-1.26.tar.gz :1.26版本的tar源码

        实验步骤

        步骤1:漏洞分析

        在实现漏洞复现之前我们得了解一下,这个漏洞的是什么原因导致的。那我们就得对源码进行分析,在进行源码的分析过程中发现了paxnames.c这个文件是有问题的,那我们废?#23433;?#22810;?#21040;?#20837;源码存放文件夹,盘它:

        cd /root/Desktop/ // 进入桌面

        cat tar-1.26/lib/paxnames.c // 预览paxnames.c文件

        在tar1.26的源码包中,lib文件夹下存放着函数库和一些配置文件,其中paxnames.c文件里面存放着检测文件名和路径安全性的相关函数和配置。就是检测程序考虑的不够完美导致了漏洞的出现。

        打开后,可以看到如下代码:

        char *

        safer_name_suffix (char const*file_name, bool link_target,

            bool absolute_names)

        {

         char const *p;

         if (absolute_names)

           p = file_name;

         else {

             /* Skip file system prefixes, leading file name components that contain

         "..", and leading slashes.  */

                     size_tprefix_len = FILE_SYSTEM_PREFIX_LEN (file_name);

         

             for (p = file_name + prefix_len; *p; )

         {

                 if (p[0] == '.' && p[1] == '.' &&(ISSLASH (p[2]) || !p[2]))

            prefix_len = p + 2 - file_name;

         

          do

            {

              char c = *p++;

              if (ISSLASH (c))

         break;

            }

          while (*p);

         }

         

             for (p = file_name + prefix_len; ISSLASH (*p); p++)

         continue;

             prefix_len = p - file_name;

         

             if (prefix_len)

         {

          const char *prefix;

          if (hash_string_insert_prefix (&prefix_table[link_target],file_name,

             prefix_len, &prefix))

            {

              static char const *const diagnostic[] =

              {

         N_("Removing leading `%s' from member names"),

         N_("Removing leading `%s' from hard link targets")

              };

              WARN ((0, 0, _(diagnostic[link_target]), prefix));

            }

         }

           }

        在研究了一段时间之后发现,这?#26410;?#30721;里面有个safer_name_suffix函数,他的任务就是检测文件名是否合法,文件后缀是否合法。

        absolute_names 是一个变量,它用来获得文件的名称,如果absolute_names变?#35838;?,那么就将文件名中文件系统的前缀给去掉。

        在之前比较老的版本,如果压缩文件中存在 .. 字符串,系统会跳过不去处理这些文件。

        而在后来的版本中,safer_name_suffix不再跳过文件名中包含 ../ 字符串的恶意字符,强制?#22659;?#25152;有存在可能被恶意访问的字符,如 ../ ,把 ../ 之前的所有字符都?#22659;?#21482;会留下其后面的字符。

        使其与解压目标路径变?#19978;嘍月?#24452;,而压缩包中的内容就会覆盖恶意访问者指定的路径文件,漏洞就这样产生了。

        例如:test.tar压缩包中有一个文件夹,其文件?#26032;?#24452;?#26469;?#20026; etc/motd../etc/shadow ,然后在执行命令 tar -C / -xvf test.taretc/motd ,意思是将test.tar里面的内容解压到etc/motd目录下。

        但是在safer_name_suffix函数中经过一系列操作,已经将 ../ 之前的内容都去掉了,路径名只剩下 etc/shdow ,这时候, etc/shdow 就被覆盖了。

        步骤2:使用POC验证漏洞

        本步将使用POC验证漏洞.

        现在我们使用POC来验证漏洞,因为此POC是覆盖 etc/shadow ,所以我们首先先查看一下原始的shadow文件有什么内容。

        使用命令:

        cat /etc/shadow // 预览shadow文件的内容

        可以看到,里面记录了各个账户的?#27809;?#21517;、?#29992;?#36807;的密码、上次更改密码的日期等。

        接下来我们来解压POC,将他解压到 etc 目录下,使用命令:

        cd /root/Desktop

        tar -C / -xvf tar-poc.tar etc/motd

        其中,X的意思是从归档文件中?#22836;?#25991;件。v的意思是输出tar处理文件的信息到屏幕。f的意思是使用归档文件,一般情况下f这个选项是必选的。

        这时,再次查看 etc/shadow 文件,发现已经被替换。已经不是之前的内容。

        我们明明是解压到etc/motd的目录下,它却解压到etc的根目录下,覆盖了shadow文件,因此到这里,我们就成功的验证了漏洞。

        实验结果分析与总结

        漏洞修复

        自己琢磨了一段时间之后,发现在safer_name_suffix中添加判断,如果检测到 ../ 字符串,直接报错,然后退出程序,如下:

        --- lib/paxnames.c.orig    2016-04-06 00:04:47.314860045 +0300

        +++ lib/paxnames.c      2016-04-06 02:08:44.962297881 +0300

        @@ -18,6 +18,7 @@

        #include <system.h>

        #include <hash.h>

        #include <paxlib.h>

        +#include <quotearg.h>

        /* Hash tables of strings.  */

        @@ -114,7 +115,15 @@

             for (p = file_name + prefix_len; *p; )

               {

                 if (p[0] == '.' && p[1] == '.' &&(ISSLASH (p[2]) || !p[2]))

        -          prefix_len = p + 2 - file_name;

        +            {

        +            static char const *constdiagnostic[] =

        +            {

        +              N_("%s: Member namecontains '..'"),

        +              N_("%s: Hard link targetcontains '..'")

        +            };

        +            FATAL_ERROR ((0, 0,_(diagnostic[link_target]),

        +                          quotearg_colon(file_name)));

        +          }

        这种方法的确可以修复漏洞,但还有一点不足,?#27809;?#22312;配置文件或者操作文件时,如果遇到 ../ 这种情况,到一半就强行停止下来,这样的话?#27809;?#20307;验度很差。

        *本文作者:LEdge1,本文属 FreeBuf 原创奖励计划,未经许可禁止转载。

        发表评论

        已有 10 条评论

        取消
        Loading...
        css.php 永利彩票是骗局吗

                    好运彩3d字谜 天津快乐10分体育彩票开奖结果查询 合买的彩票图片 安徽25选5大星 18095期7星彩开奖结果 竞彩足球比分直播观看 平码二中二玩法规则 四川时时彩诈骗案例 彩票app开发制作 曾道人三个半单双 福建快3今天开奖号 老11选5为什么停了 捷讯足球比分 陕西快乐十分胆拖玩法介绍 体彩7星彩号码多少