拓冰建站拓冰建站
首页 / 资讯中心 / 正文

命令执行漏洞入门:ACTF2020新生赛Exec1解题全记录

BUUCTF 上这套 ACTF2020 新生赛一直被很多 Web 入门玩家当成练手宝库。题目难度曲线合理能让你在“看懂题解但自己就是打不出来”的挫败感中一点点把漏洞利用的基础功磨扎实。其中 Exec1 这道题应该算是我个人认为最适合用来理解“命令执行漏洞”原理的一道入门题没有复杂的绕过没有花哨的 tricks就是干干净净让你亲手打通一次 RCE。这篇文章我就完整写一下我的解题过程从环境准备、漏洞原理、实操步骤到踩坑记录按一篇能给新手直接抄作业的方式整理出来。这道题的核心考点非常明确Web 命令执行Command Execution漏洞。所谓命令执行就是 Web 应用在调用系统命令时没有对用户输入做严格过滤导致攻击者可以通过拼接符号在目标服务器上执行任意系统命令。Exec1 恰好给了我们一个最典型的 Ping 测试功能入口你输入一个 IP 地址后端拿去执行ping结果直接回显到页面上。听起来是不是很“朴实无华”但就是这样的功能点在真实业务中依然大量存在。这篇文章适合完全零基础但想入门 CTF Web 方向的新手也适合已经刷过一些题但始终搞不清楚“为什么分号能注入、为什么管道符也能注入”的同学。我会把这道题从原理到实操完整拆开讲并且把我在做题过程中遇到的各种小坑同步列出来保证你跟着做一遍之后再遇到同类型题目能自己独立做出来。1. 题目信息与做题准备1.1 这道题究竟在考什么先看题目本身。BUUCTF 上这道题的标签很简单就一个Exec所属比赛是 ACTF2020 新生赛。Exec 是 Execute 的缩写明摆着告诉你考点就是命令执行漏洞而这类漏洞对应的攻击手法在真实安全测试中通常叫RCERemote Command/Code Execute远程命令执行。拿道题之后第一件事点开题目环境页面上会有一个输入框提示你输入 IP 地址。输入127.0.0.1点提交如果环境正常你会看到一段ping 127.0.0.1的输出结果包括PING (icmp) 56(84) bytes of data之类的内容。到这里题目意图基本就摊开了目标机器调用了系统自带的 ping 命令来探测这个 IP而你的输入被直接拼进了命令行里。为什么这是一个漏洞因为如果后端代码写成这样$ip $_POST[ip]; system(ping -c 4 . $ip);那你的输入就不是一个单纯的 IP而是一段会被 shell 解释执行的字符串。只要在输入里加上命令连接符就能让系统执行完 ping 之后继续执行你注入的命令。这就是整道题的核心逻辑。1.2 做题前需要准备的工具我建议新手有条件的话尽量别只依赖浏览器自带的页面表单养成用 Burp Suite 的习惯后面遇到有过滤、有 WAF 的题目你就知道提前熟悉工具有多重要了。我这次实际用的工具清单浏览器火狐或者 Chrome 都行主要用来打开题目页面和确认正常 ping 返回结果。Burp Suite Community用来抓包、改包、重放请求。这道题其实不太需要重放但养成抓包习惯能帮你看到前后端交互的完整细节。Hackbar 或者任意能改请求的插件方便直接在浏览器里操作 GET/POST 参数。curl如果你喜欢命令行操作curl完全够用我后面给的很多 payload 会在命令行里直接验证。这些工具里最核心的其实是 curl。因为它能让你把请求参数看得清清楚楚也方便快速测试各种 payload不涉及图形界面反而效率更高。比如典型的探测命令curl -d ip127.0.0.1;ls http://target/一眼就能判断注入是否成功。1.3 为什么这道题适合当命令执行入门题我刷过不少所谓“入门级”命令执行题很多题目要么过滤了空格要么过滤了关键字新手一上来就在绕过滤上卡半天连漏洞本身都没摸清楚。Exec1 不一样它几乎没有任何过滤你注入什么命令shell 就执行什么命令完完全全暴露命令执行漏洞最原始的样子。这意味着你只需要专注于理解两件事第一输入是怎么拼到命令里的第二哪些特殊符号能帮你注入第二条命令。理解了这两点之后再遇到过滤绕过的变种题你才会有足够的底层认知去推导 payload而不是背题解。所以我一直建议新手在打 Exec1 之前先老老实实把 Linux 基础命令、管道符、重定向这些知识过一遍做题会轻松很多。2. 命令执行漏洞原理拆解2.1 漏洞产生的根本原因命令执行漏洞产生的根本原因是不可信数据流入了系统命令的拼接过程。用人话说就是用户输入的内容被当成命令本身的一部分交给了 shell 去执行。我们拿最典型的 PHP 代码举例?php $ip $_POST[ip]; system(ping -c 4 {$ip}); ?这段代码想做的事情很简单接收用户传入的 IP 地址然后去 ping 这个地址。但问题在于$ip被直接拼接到了双引号字符串里然后交给了system函数执行。如果用户老老实实输入127.0.0.1那命令就是ping -c 4 127.0.0.1一切正常。但如果用户输入的是127.0.0.1; ls整条命令就变成了ping -c 4 127.0.0.1; lsshell 在执行时先 ping跑完之后遇到;知道这是一条命令的结束接着执行ls。于是当前目录下的文件列表就出现在了你眼前。如果不做任何过滤;、|、、||、、换行符都能达到类似效果。这段逻辑听起来特别简单但真实环境里就是有大量开发者在拼接命令时忘了过滤或者只做了简单过滤但没过滤全。尤其是运维脚本、自动部署工具、网络探测功能里这类问题非常常见。2.2 各种命令连接符的区别与用法新手最容易混淆的就是;、|、||、、这些符号。我直接给你一个对照表看完就懂。符号作用示例执行逻辑;无脑顺序执行多条命令id; whoami不管前一条成功失败都执行后一条|管道符把前一条命令的输出作为后一条的输入ls | grep flag左边命令的输出传给右边命令处理||当前一条命令失败时才执行后一条cat /nonexist || id如果左侧命令退出码非 0执行右侧后台执行前一条接着执行后一条sleep 5 id左侧命令放后台立刻执行右侧当前一条成功时才执行后一条id whoami左侧退出码为 0 才执行右侧换行符URL 编码%0a相当于回车分隔多条命令id%0awhoami同分号常用于绕过正则匹配在实际攻击中最常用的是;、|、这三种。;最无脑因为不管 ping 的结果如何它都会继续执行后面的命令|在输出内容很多时很好用你可以直接把输出喂给grep过滤则要小心一点如果前一条命令执行失败后一条就不会执行所以有时反而会让你的注入命令静默失败。Exec1 这道题我用的是;因为 ping 基本上不会失败而;的语义又最简单适合新手理解。2.3 系统命令的替代品思维还有一点特别重要搞懂命令执行之后你要形成一种直觉拿到 shell 权限之后第一件事永远是看目标机器上有什么。有了这个直觉你自然会主动去记 Linux 下那些命令的“变体用法”。比如查目录可以用ls但如果ls被过滤了就得想到dir、find . -maxdepth 1、sort *这些替代方法比如看文件内容可以用cat被过滤了就用tac、more、less、head、tail比如找 flag 文件最笨的方法是一个个目录翻高效的方法是用find / -name flag*直接定位。这些都不是什么高深技巧只是建立“命令执行之后路要怎么走”的思维模型。3. 完整解题实操过程3.1 第一步用正常输入确认功能打开题目环境之后我先往输入框提交了一个127.0.0.1。页面上很快返回了一屏类似的输出PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data. 64 bytes from 127.0.0.1: icmp_seq1 ttl64 time0.039 ms ... --- 127.0.0.1 ping statistics --- 4 packets transmitted, 4 received, 0% packet loss, time 3050ms这段返回里有几个重要信息。第一目标机器是 Linux64 bytes from、icmp_seq这些字段是 Linux ping 的输出格式第二后端确实执行了系统命令并把结果直接回显到了页面上第三输入内容没有被做任何转义或过滤。这时候我心里已经有底了这道题就是典型的命令执行。接着我抓包确认了一下请求格式发现提交方式是 POST参数名是ip提交地址就是当前页面。3.2 第二步注入 ls 查看当前目录确认功能正常之后就用;拼接一条简单的lsip127.0.0.1;ls页面返回在 ping 输出后面紧跟了一串文件名我当时看到的是index.php之类的文件。这一步的意义非常关键你已经证明了自己可以在目标机器上执行任意命令。不过要注意ls默认只显示当前目录而很多题目为了方便会把 flag 直接放在根目录/flag或者放在某个子目录里所以单纯ls往往不够。我习惯的做法是连续探测几个目录ip127.0.0.1;ls / ip127.0.0.1;ls /home ip127.0.0.1;ls /var/www/html分别在 URL 里提交这几个 payload看输出。Exec1 这道题里我第一次执行ls /的时候就直接看到了根目录下有一个名字非常显眼的文件通常是flag或者flag.txt。文件路径清晰了下一步就是把它读出来。3.3 第三步读取 flag 拿到最终答案定位到文件之后直接cat读取命令ip127.0.0.1;cat /flag或者ip127.0.0.1;cat /flag.txt如果路径没错页面上会直接回显出 flag 内容格式一般是flag{...}或者 ACTF 官方常用的actf{...}。到这里题目就已经解决了。整个流程走下来你可能觉得过于简单但请相信我Exec1 的意义就在于让你明白命令执行漏洞一旦存在且输出回显那你和拿下服务器只隔了一条命令的距离。后续你在做其他题目时会遇到输出不回显的情况那时才需要 DNSLog、sleep 时间盲注之类的手段。3.4 解题过程完整 payload 速查表为了让你方便对照我把这次解题用到的核心 payload 整理成一张表请求参数内容作用预期结果127.0.0.1正常测试返回 ping 结果127.0.0.1;ls查看当前目录显示 index.php 等文件127.0.0.1;ls /查看根目录发现 /flag127.0.0.1;cat /flag读取 flag返回 flag{}这里再补充一个细节如果你提交参数时浏览器自动做了 URL 编码;可能会变成%3B比如127.0.0.1%3Bcat%20/flag服务端解码后依然会变成分号所以不用担心。用 curl 时要注意符号因为它会让命令在后台运行导致请求发送不完整建议像上面那样给参数加上单引号或者双引号。4. 常见问题与排查技巧实录4.1 页面没有回显注入命令看不到结果这种情况最常见的两个原因第一输入点不在 IP 参数而在别的参数第二输出被丢掉了或者只有根目录下某个文件才有回显。Exec1 比较简单一般不会出现这种问题但我刷别的题目时踩过很多次。排查思路很简单先用最简单的id或者whoami试一下确认命令有没有执行。命令执行了但没回显的情况可以考虑时间盲注比如ip127.0.0.1;sleep 5如果页面等待了 5 秒才返回就说明命令确实被执行了只是输出不可见这时候可以用重定向到可访问目录或者使用外带数据的方式。4.2 flag 格式不对或者明明看到文件但读不出来如果你ls /已经看到了flag但cat /flag就是空白的先别急着怀疑命令被过滤。有可能文件内容不是普通文本也可能文件权限不给你读或者编码格式有问题。Exec1 里不会出现这么复杂的情况但养成良好习惯是必要的先file /flag看文件类型再用xxd /flag看十六进制内容确认是不是隐藏了不可见字符。另一个常见问题是ls /看到了flag但它是目录不是文件此时要ls /flag进目录再找或者直接cat /flag/flag。4.3 输入过滤了空格、分号、cat 关键字怎么办Exec1 本身没有过滤但很多同类题目会做基础防护。这里先教你几个通用的绕过思路后面刷题一定用得上。空格被过滤时别在输入里使用空格改用${IFS}代替127.0.0.1;cat${IFS}/flag或者用 tab 键的 URL 编码%09127.0.0.1;cat%09/flagcat关键字被过滤时换成tac、more、less、head、tail、od、xxd等替代命令。flag关键字被过滤时用通配符*、?或反斜杠拆分127.0.0.1;cat /fl?g 127.0.0.1;cat /f*lag 127.0.0.1;ca\t /fl\ag分号和管道符都被过滤时看一下$()和反引号有没有被过滤127.0.0.1$(cat${IFS}/flag)这个 payload 的原理是利用命令替换把cat /flag的结果作为参数传给 ping虽然输出不一定直接可见但如果页面把 ping 的完整命令行打印出来依然能拿到 flag。这一个绕过思路在无回显场景下也经常能救命。4.4 题目环境连不上报错或超时BUUCTF 的靶机有时候会因访问人数过多而启动失败或者临时挂掉这种情况跟你的解题能力无关换个时间段再试就好。不过要注意每道题的环境启动后通常都有一个有效期过了时间环境会被释放重新点击开启按钮会分配一个新的靶机地址。写题解或者复现截图时一定记得用自己的靶机地址别直接抄别人的 URL。5. 从 Exec1 学到的利用思路与防御思路5.1 一条命令执行漏洞能走到多远这道题打完你可能会觉得“不就是多执行一条命令吗”但这背后的影响范围比想象中要大得多。命令执行漏洞如果出现在可公网访问的业务系统上攻击者可以做的事情包括但不限于读取服务器上的敏感文件配置、密钥、用户数据库、反弹 shell 获得交互式终端、内网横向渗透、植入后门、加密勒索。很多真实安全事件的最初入口就是业务系统某个小功能点存在命令执行。以 Exec1 为例假设目标服务器上的 Web 服务以www-data权限运行那命令执行的初始权限很可能就这么低但结合内核提权漏洞、错误配置的 sudo 权限或者高权限计划任务攻击者完全可以拿到 root。这也是为什么我一直跟学安全的朋友说小洞也是洞入门题的价值不在于它简单而是让你看到漏洞利用的完整链路可以延伸多远。5.2 作为防御方这种洞该怎么修做安全不能只站在攻击方视角顺手聊聊修复方案。针对这类命令执行漏洞最有效的办法是禁用系统命令调用能用 API 实现的功能就不要去调 shell。如果必须要调命令可以做以下几层防护参数白名单校验IP 地址就用正则严格限定为 IPv4/IPv6 格式而不是简单替换敏感字符使用escapeshellarg、escapeshellcmd做转义把用户输入当参数处理而非命令避免直接拼接命令改成exec函数加数组参数的形式避免经过 shell 解释运行 Web 服务时使用最小权限用户禁止 root 直接启动开启 WAF 或 RASP对命令注入流量做实时拦截这套组合下来大部分命令执行漏洞都能被拒之门外。不过要承认一点开发者永远无法只靠一个点就保证彻底安全纵深防御才是正路。5.3 刷完 Exec1 之后接下来该打什么打完了 Exec1说明你已经掌握了命令执行的基本姿势接下来可以按难度梯度去刷同类题巩固思路。BUUCTF 上比较推荐的几道[GXYCTF2019]Ping Ping Ping同样是 Ping 场景但加入了空格过滤和关键字过滤练习绕过很有价值[极客大挑战 2019]RCE ME代码执行和命令执行混合考察点更深[ACTF2020 新生赛]Exec系列后续题如有的话顺着比赛思路继续刷另外别急着只刷命令执行主题可以穿插着到 BUUCTF 的 Web 其他分类比如 SQL 注入、文件上传、反序列化让知识面铺开。等哪天你能做到看到功能点就自动联想到可能的漏洞类型那才算是入了 Web 安全这道门。我在实际操作中老老实实把这道题从页面提交到抓包重放从ls到cat /flag每一步都重复了好几遍甚至故意把参数改成各种会被过滤的写法去验证不同符号的作用差异。你会发现虽然题目已经打通了但你在这个过程中积累的“试探感觉”才是真正的收获。后面遇到 Ping Ping Ping 那种加了过滤的变种题你很快就能反应过来空格被过滤就换${IFS}cat被过滤就换tac这不就是从这道题延伸出去的自然思考吗。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门