Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/security/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/selenium/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
我们可以强制perl在从命令行运行时始终使用三参数形式的open吗?_Perl_Security - Fatal编程技术网

我们可以强制perl在从命令行运行时始终使用三参数形式的open吗?

我们可以强制perl在从命令行运行时始终使用三参数形式的open吗?,perl,security,Perl,Security,从命令行运行perl一行程序已经失败 问题是选项-n/-p触发菱形运算符,该运算符使用两个参数形式的open,因此当文件名包含特殊字符时,perl无法按预期工作: $ perl -pe '' 'uname|' Linux 如果文件名以开头,例如>文件,则更危险。在这种情况下,文件将被截断 要解决此问题,我们可以: 使用CPAN中的模块 自行实现类似于ARGV::readonly模块的功能: 使用-i选项,因为perl将在处理文件之前检查文件是否存在 使用-T选项启用污染模式 我认为

从命令行运行
perl
一行程序已经失败

问题是选项
-n/-p
触发菱形运算符
,该运算符使用两个参数形式的
open
,因此当文件名包含特殊字符时,
perl
无法按预期工作:

$ perl -pe '' 'uname|'
Linux
如果文件名以
开头,例如
>文件
,则更危险。在这种情况下,文件将被截断

要解决此问题,我们可以:

  • 使用CPAN中的模块
  • 自行实现类似于
    ARGV::readonly
    模块的功能:


  • 使用
    -i
    选项,因为
    perl
    将在处理文件之前检查文件是否存在
  • 使用
    -T
    选项启用污染模式
我认为所有的解决方案都可以解决这个问题,但也有其副作用。如果我们可以强制
perl
始终使用
open
的参数形式,这将是一个更好的解决方案

我想知道我们能不能做到,force
perl
总是使用
open
的参数形式

注意


这个问题只适用于从命令行运行
perl
一行程序时的情况,因为(当然)我们在perl脚本中总是可以使用
open
的三参数形式

您可以将
ARGV::readonly
alias
结合使用:

alias perl='perl -MARGV::readonly'

或者只是教育那些正在输入“坏的”一行程序的人。

您可能只想对一行程序执行此操作(使用
-e
开关),因此您需要为此定制
ARGV::readonly

package Sanitize::ARGV;
if ($0 eq '-e') {
    @ARGV = map {  # from ARGV::readonly
        s/^(\s+)/.\/$1/;
        s/^/< /;
        $_.qq/\0/;
    } @ARGV;
}
1;
或者设置一个系统范围的
PERL5OPT
变量

PERL5OPT="-MSanitize::ARGV"
如果您想变得更加偏执,可以隐藏您的系统perl(将其重命名为不可理解的名称),并用包装器替换它

#!/bin/bash
THE_REAL_PERL=/usr/bin/glorbqweroinuerqwer
$THE_REAL_PERL -MSanitize::ARGV "$@"
shell包装器仍将尊重用户对
PERL5OPT


在一般情况下,您可以使用
CORE::GLOBAL
机制覆盖内置的
open
功能,例如

package SafeOpen;
use Carp;
BEGIN {
    *CORE::GLOBAL::open = sub (*;$@) {
        goto &CORE::open if @_ > 2;
        Carp::cluck("OH MY GOD USING THE TWO-ARG open ARE YOU LIKE INSANE?");
        return CORE::open($_[0], '<', $_[1] // $_[0]);
    };
}
1;
packagesafeopen;
使用鲤鱼;
开始{
*核心::全局::开放=子(*;$@){
转到和核心::如果@2以上,则打开;
卡普:咯咯(“哦,我的天啊,用两个ARG打开你疯了吗?”);

return CORE::open($u0]),“在我之前的回答中,我假设
ARGV
filehandle magic模拟了2参数open,但实际上没有使用Perl的内置
open
函数。因此,我对它进行了更多的研究,我认为我找到了这个问题的实际解决方案

中的函数是perl围绕
ARGV
文件句柄执行I/O的地方

在该函数的
while
循环中,有两种打开文件句柄的调用。当
可能(PL\u inplace)
为true(即,当perl使用
-i
开关运行时),调用为
do\u open\u raw
。当
可能(PL\u inplace)
为false,调用的是
do\u open6
。后一个调用能够打开到外部命令的管道,这通常是OP不想要的

解决方案如下:在源文件
doio.c
中,将
Perl\u nextargv
中的
do\u open6
调用替换为
do\u open\u raw
并从源代码中重建
Perl

    if (LIKELY(!PL_inplace)) {
        if (nomagicopen
                ? do_open6(gv, "<", 1, NULL, &GvSV(gv), 1)
                : do_open6(gv, PL_oldname, oldlen, NULL, NULL, 0)
           ) {
            return IoIFP(GvIOp(gv));
        }
    }
    if (LIKELY(!PL_inplace)) {
        if (do_open_raw(gv, PL_oldname, oldlen, O_RDONLY, 0)) {
            return IoIFP(GvIOp(gv));
        }
    }
(使用时,
nomagicopen
参数为true。我想我们可以在函数顶部将其设置为
true
,而不必更改任何其他内容,但上面的更改是旧perl的通用解决方案)

样本输出:

$ original-perl -pe '' a b c 'date|'
Can't open a: No such file or directory
Can't open b: No such file or directory.
Can't open c: No such file or directory.
Mon Sep 21 18:41:37 PDT 2015

$ modified-perl -pe '' a b c 'date|'
Can't open a: No such file or directory.
Can't open b: No such file or directory.
Can't open c: No such file or directory.
Can't open date|: No such file or directory.

我理解你的观点,但我不明白
perl-pe''uname |'
的输出怎么会不是人们所期望的,并且会认为更大的危险是
perl-pe“1”“>myfile”
。我认为所有命令行输入文件都应该使用三参数表单打开,第二个参数始终设置为
@Borodin:
'uname |'
是一个有效的文件名,而不是打开它,命令
uname
被执行并通过管道传输到
perl
。并且想象该命令可以是
rm-rf$HOME
。是的,e除了
-i
选项之外,当您想就地编辑文件时。您可以阅读我在问题中提供的链接以了解更多详细信息。或者您可以将
-MARGV::readonly
添加到
PERL5OPT
环境变量是的,我知道检查
@ARGV
是否正常的方法。我的问题是关于强制
perl
要使用三参数open?您可以设置一个
CORE::GLOBAL::open
sub(我尝试了一下,看看它是否能解决您的问题),但我认为
ARGV
机制魔法绕过了它。好吧,这就是我在问题中提到的。我猜设置
CORE::GLOBAL::open
没有效果。因为当
-n
-p
开关触发菱形操作符
,它使用
open
+1的两个参数形式进行黑客攻击
perl
源代码。我想知道为什么
perl
仍然使用两个参数形式?更改
是否会像
那样破坏向后兼容?是perl,所以是的,可能有脚本依赖于这种行为。也许有一天我们会有
-N
-P
开关,比如
-N
and
-p
将脚本包装在
while(){…}
中。
    if (LIKELY(!PL_inplace)) {
        if (do_open_raw(gv, PL_oldname, oldlen, O_RDONLY, 0)) {
            return IoIFP(GvIOp(gv));
        }
    }
$ original-perl -pe '' a b c 'date|'
Can't open a: No such file or directory
Can't open b: No such file or directory.
Can't open c: No such file or directory.
Mon Sep 21 18:41:37 PDT 2015

$ modified-perl -pe '' a b c 'date|'
Can't open a: No such file or directory.
Can't open b: No such file or directory.
Can't open c: No such file or directory.
Can't open date|: No such file or directory.