# 黑客故事：如何接管Java/Clojure/Scala程序员的电脑

- URL: https://wuming.si/blog/757/
- Author: Aaron
- Published: 2014-08-20
- Language: zh-Hans
- Categories: Uncategorized
- Originally published at: http://blog.wo.ai/archives/757

Sonatype已经对此帖做出了相应的反应，并在他们的[博客](http://blog.sonatype.com/2014/07/ssl_connectivity_for_central/ "SSL Connectivity")上声明将会对所有的用户开启SSL链接。这变化让Java程序的生态系统变得更加安全可靠，我为此感到非常高兴。

虽说如此，但如果当你看到这个博客，并考虑花10美元来评估你的产品是否需要这个安全性的需要时，答案是否定的。这就好比汽车公司决定花10美元来评估他们的汽车是否需要气囊。幸运的是，现实生活中汽车公司必须安装气囊。

Sonatype的这次机制修改令我感到很开心，希望他们能够继续减少安全性与产品的冲突。对于我们开发者而已，为用户提供最安全的最有保障的产品是我们的责任。用户对于不能处理好产品与安全性的容忍度能有多大。

有一天，我看到我的防火墙是这么设置的，于是我开始对我的一个Clojure项目进行入侵：

![](http://blog.wo.ai/wp-content/plugins/wp-o-matic/cache/49290757de_7cc829d3gw1ejg1uu2rt3j20k90bfaat.jpg)

然后我通过80端口在 [http//repo.maven.apache.org](http://repo.maven.apache.org/)下载了clojure.jar。这意味着我将能够通过一个未加密的http来下载包。我一开始认为这是[leiningen](http://leiningen.org/)的[问题](https://github.com/technomancy/leiningen/issues/1604)。但结果完全不是。Clojure.jar和其他许多的jar包在Java/Clojure/Scala领域都很重要，他们都会被正式的放在Sonatype提供的一个公共服务 –[ Maven Central](http://search.maven.org/)。[Sonatype](http://www.sonatype.com/)有一个机制：只有那些拥有身份标识的人才允许SSL链接。你需要通过捐给Apache基金会十美元，才能获得身份标识和SSL链接。如果你不相信我说的话，捐赠的网页[在这](http://www.sonatype.com/clm/secure-access-to-central)，此机制[在此](http://www.sonatype.com/clm/secure-access-to-central)博客上声明。这里面甚至提到了中间人攻击。

因为身份标识是针对个人或者组织分发，所以像maven或者leiningen这些工具不能绑定它。如果你使用这些工具，那么下载java程序或者安装它的一些依赖不会通过SSL。经过我在twitter和Sonatype的一个员工对此事进行了争论，确认了此事。

![](http://blog.wo.ai/wp-content/plugins/wp-o-matic/cache/08213c2971_7cc829d3gw1ejg1uummb7j20hr0hdq5a.jpg)

你下载的jar包会来自中间人的，并且你执行的代码会被恶意软件替换过。要想阻止这类的事情发生，你需要小心的执行每一步操作，稍有不慎就会支付别人十美元。

通常什么时候会发生这类事情？如果你曾链接过咖啡店的公共网络或者[别人的无线网络](https://ettercap.github.io/ettercap/)，中间人就能和你通信了。你的网络服务提供者应能够随意的跟你通信，有的人这么做是为了打广告。或者，你也会还会遭受来自[国家操纵](http://www.renesys.com/2013/11/mitm-internet-hijacking/)的这类攻击。

**Dilettante**

为了证明这有多么容易，我写了一个中间人代理[dilettante](https://github.com/mveytsman/dilettante)，它功能是拦截来自于maven central的JAR包然后再注入恶意代码进去。

通过dilettante来代理http的传输，然后给任何在maven central下载的JAR包设置后门。那个设置了后门的版本同时会保留原有的功能，但是当他们使用的这个类库的时候，将会提示一个友好的信息。你可以[看这个视频](http://blog.ontoillogical.com/blog/2014/07/28/how-to-take-over-any-java-developer/)：  
或者截图：

![](http://blog.wo.ai/wp-content/plugins/wp-o-matic/cache/36c7f54902_7cc829d3gw1ejg1uvfdy3j20zh0laadp.jpg)

源代码[在这](https://github.com/mveytsman/dilettante)。

**具体实现**

JAR包从maven central 下载的时候，由于是通过HTTP进行传输的，因此中间人可以随意的替换。JAR包是可以被标识的，但是根据我对于标准工具使用的经验，这些标识是不会被检查的。其他唯一的方法可以验证一个也是通过HTTP传输的SHA1和。当dilettante发现有JAR来自maven central，它将会把一个拥有后门的版本来替换成原来的。然后替换后的版本将会在受害者的电脑上运行恶意的代码。由于SHA1仅是通过HTTP传输，那么dilettante会简单地将它所能看到的所有哈希表替换成对应的拥有后面JAR包的哈希表。

我用优秀的mitproxy类库来创建我的工具。我先为代理写一个inline script，然后又用libmproxy创建一个独立的工具。
    
    
    package dilettante;
    
    public class Dilettante {
        public static void() {
            // do some evil stuff
        }
    }

JAR包只是一个包含资源，类和元数据的压缩包。我通过添加自己的类到JAR，从而给这个JAR设置了后门。

稍微头疼的是想办法如何调用我的恶意代码。我知道受害者肯定会下载一些类库。然而我需要不管用户调用类库中的哪个类，它都能运行我的代码，并且还不能影响以前类库的正常使用。

Java有静态类块这一概念，它能在类级别进行初始化。当类加载到内存的时候，静态类里面的代码会只被调用这一次。在我把恶意的类插入到Jar包之后，我就能像下面这样在静态块里面调用代码：
    
    
    import dilettante.*;
    static {
        Dilettante.backdoor();
    }

为了插入上面的代码，我需要将它直接插入到Java class里面，而不是source文件。我是使用[Karakatau](https://github.com/Storyyeller/Krakatau)将代码以[Jasmin](http://jasmin.sourceforge.net/)的格式插入进去。Karakatau是一个针对Python的Java 反编译/编译类库。
    
    
    .method static <clinit> : ()V
      ; method code size: 4 bytes
      .limit stack 0
      .limit locals 0
      invokestatic dilettante/Dilettante backdoor ()V
      return
    .end method

**局限性**

这只是个概念化的试验，同时它还是存在局限性。

1.目前由于一些原因，它还不是很快：

我必须进行反编译和编译。如果能够直接插入编译好的代码到类里面，那就更高效了。

我实际上是通过使用Python的zipfile类库将压缩包的类文件都创建了个副本。从空间和速度方面而言，这是不高效的。如果能够更加了解zip的功能，可能会找到一个高效插入数据的方法。

2.如果用户同时下载多个JAR包。那么我将会逐个设置后门。恶意的代码在每个JAR只会被执行一次。但是如果多个jar被设置了后门，那么它将会被执行多次。如果我们将那个猫的图片替换成一个高质量，稳定的后门并且它能够只影响系统一次，那么这个问题就不会再出现。

[黑客故事：如何接管Java/Clojure/Scala程序员的电脑](http://blog.jobbole.com/75167/)，首发于[博客 – 伯乐在线](http://blog.jobbole.com)。
