security - 在没有用户输入的情况下在lua中执行外部程序作为lua中的参数
问题描述
我想在lua中执行一个外部程序。通常这可以用
os.execute("run '"..arg0.."' 'arg1' arg2")
这种方法的问题是,如果我想将用户输入作为字符串传递给外部程序,用户输入可能是'; evil 'h4ck teh system' '
并且上面的脚本将像这样执行:
/bin/bash -c "run ''; evil 'h4ck teh system' '' 'arg1' arg2"
当我有'$var'
as 参数并且 shell 用它的环境变量替换它时,会出现另一个问题。在我的特殊情况下,我有类似的东西[[program 'set title "$My Title$"']]
- 所以嵌套的字符串 - 并且program
解析"$My Title$"
(使用转义序列)与'$My Title$'
(原样)不同。因为我想将标题设置为它,所以最好的方法是有这样的参数:'My Title'
. 但现在命令必须是:
os.execute([[run "set title '$My Title$'"]])
但是现在——正如我所说的——$My
将被替换为一个空字符串,因为环境不知道任何命名的变量$My
,因为我从不希望它被替换。
所以我正在寻找通常的方法
execv("run", {"set title '"..arg0.."'", arg1, arg2})
解决方案
local safe_unquoted = "^[-~_/.%w%%+,:@^]*$"
local function q(text, expand) -- quoting under *nix shells
-- "expand"
-- false/nil: $var and `cmd` must NOT be expanded (use single quotes)
-- true: $var and `cmd` must be expanded (use double quotes)
if text == "" then
text = '""'
elseif not text:match(safe_unquoted) then
if expand then
text = '"'..text:gsub('["\\]', '\\%0')..'"'
else
local new_text = {}
for s in (text.."'"):gmatch"(.-)'" do
new_text[#new_text + 1] = s:match(safe_unquoted) or "'"..s.."'"
end
text = table.concat(new_text, "\\'")
end
end
return text
end
function execute_commands(...)
local all_commands = {}
for k, command in ipairs{...} do
for j = 1, #command do
if not command[j]:match"^[-~_%w/%.]+$" then
command[j] = q(command[j], command.expand)
end
end
all_commands[k] = table.concat(command, " ") -- space is arguments delimiter
end
all_commands = table.concat(all_commands, ";") -- semicolon is commands delimiter
return os.execute("/bin/bash -c "..q(all_commands))
end
使用示例:
-- Usage example #1:
execute_commands(
{"your/program", "arg 1", "$arg2", "arg-3", "~/arg4.txt"},
{expand=true, "echo", "Your program finished with exit code $?"},
{"ls", "-l"}
)
-- The following command will be executed:
-- /bin/bash -c 'your/program '\''arg 1'\'' '\''$arg2'\'' arg-3 ~/arg4.txt;echo "Your program finished with exit code $?";ls -l'
$arg2
根据您的需要,不会因为它周围的单引号而扩展为值。
不幸的是,"Your program finished with exit code $?"
也不会被扩展(除非你明确地设置expand=true
)。
-- Usage example #2:
execute_commands{"run", "set title '$My Title$'", "arg1", "arg2"}
-- the generated command is not trivial, but it does exactly what you need :-)
-- /bin/bash -c 'run '\''set title '\''\'\'\''$My Title$'\''\'\'' arg1 arg2'
推荐阅读
- git - .gitignore 不会忽略特定文件
- docker - 尝试在 docker 容器中运行 GUI 时为什么出现“无效的参考格式”?
- php - 更改单元格的 textFormat 会破坏 Google 工作表中的超链接
- python - 是否可以修改存在于函数范围之外的列表?
- python - 如何从同一id/person的其他行填充大型数据框中的缺失数据?
- c - 使用 mingw 从 Linux 编译 SDL2 windows EXE '应用程序无法正确启动'
- c# - 调整 LCS 算法以获得最小不变的运行长度
- c# - 如何在 C# 和 C++ 之间共享原始数据?
- machine-learning - 如何公平地比较基线和 GridSearchCV 结果?
- java - Java SpringBoot 和 JSON 文件的理解——会付费