inotifywait 的潜在解决方法无法生成 NUL 分隔的输出

inotifywait 的潜在解决方法无法生成 NUL 分隔的输出

我目前正在编写一个 bash 脚本,它使用inotifywait对用户提供的文件和目录列表执行某些操作。

它引起了我的注意与许多 shell 工具不同,inotifywait它无法使用\0.这留下注入攻击的可能性具有专门设计的合法文件名(包含换行符)。

我想解决这个问题,以确保我的脚本不会引入任何不必要的漏洞。我的做法如下:

  • 确保传递给观看的所有文件/路径inotifywait都删除了尾部反斜杠
  • 格式化inotifywait输出以--format "%e %w%f//"产生输出,如下所示:
    • <EVENT LIST> <FILE PATH>//
  • 通过管道inotifywait输出到 sed;任何//在行尾发现的\0
  • 使用 bashwhile 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[]}数组只是从命令行参数复制的,但该数组可能以其他方式构建,并且可能包含“有趣”的字符。

  1. 是否有任何恶意路径可以打破这个?即使$events和变量的内容$filepath对于任何给定事件都是不正确的?

  2. 如果这是不漏水的,有没有更清洁的方法可以做到这一点?

注意我知道我可以轻松地写一个打电话inotify_add_watch()给朋友的程序来解决这个问题。但现在由于其他依赖项,我正在 bash 中工作。


我对于是否将其发布在此处或 codereview.SE 甚至主要的 so.SE 一直存在冲突。

答案1

支持 NUL 分隔输出,您可以像这样使用它:

#!/bin/bash

shopt -s extglob
watchlist=("${@}")

# Remove trailing slashes from any watchlist elements
watchlist=("${watchlist[@]%%+(/)}")

printf -vnewline "\n"

inotifywait -qrm "${watchlist[@]}" --format "%e %w%f%0" | \
while IFS= read -r -d '' line; do
    events="${line%% *}"
    filepath="${line#* }"
    printf "events=%s\nfilepath=%q\n" "$events" "$filepath"
done

请注意,当使用 --format 时,此版本默认不添加换行符。

答案2

您需要清理watchlist以将 any 替换///。考虑一个名为\nabc(其中\n为换行符) 的目录:

$ mkdir t
$ mkdir t/$'\nabc'
$ touch t/$'\nabc'/x

如果通过目录,您将在行尾t//$'\nabc'看到伪造的输出://

$ inotifywait -m -r t//$'\nabc' --format "%e %w%f//" 
Setting up watches.  Beware: since -r was given, this may take a while!
Watches established.
OPEN t//
abc/x//
ATTRIB t//
abc/x//
CLOSE_WRITE,CLOSE t//
abc/x//

请注意,您也可以使用-c而不是--format获取数据集样式输出,用换行符双引号文件名,但更难解析,在我的例子中,核心转储在上面的示例中。

-c和的输出示例touch t/$'new\nfile'

t/,CREATE,"new
file"

相关内容