想接管别人的整个Java生态系统?只需一次中间人攻击

大受欢迎且广泛部署的几百个Java库和JVM编译器,它们下载依赖项时,仍在用HTTP协议,却没有校验完整性。本来只是想给一个小型项目做一个简单漏洞报告,不料猛地发现了这个安全漏洞,影响了基于Java虚拟机(JVM)做开发的整个生态系统。

初探

Max Veytsman于2014年发表了一篇很棒的文章,名为《如何接管任意Java(或Closure或Scala)开发人员的计算机》,这项工作正是基于这篇文章开展的。

当时,由Sonatype运行的Maven中央仓库在提供JAR文件时,还不支持SSL(HTTPS)。多亏Max的文章,Sonatype几天内就修复了这个问题。我强烈建议你在阅读本文之前,至少先略读一下那篇文章。虽然它已经发表了5年,但其中的警告仍然有效,不仅如此,现在还能适用于Kotlin和Groovy的开发人员。

然而,这一次不是因为存储库主机缺乏对HTTPS的支持,而是因为普遍都在采用“一字之差”的HTTP,所以直到今天,仍有成千上万的开源项目易受攻击。

Max在他的文章中介绍了一个名为Dilettante的工具,“它是一个中间人代理,拦截来自【任何工件(artifact)仓库】的JAR包,并将恶意代码注入其中。通过Dilettante代理HTTP流量,将会在【从工件仓库下载的】任何JAR包里开后门。”

Dilettante是一个简单的POC,它所做的仅仅是让Java在屏幕上展现猫图片。但就是这种非常简单的技术,却可以用来大面积恶意破坏Java生态系统——只要项目是通过HTTP而不是HTTPS下载依赖项的。

图中猫咪说:听说你提供JAR包不用ssl?

HTTPS不仅能加密客户端和服务器之间的流量,还能保证客户端是在与其所请求的服务器进行通信,避免有人在中间冒名顶替(即MITM,中间人攻击)。

我是怎么发现的?

有一次,我发现自己的项目中有一个工件用的是HTTP。

// Ktor没有发布到jcenter仓库。
	maven {
	    setUrl("http://dl.bintray.com/kotlin/ktor")
	}

这是怎么来的?

这是从Ktor仓库复制和粘贴来的。我深入研究Ktor仓库的历史,发现直到最近,Ktor还在用HTTP来解析依赖关系。有一点要注意,Ktor是JetBrains的一个官方库。就连JetBrains的官方库都这样?我十分好奇,开始寻找其他哪里还有这个库。

谁容易遭受攻击?

长话短说:GitHub上一些最流行的基于JVM的项目,它们曾经或仍然容易受到攻击。

组织 项目 加星数 已完成 GitHub上的问题 已确认 已修复 会审核 不审核 审核结果 保证影响 CVE(漏洞和披露) 无已发布的发行版本 备注
arrow-kt arrow 2718 链接 未完成 CVE-2019-11404
ben-manes caffeine 6021 链接 无妨
cbeust jcommander 1287 链接 未完成
cbeust testng 1285 链接 未完成
cbeust kobalt 370 链接 未完成 构建工具。影响到用户。
CodeNarc CodeNarc 204 链接 未完成
controlsfx controlsfx 229 链接 未完成
diffplug spotless 700 链接 尚无定论
Eclipse vorto 103 链接 未完成 CVE-2019-10248
Eclipse buildship 422 链接 未完成
Eclipse xtext-maven 6 链接 未完成 CVE-2019-10249
Eclipse hawkbit 184 链接 未完成 CVE-2019-10240
Eclipse xtext-xtend 55 链接 未完成 CVE-2019-10249
Eclipse sw360 23 链接 未完成
ehcache ehcache3 1323 链接 无妨 提交请求(pr)
FasterXML jackson-module-scala 385 链接 未完成
grails grails-core 2474 链接 无妨 CVE-2019-12728
HellFirePvP AstralSorcery 99 链接 未完成 “我的世界”模组
immutables immutables 2409 链接 未完成
ktorio ktor 5290 链接 未完成 CVE-2019-10102
MightyPirates OpenComputers 792 链接 未完成 “我的世界”模组
MinecraftForge CoreMods 22 链接 未完成 “我的世界”模组
NationalSecurityAgency datawave 243 链接 未完成
nebula-plugins nebula-kotlin-plugin 54 链接 未完成
nebula-plugins nebula-test 37 链接 未完成
nebula-plugins nebula-grails-plugin 2 链接 未完成
nebula-plugins nebula-clojure-plugin 12 链接 未完成
nextflow-io nextflow 818 链接 未完成
OpenAPITools openapi-generator 2456 链接 未完成 CVE-2019-11405 代码生成器
PayPal Gibberish-Detector-Java 18 链接 未完成
PayPal digraph-parser 21 链接 未完成
PayPal SeLion 213 链接 未完成
PayPal NNAnalytics 60 链接 无妨
PayPal gimel 152 链接 未完成
PayPal aurora 81 链接 未完成
powermock powermock 2599 链接 未完成
SlimeKnights TinkersConstruct 592 链接 未完成 “我的世界”模组
sourcerer-io sourcerer-app 4523 链接 未完成
spinnaker spinnaker 6213 链接 未完成
spockframework spock 2368 链接 未完成
swagger-api swagger-codegen 9540 链接 未完成 代码生成器
target data-validator 12 链接 未完成
TheGreyGhost MinecraftByExample 549 链接 未完成
typelevel cats 3261 链接 无妨
uber uReplicator 493 链接 未完成
uber uberscriptquery 42 链接 未完成
uber chaperone 603 链接 未完成
WebGoat WebGoat 2546 链接 未完成
xtext maven-xtext-example 51 链接 未完成
总加星数 63960
Sheetsu.com提供

注意:“已完成”列写着“是”的项目已完全解决了问题,并且已审核过,或为其之前的版本发布了CVE编号。

下面是上表的Google Sheets地址,有兴趣可以去看看。

不安全依赖的解决方案

除了上面列出的项目之外,还有一些大型社区和组织也会受此漏洞影响。

“我的世界(Minecraft)”游戏模组

这是我找的第一个地方,不出所料,马上就找到了这个漏洞,在几乎所有模组的构建的基础架构中都有它。

JetBrains

考虑到Ktor事件可能不是一次性事件,我开始关注JetBrains在GitHub上的项目。
Kotlin 编译器

Kotlin是JetBrains开发的编程语言,可编译为JVM、LLVM和JavaScript,在Android开发人员中很受欢迎。谷歌最近指定Kotlin现在成为Android开发的首选语言

我在Kotlin编译器代码库中,发现了许多实例,它们的构建的基础设施和测试都通过HTTP下载依赖项.

不仅Kotlin编译器的源代码的依赖容易受到攻击,而且易受攻击的代码仓库也用在了Gradle的“buildscript”类路径,这增加了把牵连到的工件发布出去的潜在风险。

如果这还不够糟糕,那么buildscript类路径也用于解析以前版本的Kotlin编译器,从而使编译器可能遭受“Trusting Trust”攻击(参见下面更详细的内容)。

IntelliJ IDEA
IntelliJ和一些官方插件不仅容易受到攻击,而且很多情况下,创建启动项目会用到代码生成器,所以IntelliJ生成的项目也容易受到攻击。

Gradle

Gradle是一个有趣的案例。作为Gradle的贡献者,你不会受到此漏洞的影响。但是,当在Gradle公司的Team City CI基础设施上,用Gradle构建Gradle代码库时,该基础设施会覆盖一些默认值,改成用HTTP从JFrog Artifactory实例上获取工件。幸运的是,该基础设施与Gradle JFrog Artifactory服务器位于同一网络中。

话又说回来,Gradle公司的JFrog Artifactory服务器还通过HTTP为其他工件服务器建立镜像,因此可能会将这些镜像暴露给基于MITM的缓存中毒(cache poisoning)攻击。

Elastic Search

在撰写本文时,Elastic Search代码库有3.86万次加星,是GitHub上最受瞩目的Java项目。Elastic Search的主工程有超过1100个贡献者。因此我确定,Elastic构建里的测试逻辑部分易受此漏洞影响。

Apache

我在Apache软件基金会(Apache Software Foundation)的几个项目中发现了这个漏洞。

其中值得注意的将在下文列出。

截至本文发布之日,Apache软件基金会已决定不给受影响项目发布CVE编号。虽然这些项目大多没有统计过是否被此漏洞攻陷。
Groovy 编译器


Apache Groovy是在JVM上做开发最流行的替代品之一,也容易受到攻击。在撰写本文时,根据Tiobe索引,Groovy在世界​编程语言中受欢迎程度排名第19。与Kotlin类似,Groovy编译器的buildscript类路径有通过HTTP解析的依赖关系。这也导致了工件被破坏的可能性。

幸运的是,构建Groovy编译器的引导编译器完全用Java编写,因此受“Trusting Trust”攻击的可能性非常小。
此外,我还发现Groovy的Eclipse插件易受攻击。

Hadoop
Apache Hadoop有超过193个贡献者,成为贡献者最多的项目。所有贡献者在他们机器上运行的Hadoop构建都可能被MITM攻陷。
Kafka
Apache Kafka最初由LinkedIn团队编写,是一个快速的事件代理。LinkedIn在内部使用Kafka,每天摄取的信息条数已经超过1万亿条。我发现Kafka的构建系统是通过HTTP而不是HTTPS加载Gradle插件。

Apache其他项目
我发现,易受攻击的Apache项目包括但不限于以下项目:Casandra、Geode、Storm、Bigtop、Fink、OpenJPA、Royal Compiler和Airavata。

Jenkins

Jenkins在全球有超过100万用户,是使用最广泛的开源自动化服务器。

Jenkins社区宣布2017年的纪录增长和创新

Jenkins被用作自托管的CI管道,用于自动构建和测试软件。Jenkins和许多Jenkins官方插件都附带了通过HTTP下载的依赖项。

Spring

我在spring-security-oauth项目发现了第一个(漏洞)位置。Spring项目是我开始研究基于Maven的第一个项目,因此不得不找了一种完全不同的搜索方法,用来通过GitHub搜索功能检查Maven POM文件。我一开始寻找,就发现这个漏洞存在于Spring组织下的许多其他项目中。

Spring团队立即做出响应,开始修补他们的所有项目。因受Pivotal项目重度影响,Pivotal开发了一个工具,用以查找和替换整个代码库中所有使用HTTP的地方。该工具在此:
spring-io/nohttp

Red Hat

这个漏洞还影响了Red Hat维护的许多项目。这些项目包括但不限于Hibernate ORM、RestEasy和Wildfly(旧称JBoss)生态系统中的许多项目。

Eclipse基金会

与Red Hat和Apache基金会类似,漏洞也影响了Eclipse基金会的项目Vorto、Buildship、xtext、Orion和Birt。

Oracle

此漏洞还影响了Oracle的一些开源项目,包括VisualVM、PGQL、OpenGrok和Helidon。

测试库和框架

一些非常流行的JVM测试库和框架也很容易受到攻击,包括TestNG、Spock和PowerMock。

其他项目

其他项目,包括Grails、FasterJacksonXML和Ehcache3的Scala模块也发现了此漏洞。此外,我在网飞(Netflix)、谷歌、Twitter、美国国家安全局(NSA)、Stripe、Gluon(Scene Builder)PortSwigger、Black Duck、Snyk、LinkedIn和PayPal的开源项目中也发现了这个漏洞。讽刺的是,当我向PayPal的安全团队提交问题报告漏洞时,他们关闭了这个问题,因为他们认为MITM “超出了他们的HackerOne计划范围”。

MITM的常见程度如何?

我对常见的MITM的初步研究,源于我研究恶意破坏XML的解析器。这些解析器加载了通过HTTP加载的DTD文件,以实现XXE。相关信息以后找机会另写文章详述。我发现MITM的常见程度相当惊人。

互联网服务提供商

令我惊讶的是,互联网服务提供商(ISP)似乎经常做MITM。

康卡斯特开始向我在互联网上请求的页面注入400多行JavaScript代码,以便当浏览器渲染页面时,用JavaScript生成弹出窗口,向我推销新的调制解调器。

引用自:康卡斯特持续将自己的代码注入您访问的网站

印度的Bharat Sanchar Nigam Limited(BSNL)也曾将广告注入用户通过HTTP访问的网页。

这就说明,MITM的基础条件早已具备,稍加利用就能影响JAR文件。

恶意行为者

当恶意行为者获得对系统的访问权限时,他们通常会迅速利用新的立足点来建立MITM。Verizon每年都会发布数据泄露调查报告(Data Breach Investigation Report,DBIR),分析每年最常被利用的各种攻击媒介。下面引用自他们的一份报告。

行为
三大威胁行为是黑客入侵、恶意软件和社会工程学。最常见的黑客入侵行为的类型是使用被盗的登录凭据、利用后门程序和中间人(man-in-the-middle,即MITM的全写)攻击。
引用自: Verizon 2011数据违规调查报告;第69页

引用自该报告的分析:

我推测,一旦黑客已在系统中立足,MITM就比较次要了。但荷兰高科技犯罪部门的数据显示,MITM本身就值得关注的——在他们统计到的32个数据泄露事件中,有15个涉及MITM行为。
引用自:Stack Exchange上的回答:“中间人”攻击极为罕见吗?

应把MITM攻击视为软件安全中确定存在的威胁。

通过公共WiFi连接

抛开所有其他攻击媒介,开发人员通过公共WiFi从事这些项目的工作,都等同于放开了他们的电脑,可能会受到恶意攻击。这种攻击可以用著名的Firefox插件Firesheep演示。

WiFi热点的潜在危害可能会对开发人员产生重大影响,因为他们很多人会在咖啡店、开发者大会等地方使用公共WiFi。只需要WiFi Pineapple,加上他们电脑未缓存过的依赖就可以感染他们的电脑了。

政府机构

拜斯诺登所赐,我们现在知道了美国政府三个邮件中介(letter agencies)对美国公民进行MITM攻击的各种方法。

NSA靠跟美国电信公司的秘密合作伙伴关系,诱使目标访问FoxAcid服务器。作为Turmoil系统的一部分,NSA将秘密服务器(代号为Quantum)放置在互联网骨干网的关键位置,确保它们可以比其他网站更快响应。靠这个速度差,这些服务器可以在合法网站响应之前,模拟成目标要访问的网站,从而欺骗目标的浏览器访问Foxacid服务器。
引用自: NSA如何使用QUANTUM和FOXACID攻击Tor/Firefox用户

以前,由于BGP路由配置错误,美国国内的互联网流量也有过通过国外路由的历史。

通过HTTP加载的最常见的存储库

让我们看一下使用HTTP的最常见代码库的一些统计信息。请注意,这些数字并不精确,可能略微大些,因为GitHub的搜索本质上是模糊搜索。

Maven中央仓库(Maven Central)

Maven中央仓库是JVM生态系统中最常用的工件服务器,是Maven使用的默认工件服务器,是JVM工件托管空间中的第一个主要参与者。

JFrog JCenter

JCenter是Maven中央仓库的超集。开发人员把他们的工件发布到JFrog Bintray后,可以请求在此创建他们工件的镜像。

JFrog Bintray

JFrog Bintray让开发人员可以为开源项目免费创建自己的工件服务器。

公司 服务器 URL 使用Maven数 使用Gradle数
Sonatype Maven Central 链接 ~4万 ~5600
Sonatype Maven Central 链接 偏斜数据(Skewed Data) ~11800
JFrog JCenter 链接 ~15200 ~37200
JFrog Bintray 链接 ~7300 ~17300
Pivotal Spring 链接 ~187000 ~27000
Sheetsu.com提供

显然,这是Gradle和Maven项目中广泛存在的一个安全漏洞。

编写一个(理论上的)Java库蠕虫

作为一个思维实验,我草拟了滥用此MITM漏洞来创建Java库蠕虫的理论。实验结果参见此处:
让咱们写一个(理论上的)Java库蠕虫
若你觉得“太长不看”,简单说来如下图:

该漏洞的后果是,在发布期间使用有MITM漏洞的依赖,可能会让恶意代码攻陷构建出来的工件,从而感染下游用户。

修复过去

对于已经发布的库,除非这些项目构建是完全可重复的,否则无可奈何。

对于易受此影响的编译器(Kotlin)、用于测试自己的测试库(Spock和TestNG)、用于构建自己的构建工具(Gradle),这可能是一个问题,因为信任链已被打破。大多数编译器都用于编译自己。有关此主题的更多信息,请参阅Ken Thompson写的论文《Reflections on Trusting Trust》,这篇相对较短。

修复未来

我认为像Gradle、Maven和SBT这样的构建工具,应该默认用HTTPS解析依赖关系,除非用户明确声明不用HTTPS。这将迫使用户明确声明使用不安全的协议,从而防止不小心写错。我向Gradle和Maven都提出了要求实现该功能的提案,链接如下,请帮我投个赞成票!

Deprecate HTTP Download by JLLeitschuh · Pull Request #9419 · gradle/gradle

[MNG-6673] Deprecate HTTP Download & Upload - ASF JIRA

代码仓库的自动审查

Pivotal开发的nohttp工具可以查找所有出现的HTTP,除了列入白名单的HTTP(比如XML命名空间名称)。这将确保HTTP不会在其他地方引起问题(比如Gradle Wrapper位置,DTD声明等)。它可以寻找和替换“HTTP”,并集成在构建里,确保将来不使用HTTP。
spring-io/nohttp

工件主机将在2020年1月弃用HTTP

随着此漏洞的范围变得越来越大,我很快意识到,修复这个漏洞的一些责任在Maven Central和JCenter等工件主机上。我联系了两个最大的工件主机Sonatype(Maven Central)、JFrog(JCenter),以及Pivotal(Spring)、Eclipse Foundation、Jenkins、Red Hat和JetBrains等较小的主机,询问它们是否愿意从2020年1月15日起完全阻止通过HTTP发出的下载请求。

25%的Maven Central下载仍在使用HTTP

JFrog和Pivotal很快就都告诉我他们会跟进。

个人容易受到这种影响吗?

鉴于我发现许多广泛使用的开源项目都存在这个漏洞,我建议任何开发JVM软件的人,都应检查代码库的构建逻辑,以解决使用HTTP依赖的问题。

我需要找什么?

对于Gradle,你应该寻找像这样的代码库配置。

// 这些依赖项用于整个构建的类路径
	buildscript {
	    repositories {
	        maven {
	            url 'http://[SOME URL HERE]'
	        }
	    }
	    // ...
	}
	

	// 这些依赖项用作编译器的输入,并用于测试的类路径
	repositories {
	    maven {
	        url 'http://[SOME URL HERE]'
	    }
	}
	// ...
	

	// 这是没有安全上传构建工件的一个例子。
	// 若你找到了这个,那么用于上传的证书可能就受到了威胁。
	uploadArchives {
	    repositories {
	        mavenDeployer {
	            snapshotRepository(url: 'http://[SOME URL HERE]') {
	                authentication userName: repoUser, password: repoPassword
	            }
	            repository(url: 'http://[SOME URL HERE]') {
	                authentication(userName: repoUser, password: repoPassword);
	            }
	        }
	    }
	}

Gradle开发人员可能还应检查所有init.gradle脚本,它们在其公司内部分发,但一般不检入源代码管理系统。

对于基于Maven的项目,你要寻找像这样的代码库配置。

<!-- 这些依赖项用作编译器的输入,并用于测试的类路径 -->
	<repositories>
	  <repository>
	    <id>[SOME ID]</id>
	    <name>Example insecure repository</name>
	    <url>http://[SOME URL HERE]</url>
	  </repository>
	</repositories>
	
	<!-- ... -->	

	<!-- 这是没有安全上传构建工件的一个例子。 -->
	<!-- 若你找到了这个,那么用于上传的证书可能就受到了威胁。 -->
	<distributionManagement>
	  <repository>
	    <id>[SOME ID]</id>
	    <name>Example insecure repository</name>
	    <url>http://[SOME URL HERE]</url>
	  </repository>
	</distributionManagement>
	

	<!-- 这些依赖项用于整个构建的类路径 -->
	<pluginRepositories>
	  <pluginRepository>
	    <id>[SOME ID]</id>
	    <name>Example insecure repository</name>
	    <url>http://[SOME URL HERE]</url>
	  </pluginRepository>
	</pluginRepositories>

Maven开发人员还应该检查~/.m2/settings.xml文件中的配置,因为代码库凭据通常就存在这里。

此外,JFrog Artifactory或Sonatype的Nexus的企业用户,应检查其服务器的配置,看它们是否通过HTTP创建了其他工件服务器的镜像。

在JFrog Artifactory中不安全的配置的例子

我已经联系了Sonatype和JFrog,要求他们在未来的更新中,对不安全的配置向用户/管理员提出警告。

JFrog回应说,该功能已正式成为他们路线图的一部分,但还没有计划发布日期。

如果发现此漏洞,该怎么办?

要把执行潜在恶意Jar的整个机器(开发机、构建机等)看成可能被攻陷了。这也意味着该机器可以访问的任何内容(其他项目、凭据、其他主机等)也应该视为可能被攻陷了。共享工件的缓存,如~/.gradle和~/.m2目录,其中的Gradle和Maven的缓存工件都应视为已受污染,应该删除。为避免单个易受攻击的应用程序连累其构建的每个项目,最佳做法是隔离构建。

如果你是易受此攻击的开源项目的维护者,那么你有责任审查先前的版本,或提交CVE编号,通知下游用户可能存在的危害。

结束语

不幸的是,我只能联系受此漏洞影响的一小部分项目。你在工作中依赖的许多开源项目可能都容易受此影响。如果你可以,请联系你发现的受影响项目,一起保护Java生态系统。

如果你使用开源软件,或用这些构建工具开发商业软件,我强烈建议:为整个软件供应链的安全,请审查你的构建。

特别鸣谢

感谢我联系的所有组织中,所有真正令人敬畏的专业安全团队和项目维护人员。我自己是绝不可能修补所有地方的。其中一些团队,在我报告后几小时内就做出回应,并在第二天就推出修复程序。另外,我要感谢Snyk愿意做这些CVE报告的CNA。我还要感谢Max Veytsman创造了Dilettante。用POC使披露流程更加顺畅。

深入研究的附注

如果你是一名安全研究人员,并希望在其他Java项目中发现这些安全漏洞,我可能漏了说明我在Github搜索时用的查询条件,补充如下:

在GitHub搜索功能里查询漏洞时可用以下查询条件

在GITHUB_ORGANIZATION的Gradle构建文件里搜索使用“http://”之处

https://github.com/search?l=Gradle&q=org%3A[GITHUB_ORGANIZATION]+http%3A%2F%2F&type=Code

在工程的源代码里搜索代码仓库的通用查询条件

https://github.com/search?q=org%3A[GITHUB_ORGANIZATION]+repositories&type=Code

在Gradle Builds里搜索的特殊查询条件

https://github.com/search?l=Gradle&q=org%3A[GITHUB_ORGANIZATION]+repositories&type=Code

在Maven POM文件里搜索的特殊查询条件

https://github.com/search?l=Maven+POM&q=org%[GITHUB_ORGANIZATION]+repositories&type=Code
https://github.com/search?l=Maven+POM&q=org%[GITHUB_ORGANIZATION]+repository&type=Code

如果你用这些查询条件在某项目中发现此问题,请指回本文。

检查发布版本异同的工具

原文链接:

https://medium.com/bugbountywriteup/want-to-take-over-the-java-ecosystem-all-you-need-is-a-mitm-1fc329d898fb

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章