Common Lisp 格式指令的安全解析
Safe Parsing of Format Directives in Common Lisp
我想从输入文件(用户可能已修改也可能未修改)中读取字符串。我想将此字符串视为要使用固定数量的参数调用的格式指令。但是,我知道某些格式指令(特别是想到 ~/
)可能会被用于注入函数调用,从而使这种方法本质上是不安全的。
在Common Lisp中使用read
解析数据时,该语言提供了*read-eval*
动态变量,可以设置为nil
来禁用#.
代码注入。我正在寻找类似的东西,可以防止格式指令内的代码注入和任意函数调用。
您需要担心的不仅仅是 ~/。漂亮的打印机功能有很多代码扩展的可能性,甚至 ~A 也会导致问题,因为对象可能在 print-object 上定义了方法.例如,
(defclass x () ())
(defmethod print-object ((x x) stream)
(format *error-output* "Executing arbitrary code...~%")
(call-next-method x stream))
CL-USER> (format t "~A" (make-instance 'x))
Executing arbitrary code...
#<X {1004E4B513}>
NIL
我认为您需要自己定义哪些指令是 安全的,使用您认为重要的任何标准,然后仅包括那些。
如果用户不能引入自定义代码而只是格式化字符串,那么就可以避免print-object
的问题。请记住使用 with-standard-io-syntax
(或它的自定义版本)来控制您将生成的确切输出类型(想想 *print-base*
,...)。
您可以扫描输入字符串以检测 ~/
的存在(但 ~~/
有效)并拒绝解释包含列入黑名单的结构的格式。
但是,有些分析比较困难,您可能需要在运行时进行操作。
例如,如果格式字符串格式不正确,您可能会遇到必须处理的错误(此外,您可能会为预期的参数提供错误的值)。
即使用户没有恶意,您也可能会遇到迭代构造问题:
~{<X>~:*~}
... 永远不会停止,因为 ~:*
倒回当前参数。为了处理这个问题,您必须考虑 <X>
可能会或不会打印某些内容。您可以实施这两种策略:
- 有一个超时来限制格式化所花费的时间
- 当写入过多时(例如写入字符串缓冲区),让底层流到达文件末尾。
可能还有其他我目前没有发现的问题,请注意。
我想从输入文件(用户可能已修改也可能未修改)中读取字符串。我想将此字符串视为要使用固定数量的参数调用的格式指令。但是,我知道某些格式指令(特别是想到 ~/
)可能会被用于注入函数调用,从而使这种方法本质上是不安全的。
在Common Lisp中使用read
解析数据时,该语言提供了*read-eval*
动态变量,可以设置为nil
来禁用#.
代码注入。我正在寻找类似的东西,可以防止格式指令内的代码注入和任意函数调用。
您需要担心的不仅仅是 ~/。漂亮的打印机功能有很多代码扩展的可能性,甚至 ~A 也会导致问题,因为对象可能在 print-object 上定义了方法.例如,
(defclass x () ())
(defmethod print-object ((x x) stream)
(format *error-output* "Executing arbitrary code...~%")
(call-next-method x stream))
CL-USER> (format t "~A" (make-instance 'x))
Executing arbitrary code...
#<X {1004E4B513}>
NIL
我认为您需要自己定义哪些指令是 安全的,使用您认为重要的任何标准,然后仅包括那些。
如果用户不能引入自定义代码而只是格式化字符串,那么就可以避免print-object
的问题。请记住使用 with-standard-io-syntax
(或它的自定义版本)来控制您将生成的确切输出类型(想想 *print-base*
,...)。
您可以扫描输入字符串以检测 ~/
的存在(但 ~~/
有效)并拒绝解释包含列入黑名单的结构的格式。
但是,有些分析比较困难,您可能需要在运行时进行操作。
例如,如果格式字符串格式不正确,您可能会遇到必须处理的错误(此外,您可能会为预期的参数提供错误的值)。
即使用户没有恶意,您也可能会遇到迭代构造问题:
~{<X>~:*~}
... 永远不会停止,因为 ~:*
倒回当前参数。为了处理这个问题,您必须考虑 <X>
可能会或不会打印某些内容。您可以实施这两种策略:
- 有一个超时来限制格式化所花费的时间
- 当写入过多时(例如写入字符串缓冲区),让底层流到达文件末尾。
可能还有其他我目前没有发现的问题,请注意。