首页 后端开发 php教程 php反序列unserialize的一个小特点

php反序列unserialize的一个小特点

Jun 13, 2016 pm 12:30 PM
case data false goto return

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

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

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解锁Myrise中的所有内容
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

C语言return的用法详解 C语言return的用法详解 Oct 07, 2023 am 10:58 AM

C语言return的用法有:1、对于返回值类型为void的函数,可以使用return语句来提前结束函数的执行;2、对于返回值类型不为void的函数,return语句的作用是将函数的执行结果返回给调用者;3、提前结束函数的执行,在函数内部,我们可以使用return语句来提前结束函数的执行,即使函数并没有返回值。

Java中return和finally语句的执行顺序是怎样的? Java中return和finally语句的执行顺序是怎样的? Apr 25, 2023 pm 07:55 PM

源码:publicclassReturnFinallyDemo{publicstaticvoidmain(String[]args){System.out.println(case1());}publicstaticintcase1(){intx;try{x=1;returnx;}finally{x=3;}}}#输出上述代码的输出可以简单地得出结论:return在finally之前执行,我们来看下字节码层面上发生了什么事情。下面截取case1方法的部分字节码,并且对照源码,将每个指令的含义注释在

c语言中goto语句的含义是什么 c语言中goto语句的含义是什么 Dec 22, 2022 pm 06:00 PM

在c语言中,goto语句被称为无条件转移语句,允许把控制无条件转移到同一函数内的被标记的语句;语法“goto label;...label: statement;”,其中label可以是任何除C关键字以外的纯文本,它可以设置在C程序中goto语句的前面或者后面。

HMD Skyline 获得新的颜色选项和官方磁性外壳 HMD Skyline 获得新的颜色选项和官方磁性外壳 Aug 23, 2024 am 07:04 AM

上个月推出 HMD Skyline(亚马逊售价 499 美元)时,它有两种颜色:霓虹粉和扭曲黑。现在,第三种颜色加入了蓝色托帕石的行列。 HMD Global 还宣布了 PH 的官方案例

go语言中goto怎么用 go语言中goto怎么用 Nov 23, 2022 pm 06:40 PM

在go语言中,goto语句用于无条件跳转,可以无条件地转移到程序中指定的行;它通过标签进行代码间的无条件跳转。goto后接一个标签,这个标签的意义是告诉Go程序下一步要执行哪行的代码,语法“goto 标签;... ...标签: 表达式;”。goto打破原有代码执行顺序,直接跳转到指定行执行代码;goto语句通常与条件语句配合使用,可用来实现条件转移、构成循环、跳出循环体等功能。

Vue3怎么使用setup语法糖拒绝写return Vue3怎么使用setup语法糖拒绝写return May 12, 2023 pm 06:34 PM

Vue3.2setup语法糖是在单文件组件(SFC)中使用组合式API的编译时语法糖解决Vue3.0中setup需要繁琐将声明的变量、函数以及import引入的内容通过return向外暴露,才能在使用的问题1.在使用中无需return声明的变量、函数以及import引入的内容,即可在使用语法糖//import引入的内容import{getToday}from'./utils'//变量constmsg='Hello!'//函数func

switch case判断变量 switch case判断变量 Feb 19, 2024 am 08:04 AM

switchcase判断变量,需要具体代码示例在编程中,我们经常需要根据不同的变量值来执行不同的操作。switchcase语句是一种方便的结构,可以根据变量的值来选择不同的代码块进行执行。下面是一个具体的代码示例,展示了如何使用switchcase语句判断变量的不同取值:#includeintmain(){

详解JavaScript函数返回值和return语句 详解JavaScript函数返回值和return语句 Aug 04, 2022 am 09:46 AM

JavaScript 函数提供两个接口实现与外界的交互,其中参数作为入口,接收外界信息;返回值作为出口,把运算结果反馈给外界。下面本篇文章带大家了解一下JavaScript函数返回值,浅析下return语句的用法,希望对大家有所帮助!

See all articles