题目
我们有一个简单的 PHP 脚本,负责处理用户输入,并通过回调函数对数组进行操作,然而,这个脚本并未对输入进行严格的过滤。你是否能发现某些细节并利用它来深入了解更多信息?
解题过程
1. 初始访问
- 请求网址:
http://challenge.qsnctf.com:34142/ - 目的:查看页面内容,了解靶场结构
- 结果:获取到页面展示的PHP代码
2. 代码分析
<?phpfunctionexecuteCallback($callback){$someArray=[0,1,2,3];returnarray_map($callback,$someArray);}if(isset($_GET['callback'])){$evilCallback=$_GET['callback'];$newArray=executeCallback($evilCallback);}?>executeCallback函数详细解释
函数定义:
functionexecuteCallback($callback)- 参数:
$callback- 接收一个回调函数(可以是函数名字符串、匿名函数或可调用对象) - 返回值:返回一个新数组,包含回调函数处理后的结果
执行流程:
- 数组初始化:
$someArray = [0, 1, 2, 3];- 创建包含4个整数的数组 - 回调执行:
return array_map($callback, $someArray);使用array_map函数将回调应用到数组每个元素
array_map函数作用:
array_map($callback, $array)是PHP内置函数,用于将回调函数应用到数组的每个元素- 它会遍历数组中的每个元素,将元素值作为参数传递给回调函数
- 返回一个新数组,包含回调函数处理每个元素后的结果
- 原数组保持不变
回调函数执行机制:
- 对于数组
[0, 1, 2, 3],回调函数会被执行4次 - 每次执行时,数组元素值会作为参数传入回调函数
- 执行过程:
$callback(0); $callback(1); $callback(2); $callback(3);
漏洞产生原因:
- 函数直接将外部传入的
$callback参数作为回调执行,没有任何验证 - PHP支持将内置函数名(如
phpinfo、system)作为字符串传递给回调函数 - 当
$callback是用户可控的GET参数时,攻击者可以注入恶意函数名
与漏洞利用的关联:
- 尽管函数返回结果被赋值给
$newArray,但对于有副作用的函数(如phpinfo()会直接输出内容,system()会执行系统命令),不需要获取返回值就能产生危害 - 数组
[0, 1, 2, 3]决定了回调函数的执行次数,但对于无参数函数(如phpinfo()),执行次数不影响最终结果 - 即使
$newArray没有被输出,phpinfo()等函数仍会直接向浏览器输出内容
关键漏洞点:
$newArray = executeCallback($evilCallback);- 将用户可控的$evilCallback传入函数return array_map($callback, $someArray);- 直接执行不可信的回调函数缺少对回调函数的白名单验证或类型检查
发现漏洞:
callbackGET参数直接作为回调函数传入executeCallback执行PHP回调函数支持内置函数名,可直接注入内置函数
3. 尝试系统命令
- 请求网址:
http://challenge.qsnctf.com:34142/?callback=system('ls') - 目的:尝试执行系统命令查看目录文件
- 结果:连接被中止(服务器可能对系统命令做了防护)
4. 执行phpinfo函数
- 请求网址:
http://challenge.qsnctf.com:34142/?callback=phpinfo - 目的:获取服务器环境变量和配置信息
- 结果:成功执行,返回phpinfo()输出
5. 查找flag
- 在phpinfo输出的
Environment部分找到FLAG变量 - flag值:
qsnctf{e386fff2cee0455bb7f0a2027712f47d}
漏洞原理
PHP回调函数漏洞:当用户可控参数直接作为回调函数执行时,可注入内置函数(如phpinfo、system等),从而获取服务器敏感信息或执行系统命令。