0

0

php反序列unserialize的一个小特点

php中文网

php中文网

发布时间:2016-06-13 12:30:39

|

946人浏览过

|

来源于php中文网

原创

php反序列unserialize的一个小特性

这几天wordpress的那个反序列漏洞比较火,具体漏洞我就不做分析了,看这篇:http://drops.wooyun.org/papers/596,?
你也可以去看英文的原文:http://vagosec.org/2013/09/wordpress-php-object-injection/。?

wp官网打了补丁,我试图去bypass补丁,但让我自以为成功的时候,发现我天真了,并没有成功绕过wp的补丁,但却发现了unserialize的一个小特性,在此和大家分享一下。?

1.unserialize()函数相关源码:?

if ((yylimit - yycursor) ????????yych = *yycursor;?<br style="margin: 0px; padding: 0px;">????????switch (yych) {?<br style="margin: 0px; padding: 0px;">????????case 'c':?<br style="margin: 0px; padding: 0px;">????????case 'o':????????goto yy13;?<br style="margin: 0px; padding: 0px;">????????case 'n':????????goto yy5;?<br style="margin: 0px; padding: 0px;">????????case 'r':????????goto yy2;?<br style="margin: 0px; padding: 0px;">????????case 's':????????goto yy10;?<br style="margin: 0px; padding: 0px;">????????case 'a':????????goto yy11;?<br style="margin: 0px; padding: 0px;">????????case 'b':????????goto yy6;?<br style="margin: 0px; padding: 0px;">????????case 'd':????????goto yy8;?<br style="margin: 0px; padding: 0px;">????????case 'i':????????goto yy7;?<br style="margin: 0px; padding: 0px;">????????case 'o':????????goto yy12;?<br style="margin: 0px; padding: 0px;">????????case 'r':????????goto yy4;?<br style="margin: 0px; padding: 0px;">????????case 's':????????goto yy9;?<br style="margin: 0px; padding: 0px;">????????case '}':????????goto yy14;?<br style="margin: 0px; padding: 0px;">????????default:????????goto yy16;?<br style="margin: 0px; padding: 0px;">????????}

上边这段代码是判断序列串的处理方式,如序列串o:4:"test":1:{s:1:"a";s:3:"aaa";},处理这个序列串,先获取字符串第一个字符为o,然后case 'o':??goto yy13?

yy13:?<br style="margin: 0px; padding: 0px;">????????yych = *(yymarker = ++yycursor);?<br style="margin: 0px; padding: 0px;">????????if (yych == ':') goto yy17;?<br style="margin: 0px; padding: 0px;">????????goto yy3;

从上边代码看出,指针移动一位指向第二个字符,判断字符是否为:,然后 goto yy17?

yy17:?<br style="margin: 0px; padding: 0px;">????????yych = *++yycursor;?<br style="margin: 0px; padding: 0px;">????????if (yybm[0+yych] & 128) {?<br style="margin: 0px; padding: 0px;">????????????????goto yy20;?<br style="margin: 0px; padding: 0px;">????????}?<br style="margin: 0px; padding: 0px;">????????if (yych == '+') goto yy19;?<br style="margin: 0px; padding: 0px;"><br style="margin: 0px; padding: 0px;">.......?<br style="margin: 0px; padding: 0px;"><br style="margin: 0px; padding: 0px;">yy19:?<br style="margin: 0px; padding: 0px;">????????yych = *++yycursor;?<br style="margin: 0px; padding: 0px;">????????if (yybm[0+yych] & 128) {?<br style="margin: 0px; padding: 0px;">????????????????goto yy20;?<br style="margin: 0px; padding: 0px;">????????}?<br style="margin: 0px; padding: 0px;">????????goto yy18;

从上边代码看出,指针移动,判断下一位字符,如果字符是数字直接goto yy20,如果是'+'就goto yy19,而yy19中是对下一位字符判断,如果下一位字符是数字goto yy20,不是就goto yy18,yy18是直接退出序列处理,yy20是对object性的序列的处理,所以从上边可以看出:?

o:+4:"test":1:{s:1:"a";s:3:"aaa";}?<br style="margin: 0px; padding: 0px;">o:4:"test":1:{s:1:"a";s:3:"aaa";}

都能够被unserialize反序列化,且结果相同。?

2.实际测试:?

<?php ?<br style="margin: 0px; padding: 0px;">var_dump(unserialize('o:+4:"test":1:{s:1:"a";s:3:"aaa";}'));?<br style="margin: 0px; padding: 0px;">var_dump(unserialize('o:4:"test":1:{s:1:"a";s:3:"aaa";}'));?<br style="margin: 0px; padding: 0px;">?>

输出:?

object(__php_incomplete_class)#1 (2) { ["__php_incomplete_class_name"]=> string(4) "test" ["a"]=> string(3) "aaa" }?<br style="margin: 0px; padding: 0px;">object(__php_incomplete_class)#1 (2) { ["__php_incomplete_class_name"]=> string(4) "test" ["a"]=> string(3) "aaa" }

其实,不光object类型处理可以多一个'+',其他类型也可以,具体测试不做过多描述。?

3.我们看下wp的补丁:?

function is_serialized( $data, $strict = true ) {?<br style="margin: 0px; padding: 0px;">????????// if it isn't a string, it isn't serialized?<br style="margin: 0px; padding: 0px;">????????if ( ! is_string( $data ) )?<br style="margin: 0px; padding: 0px;">????????????????return false;?<br style="margin: 0px; padding: 0px;">????????$data = trim( $data );?<br style="margin: 0px; padding: 0px;">???????? if ( 'n;' == $data )?<br style="margin: 0px; padding: 0px;">????????????????return true;?<br style="margin: 0px; padding: 0px;">????????$length = strlen( $data );?<br style="margin: 0px; padding: 0px;">????????if ( $length ????????????????return false;?<br style="margin: 0px; padding: 0px;">????????if ( ':' !== $data[1] )?<br style="margin: 0px; padding: 0px;">????????????????return false;?<br style="margin: 0px; padding: 0px;">????????if ( $strict ) {//output?<br style="margin: 0px; padding: 0px;">????????????????$lastc = $data[ $length - 1 ];?<br style="margin: 0px; padding: 0px;">????????????????if ( ';' !== $lastc && '}' !== $lastc )?<br style="margin: 0px; padding: 0px;">????????????????????????return false;?<br style="margin: 0px; padding: 0px;">????????} else {//input?<br style="margin: 0px; padding: 0px;">????????????????$semicolon = strpos( $data, ';' );?<br style="margin: 0px; padding: 0px;">????????????????$brace???? = strpos( $data, '}' );?<br style="margin: 0px; padding: 0px;">????????????????// either ; or } must exist.?<br style="margin: 0px; padding: 0px;">????????????????if ( false === $semicolon && false === $brace )?<br style="margin: 0px; padding: 0px;">????????????????????????return false;?<br style="margin: 0px; padding: 0px;">????????????????// but neither must be in the first x characters.?<br style="margin: 0px; padding: 0px;">????????????????if ( false !== $semicolon && $semicolon ????????????????????????return false;?<br style="margin: 0px; padding: 0px;">????????????????if ( false !== $brace && $brace ????????????????????????return false;?<br style="margin: 0px; padding: 0px;">????????}?<br style="margin: 0px; padding: 0px;">????????$token = $data[0];?<br style="margin: 0px; padding: 0px;">????????switch ( $token ) {?<br style="margin: 0px; padding: 0px;">????????????????case 's' :?<br style="margin: 0px; padding: 0px;">????????????????????????if ( $strict ) {?<br style="margin: 0px; padding: 0px;">????????????????????????????????if ( '"' !== $data[ $length - 2 ] )?<br style="margin: 0px; padding: 0px;">????????????????????????????????????????return false;?<br style="margin: 0px; padding: 0px;">????????????????????????} elseif ( false === strpos( $data, '"' ) ) {?<br style="margin: 0px; padding: 0px;">????????????????????????????????return false;?<br style="margin: 0px; padding: 0px;">????????????????????????}?<br style="margin: 0px; padding: 0px;">????????????????case 'a' :?<br style="margin: 0px; padding: 0px;">????????????????case 'o' :?<br style="margin: 0px; padding: 0px;">????????????????????????echo "a";?<br style="margin: 0px; padding: 0px;">????????????????????????return (bool) preg_match( "/^{$token}:[0-9]+:/s", $data );?<br style="margin: 0px; padding: 0px;">????????????????case 'b' :?<br style="margin: 0px; padding: 0px;">????????????????case 'i' :?<br style="margin: 0px; padding: 0px;">????????????????case 'd' :?<br style="margin: 0px; padding: 0px;">????????????????????????$end = $strict ? '$' : '';?<br style="margin: 0px; padding: 0px;">????????????????????????return (bool) preg_match( "/^{$token}:[0-9.e-]+;$end/", $data );?<br style="margin: 0px; padding: 0px;">????????}?<br style="margin: 0px; padding: 0px;">????????return false;?<br style="margin: 0px; padding: 0px;">}
补丁中的?

return (bool) preg_match( "/^{$token}:[0-9]+:/s", $data );

可以多一个'+'来绕过,虽然我们通过这个方法把序列值写入了数据库,但从数据库中提取数据,再次验证的时候却没法绕过了,我这个加号没能使数据进出数据库发生任何变化,我个人认为这个补丁绕过重点在于数据进出数据的前后变化。?

4.总结?
虽然没有绕过wp补丁,但这个unserialize()的小特性可能会被很多开发人员忽略,导致程序出现安全缺陷。?
以上的分析有什么错误请留言指出。?

5.参考?
《wordpress
http://vagosec.org/2013/09/wordpress-php-object-injection/?
《var_unserializer.c源码》?
https://github.com/php/php-src/blob/73cd2e0ab14d804c6bf0b689490bdd4fd6e969b1/ext/standard/var_unserializer.c?
《php string序列化与反序列化语法解析不一致带来的安全隐患》?
http://zone.wooyun.org/content/1664

相关文章

PHP速学教程(入门到精通)
PHP速学教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法

本专题系统整理pixiv网页版官网入口及登录访问方式,涵盖官网登录页面直达路径、在线阅读入口及快速进入方法说明,帮助用户高效找到pixiv官方网站,实现便捷、安全的网页端浏览与账号登录体验。

463

2026.02.13

微博网页版主页入口与登录指南_官方网页端快速访问方法
微博网页版主页入口与登录指南_官方网页端快速访问方法

本专题系统整理微博网页版官方入口及网页端登录方式,涵盖首页直达地址、账号登录流程与常见访问问题说明,帮助用户快速找到微博官网主页,实现便捷、安全的网页端登录与内容浏览体验。

135

2026.02.13

Flutter跨平台开发与状态管理实战
Flutter跨平台开发与状态管理实战

本专题围绕Flutter框架展开,系统讲解跨平台UI构建原理与状态管理方案。内容涵盖Widget生命周期、路由管理、Provider与Bloc状态管理模式、网络请求封装及性能优化技巧。通过实战项目演示,帮助开发者构建流畅、可维护的跨平台移动应用。

64

2026.02.13

TypeScript工程化开发与Vite构建优化实践
TypeScript工程化开发与Vite构建优化实践

本专题面向前端开发者,深入讲解 TypeScript 类型系统与大型项目结构设计方法,并结合 Vite 构建工具优化前端工程化流程。内容包括模块化设计、类型声明管理、代码分割、热更新原理以及构建性能调优。通过完整项目示例,帮助开发者提升代码可维护性与开发效率。

20

2026.02.13

Redis高可用架构与分布式缓存实战
Redis高可用架构与分布式缓存实战

本专题围绕 Redis 在高并发系统中的应用展开,系统讲解主从复制、哨兵机制、Cluster 集群模式及数据分片原理。内容涵盖缓存穿透与雪崩解决方案、分布式锁实现、热点数据优化及持久化策略。通过真实业务场景演示,帮助开发者构建高可用、可扩展的分布式缓存系统。

26

2026.02.13

c语言 数据类型
c语言 数据类型

本专题整合了c语言数据类型相关内容,阅读专题下面的文章了解更多详细内容。

29

2026.02.12

雨课堂网页版登录入口与使用指南_官方在线教学平台访问方法
雨课堂网页版登录入口与使用指南_官方在线教学平台访问方法

本专题系统整理雨课堂网页版官方入口及在线登录方式,涵盖账号登录流程、官方直连入口及平台访问方法说明,帮助师生用户快速进入雨课堂在线教学平台,实现便捷、高效的课程学习与教学管理体验。

14

2026.02.12

豆包AI网页版入口与智能创作指南_官方在线写作与图片生成使用方法
豆包AI网页版入口与智能创作指南_官方在线写作与图片生成使用方法

本专题汇总豆包AI官方网页版入口及在线使用方式,涵盖智能写作工具、图片生成体验入口和官网登录方法,帮助用户快速直达豆包AI平台,高效完成文本创作与AI生图任务,实现便捷智能创作体验。

524

2026.02.12

PostgreSQL性能优化与索引调优实战
PostgreSQL性能优化与索引调优实战

本专题面向后端开发与数据库工程师,深入讲解 PostgreSQL 查询优化原理与索引机制。内容包括执行计划分析、常见索引类型对比、慢查询优化策略、事务隔离级别以及高并发场景下的性能调优技巧。通过实战案例解析,帮助开发者提升数据库响应速度与系统稳定性。

53

2026.02.12

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
前端系列快速入门课程
前端系列快速入门课程

共4课时 | 0.4万人学习

Pandas 教程
Pandas 教程

共15课时 | 1.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号