我目前正在编写一个 bash 脚本,用于inotifywait
对用户提供的文件和目录列表执行某些操作。
我注意到,与许多 shell 工具不同,inotifywait
它无法使用\0
. 这留下了使用专门制作但合法的文件名(包含换行符)进行注入攻击的可能性。
我想解决这个问题,以确保我的脚本不会引入任何不必要的漏洞。我的方法如下:
- 确保传递
inotifywait
给观看的所有文件/路径都删除了尾随反斜杠 - 格式化
inotifywait
输出--format "%e %w%f//"
以产生如下输出:<EVENT LIST> <FILE PATH>//
- 管道
inotifywait
输出到 sed;任何//
在行尾发现\0
- 使用 bash
while read
循环读取 -\0
分隔的记录 - 这意味着在第一条记录之后,所有后续记录都将有一个额外的前导换行符。这是剥离
- 然后可以在第一个空格处拆分每个记录 - 在空格之前是事件列表(按照 inotifywait 逗号分隔) - 在空格之后是与事件关联的完整路径名
#!/bin/bash
shopt -s extglob
watchlist=("${@}")
# Remove trailing slashes from any watchlist elements
watchlist=("${watchlist[@]%%+(/)}")
# Reduce multiple consecutive slashes to singles as per @meuh
watchlist=("${watchlist[@]//+(\/)/\/}")
printf -vnewline "\n"
inotifywait -qrm "${watchlist[@]}" --format "%e %w%f//" | \
sed -u 's%//$%\x00%' | \
while IFS= read -r -d '' line; do
line="${line#${newline}}"
events="${line%% *}"
filepath="${line#* }"
printf "events=%s\nfilepath=%q\n" "$events" "$filepath"
done
据我所知,它处理包含有趣字符的文件/路径名 - 空格、换行符、引号等。但这似乎是一个相当不雅的组合。
出于这个问题的目的,${watchlist[]}
数组只是从命令行参数复制而来,但这个数组可能会以其他方式构建,并且可能包含“有趣”的字符。
是否有任何恶意路径可以破坏这一点?即,对于任何给定的事件,使
$events
和$filepath
变量的内容不正确?如果这是防水的,有没有更清洁的方法可以做到这一点?
注意我知道我可以很容易地编写一个c程序来调用inotify_add_watch()
和朋友来解决这个问题。但现在由于其他依赖关系,我正在使用 bash。
我一直对是否在此处发布此内容或 codereview.SE 甚至主要的 so.SE 存在冲突。
有支持 NUL 分隔输出的fork,您可以像这样使用它:
请注意,使用 --format 时,此版本默认不添加换行符。
您需要进行消毒
watchlist
才能将任何内容//
替换为/
. 考虑一个名为\nabc
(\n
换行符在哪里)的目录:如果通过了目录,您将在行尾
t//$'\nabc'
看到带有虚假的输出://
请注意,您也可以使用
-c
而不是--format
获取csv样式的输出,它用换行符对文件名进行双引号,但它更难解析,在我的例子中,核心转储在上面的示例中。-c
和的示例输出touch t/$'new\nfile'
: