如何在 bash 中转义 3 级(su 命令,psql,然后查询)

How to escape 3 level in bash (su command, psql, then query)

我正在编写一个 bash 脚本,用于在服务器上安装应用程序并为该应用程序创建一个 postgresql 用户。

问题在于,如果用户包含特殊字符,则不会对其进行转义。所以我想在查询中转义名称。

这是我的部分代码:

db_user="test-test"
db_password=1234
su - postgres -c "psql -c \"CREATE USER $db_user WITH PASSWORD '$db_password';\""

所以我要逃走:

当然,如果我在 $db_user 周围添加引号,它就不再起作用了。我尝试了其他解决方案,但 none 有效。

有什么想法吗?

谢谢

让 shell 为您代劳。在这种情况下,这意味着 printf '%q' —— returns 每个文字参数的 eval 安全版本。

cmd=( psql -c "CREATE USER $db_user WITH PASSWORD '$db_password';" )
printf -v cmd_q '%q ' "${cmd[@]}"
su - postgres -c "$cmd_q"

顺便说一下,以这种方式将文字文本替换为 SQL 查询是非常不安全的——但是如果您按照上述过程进行操作,您很可能只会出现 SQL 注入错误,而不是 shell 注入错误。


为了避免 SQL 注入错误,您希望完全避免将值文本替换到您的查询中。

# This is inefficient, but makes it completely unambiguous that our heredocs are literal
query=$(cat <<'EOF'
CREATE USER :new_user_name WITH PASSWORD :'new_user_password';
EOF
)

cmd=(
  psql \
    --set=new_user_name="$db_user" \
    --set=new_user_password="$db_password"
    -c "$query"
)

printf -v cmd_q '%q ' "${cmd[@]}"
su - postgres -c "$cmd_q"

http://caryrobbins.com/dev/postgres-scripting/ for more on this technique. The classic XKCD linked in its header (also useful as a concrete example of the risks the original code was taking!) has its original source at https://xkcd.com/327/