Clojure关键字示例安全问题

4
阅读完这个问题Clojure关键字从用户数据创建的安全隐患?,特别是这个答案后,我试图在REPL中找到一个可以演示该问题的案例。 以下是一次尝试:
user> *clojure-version*
{:major 1, :minor 8, :incremental 0, :qualifier nil}
user> (def a (atom 0))
#'user/a
user> (defn bad-fn []
        (println "called ")
        (swap! a inc))
#'user/bad-fn
user> @a
0
user> (keyword "#=(bad-fn)")
:#=(bad-fn)
user> @a
0

我该如何重现这个问题?

1个回答

6
问题不在于调用字符串上的keyword函数会立即执行嵌入在字符串中的任何代码,而是如果您想将例如(keyword "foo #=(println :bar)")的字符串表示存储在文件中,然后使用read消耗该文件,您最终会执行嵌入的代码。
当然,根本不建议read用户提供的字符串,但问题是关于安全性,因此答案(Brian和我)描述了与特定命名的keyword函数一起误用各种设施可能导致的安全问题。
使用clojure.edn(2010年发布该问题时不可用)可以减轻#=问题,但不解决更广泛的问题,即无论使用哪个读取器,都不应该期望能够将(keyword <arbitrary-string>)的字符串表示读回为相同的关键字。忽略这一点很容易导致数据损坏。

2
简短示例(数据损坏):{(关键字"a :b"):c} - cfrick
关键字应该被内部化为symbols,其中空格不是有效字符。 - Thumbnail
1
@缩略图 首先,2010年的原始问题涉及在用户数据上调用 clojure.core/keyword 的实际安全影响。clojure.core/keyword 不验证其输入以检查是否包含空格,因此虽然规范可能不允许带有空格的关键字,但如果向其中传递任意的用户提供的字符串,则完全可以创建这样的关键字。其次,读取器故意接受符合该规范“不正确”的(无空格)关键字——回到2013年,提交了一个使其更加严格的补丁,但破坏了现有代码并被撤销了。 - Michał Marczyk
1
最后一点的参考资料:CLJ-1252clojure-dev threadAlex Miller的关键信息),CLJ-1252提交撤消提交 - Michał Marczyk
1
还要注意的是,符号字面量规范目前不包括 <>= - 请参见此问题。虽然这与 keyword 的行为直接相关,但它表明即使读取器对符号和关键字字面量比规范更宽容。 </end tangent>;-) - Michał Marczyk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接