[英]How does IPC::System::Simple capturex work?
The documentation of capurex
, states that the function never invokes the shell . capurex
的文档指出 function永远不会调用 shell 。
My assumption: Since no shell is invoked, characters like *
or ;
我的假设:由于没有调用 shell,因此*
或;
等字符will not get interpreted and therefore can't do harm.不会被解释,因此不会造成伤害。 This is why calls to external programs are not (or less) susceptible to accidentally malformed input or intended injection attacks as shown in the example below (sorry for the German output messages):这就是为什么对外部程序的调用不会(或更少)容易受到意外错误输入或预期注入攻击的影响,如下例所示(对于德国 output 消息感到抱歉):
use v5.26;
use IPC::System::Simple 'capturex';
# (very) vulnerable to shell injection
say `ls @ARGV`;
# just a visual line
say '----------';
# no shell injection "possible" (?)
say capturex('ls', @ARGV);
The output: output:
user@host:-$ perl shell-injection.pl -1 \*.pl \; hostname
shell-injection.pl
host
----------
ls: Zugriff auf '*.pl' nicht möglich: Datei oder Verzeichnis nicht gefunden
ls: Zugriff auf ';' nicht möglich: Datei oder Verzeichnis nicht gefunden
ls: Zugriff auf 'hostname' nicht möglich: Datei oder Verzeichnis nicht gefunden
"ls" unexpectedly returned exit value 2 at shell-injection.pl line 11.
user@host:-$
My Questions:我的问题:
What terminologies can be used to describe, how the code is executed with capturex
?可以使用哪些术语来描述,如何使用capturex
执行代码? What are examples / techniques / terms used in other languages or environments?其他语言或环境中使用的示例/技术/术语是什么? (eg system call
?) (例如system call
?)
Is it actually advisable to use this technique without input checking (I assume not) and if not, for what reason (attack vector)?实际上是否建议在没有输入检查的情况下使用这种技术(我假设不是),如果不是,出于什么原因(攻击向量)?
The best way to get informed about how capturex
operates is by looking at its source .了解capturex
如何运作的最佳方式是查看其来源。
The sub implements its own piped open in "list-form", to work around the (ancient.) v5.6.x limitations.该子以“列表形式”实现自己的管道打开,以解决(古老的)v5.6.x 限制。 It does so by fork
-ing a process using piped open and then "manually" exec
-ing the command in the child, where it can use the list-form.它是通过使用管道打开的fork
进程来实现的,然后在子进程中“手动” exec
命令,它可以在其中使用列表形式。 Then the output is read in the parent.然后在父级中读取 output。 Follow the word "pipe" in the open page, and then the link to perlipc .按照打开页面中的“管道”一词,然后是perlipc的链接。
So there can be no shell involved since exec in the LIST form uses execvp(3)
system call to directly run the command.所以不会有 shell 涉及,因为 LIST 形式的exec使用execvp(3)
系统调用直接运行命令。 (What may happen when it runs with a single argument as well, if it contains no shell meta-charactes.) Thus the characters that (would) have a special meaning in the shell may be used freely as literal characters in the command. (当它使用单个参数运行时,如果它不包含 shell 元字符,则可能会发生什么情况。)因此,在 shell 中(可能)具有特殊含义的字符可以在命令中作为文字字符自由使用。
As for the second question -- if a command is formed with user-input it must always be checked really carefully, Note that one shouldn't literally use input in a command.至于第二个问题——如果命令是由用户输入形成的,则必须始终非常仔细地检查它,请注意,不应在命令中逐字使用输入。 but rather support keywords and parameters based on which the program composes the command.而是支持程序构成命令的关键字和参数。 Avoiding the shell of course helps but any user input must be checked.避免 shell 当然有帮助,但必须检查任何用户输入。
The injection bug is more of a programming error, whereby variable interpolation isn't used right and results in an unintended command;注入错误更多的是编程错误,即变量插值没有正确使用并导致意外命令; there is no need for malicious acts there, just for the "right" input that exposes the bug.那里不需要恶意行为,只需要暴露错误的“正确”输入。
All capturex
does is save you from having to form a valid shell command. capturex
所做的只是让您不必形成有效的 shell 命令。 Some validation may still be needed.可能仍需要一些验证。
What terminologies can be used to describe, how the code is executed with
capturex
?可以使用哪些术语来描述,如何使用capturex
执行代码?
The source for the latest version of IPC::System::Simple is found here .最新版本 IPC::System::Simple 的源代码可在此处找到。
On non-Windows systems, capturex
uses the fork
and execve
system calls via the open(my $pipe, '-|')
and exec BLOCK LIST
Perl functions respectively.在非 Windows 系统上,capturex 分别通过open(my $pipe, '-|')
和exec BLOCK LIST
capturex
函数使用fork
和execve
系统调用。 This form of Perl's exec
function executes the program directly rather than invoking a shell.这种 Perl 的exec
function 形式直接执行程序,而不是调用 shell。
exec "ls foo"; # Executes /bin/sh
exec { "/bin/sh" } "/bin/sh", "-c", "ls foo"; # Equivalent to previous.
exec { "ls" } "ls", "foo"; # Executes ls
Is it actually advisable to use this technique without input checking (I assume not) and if not, for what reason (attack vector)?实际上是否建议在没有输入检查的情况下使用这种技术(我假设不是),如果不是,出于什么原因(攻击向量)?
What if you provide a relative path to the program to execute and the user set the PATH
env var being used?如果您提供要执行的程序的相对路径并且用户设置正在使用的PATH
环境变量怎么办?
What if you provide a relative path to a file as an argument and the user set the current work directory?如果您提供文件的相对路径作为参数并且用户设置当前工作目录会怎样?
What if you pass a string that starts with a -
?如果你传递一个以-
开头的字符串怎么办? That could be interpreted as an option rather than argument.这可以被解释为一种选择而不是论据。 (This is why you'd use 'ls', '--', $file
instead of 'ls', $file
.) (这就是为什么你会使用'ls', '--', $file
而不是'ls', $file
。)
What if you pass ../../../../../../etc/passwd
?如果你通过../../../../../../etc/passwd
怎么办? That could have undesired effect if the program uses the argument in a file path.如果程序在文件路径中使用参数,这可能会产生不良影响。
What if you pass a regex to a program, and the regular expression would take longer than the lifespan of the universe to fail to match?如果您将正则表达式传递给程序,并且正则表达式将花费比宇宙的生命周期更长的时间来匹配失败怎么办?
It's possible that some validation still needs to occur.可能仍需要进行一些验证。 All capturex
does is save you from having to form a valid shell command. capturex
所做的只是让您不必形成有效的 shell 命令。
It might be the receiving program's job to do the validation, it might be yours, or it might be a combination.进行验证可能是接收程序的工作,可能是您的工作,也可能是组合的工作。
Yes, check the values you send to external commands even if you don't think you are because you have some other security feature in place.是的,请检查您发送给外部命令的值,即使您认为自己不是,因为您有其他一些安全功能。
You have two different paths to executing external commands in your example:在您的示例中,您有两种不同的路径来执行外部命令:
*.tmp
is still a glob:所以, *.tmp
仍然是一个 glob:system $single_string;
exec $single_string;
capturex
is doing this for you. capturex
正在为您执行此操作。 There's no shell to interpret things such as *.tmp
, so the arguments are their literal values.没有 shell 来解释诸如*.tmp
之类的东西,所以 arguments 是它们的文字值。 You'd see the same behavior with the list forms of system
or exec
:您会看到与system
或exec
的列表 forms 相同的行为:system $program, @args;
exec $program, @args
You still have to be careful, because @args
might be empty, so that looks like the single argument form again.你还是要小心,因为@args
可能是空的,所以看起来又像单参数形式。 There's a special form that handles that for you.有一个特殊的表格可以为您处理。 It looks like you specify the program twice, but it all works out:看起来您指定了两次程序,但一切正常:
system { $program }, $program, @args;
exec { $program }, $program, @args
I discuss this in detail in Mastering Perl 's "Secure Programming Techniques" chapter, but you can read about some of it in perlsec too.我在Mastering Perl的“安全编程技术”一章中详细讨论了这一点,但您也可以在perlsec中阅读其中的一些内容。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.