Contents
  1. 1. CVE-2018-11235
    1. 1.1. Git 的 hook 脚本
    2. 1.2. 构造目录穿越,传送恶意脚本
    3. 1.3. 修复代码
  2. 2. ZipperDown

CVE-2018-11235

日前收到消息,安全部门让更新 Git 客户端,这是怎么回事呢?

近日Git客户端被发现存在一个潜在的远程代码执行漏洞(CVE-2018-11235),当用户使用’git clone –recurse-submodules’ 命令克隆恶意代码仓库时, 可易导致本地任意代码执行,被植入病毒、木马等,目前利用的POC代码已经公开。

通过给出的几个链接进行了一番观摩学习

  1. https://marc.info/?l=git&m=152761328506724&w=2
  2. http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-11235
  3. https://blogs.msdn.microsoft.com/devops/2018/05/29/announcing-the-may-2018-git-security-vulnerability/

大概了解到构造了目录穿越漏洞从而达到执行任意代码的目的,到底是怎么做到的没研究明白。于是找到一些白帽子的博客学习,阿里云社区上有篇文章详细分析了漏洞的原理、构造方法并从 Git 源码上解释了原因以及简要分析了修复代码

https://xz.aliyun.com/t/2371#toc-0

Git 的 hook 脚本

hook 脚本是放在 .git/hooks 目录下,并且这个目录不会被传送,也就是说当 clone 一个仓库时不会得到脚本文件。这些脚本都是客户端侧自己给自己加的,所以说这里有一层过滤防护——hook 脚本不会在网络中传送,因而一定程度断绝了远程代码执行的危险。

构造目录穿越,传送恶意脚本

通过利用 Git 子模块功能,绕过前述 hook 脚本过滤的保护,将脚本从远端推送(传递)到了 .git/hooks/ 目录。
假设一个子模块叫做 vuln ,他的 .gitmodules 配置如下
[submodule “vuln”]
path = vuln
url = ./../repo_sub

本来正常的子模块 Git 目录为 .git/modules/vuln,但最后被构造为 .git/modules/../../vuln,指向了当前的目录 vuln

  1. 将目录 .git/modules/vuln 拷贝到当前目录 modules 下。根目录中的 modules 目录是用来存放子模块代码的目录.
  2. modules/vuln 目录中的 hooks 目录添加 hook 脚本。
  3. 构造子模块,使其 name 成为 ../../modules/vuln,使子模块的 Git 目录信息指向当前目录下 module/vuln
  4. 构造 repo,使其在 git clone 时触发 hook 脚本

修复代码

https://github.com/git/git/commit/0383bbb9015898cbc79abd7b64316484d7713b44

主要是对从 .gitmodules 中获取的 name 进行了检查

问题就转为了如何检查名字中是否带有 ../ 的字段?

    int check_submodule_name(const char *name)
    {
        /* Disallow empty names */
        if (!*name)
            return -1;
        
        /*
         * Look for '..' as a path component. Check both '/' and '\\' as
         * separators rather than is_dir_sep(), because we want the name rules
         * to be consistent across platforms.
         */
        goto in_component; /* always start inside component */
        while (*name) {
            char c = *name++;
            if (c == '/' || c == '\\') {
            in_component:
                if (name[0] == '.' && name[1] == '.' &&
                    (!name[2] || name[2] == '/' || name[2] == '\\'))
                    return -1;
            }
        }
        
        return 0;
    }

这段代码里使用了 goto,goto 也不是不能用在生产生活中。五六个判断条件组合在一起也不是什么大逆不道的事情。需要检查 \ 来达到跨平台保护?什么平台是用 \ 来做目录分割?Windows?

ZipperDown

不久之前 iOS 上也有个类似的问题,不过复现方法简单多了。两个漏洞都具有相同的环境

  1. 可接收来自远端的脚本
  2. 客户端会在某个时刻调用特定目录下的脚本

所以,只需要将来自 1 的脚本想办法弄到 2 中的目录就行,在 iOS 上广泛存在热补文件,构造恶意的脚本替换正常的脚本就可以达到攻击的目的。

1.App直接接收不可信Zip文件,并使用SSZipArchive/ZipArchive(或其它存在路径穿越问题的代码)解压。例如聊天应用、文件管理应用中可能存在这类业务场景。

2.App通过HTTP下载Zip文件,使用SSZipArchive/ZipArchive(或其它存在路径穿越问题的代码)解压。在这种场景下,攻击者可以通过流量劫持等途径,将正常Zip文件替换为恶意Zip文件,在App中实现文件覆盖。

第二点广泛存在,我们的业务代码中就存在从非 HTTPS 协议中下载 zip 包的情况,即使 HTTPS 也不一定安全,也有可能中间人攻击。中间人攻击的典型案例就是 Charles 抓 HTTPS 的包,MrPeak 介绍的 mitmproxy 工具也是这个原理。

Contents
  1. 1. CVE-2018-11235
    1. 1.1. Git 的 hook 脚本
    2. 1.2. 构造目录穿越,传送恶意脚本
    3. 1.3. 修复代码
  2. 2. ZipperDown