简体   繁体   English

IPC::System::Simple capturex 是如何工作的?

[英]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:我的问题:

  1. 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 ?)

  2. 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函数使用forkexecve系统调用。 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:在您的示例中,您有两种不同的路径来执行外部命令:

  1. Pass the shell a single string.将 shell 传递给单个字符串。 In backticks, Perl constructs the entire command, and if it looks like the shell needs to handle it (globs, etc), the shell gets a chance to stick its fingers in. The shell then figures out what the command means, interprets its arguments, and does the work. In backticks, Perl constructs the entire command, and if it looks like the shell needs to handle it (globs, etc), the shell gets a chance to stick its fingers in. The shell then figures out what the command means, interprets its arguments , 并完成工作。 So, the *.tmp is still a glob:所以, *.tmp仍然是一个 glob:
system $single_string;
exec $single_string;
  1. Pass a list to the system and execute the command directly, with no shell in the way.向系统传递一个列表,直接执行命令,没有 shell 碍事。 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 :您会看到与systemexec的列表 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM