php反序列化键值逃逸

又遇到键值逃逸了。

这里提前说一下我的理解吧,这次理解比上几次遇到字符串逃逸还要深刻一点。

譬如这次我是先写逃逸payload,然后使用 "}; 闭合第一个逃逸部分,然后在后续插入新的字符串,也就是更改可控值,再用一次 "}; 闭合后续字符串。

 

详细的看题目吧。来自:[0CTF 2016]piapiapia

打开是个login界面,很难不让人想到sql注入,但是注不出来。

这里没先用dirsearch,因为太慢,先用脚本扫看能不能扫出东西:

绷不住了,全都能访问。

那这里我就选择www.zip,这个集成了源码备份文件。

下载得到一堆源码,接下来就是源码审计。

一个个看,先看class文件:

 

没什么特别的,就是mysql数据库,下面有个filter过滤函数,会把关键字换成hacker,如果我还没看到后面,都真要以为是sql的黑名单注入了。

然后接着看config.php,出现关键信息:

flag就在config.php,所以我们的目标应该是对这个config.php有所操作,但是暂时还没有想法,接着看index.php:

这里出现了个profile.php,里面是个username和password的strlen检验,没什么特别的,再看到profile.php:

又套到了update.php,但是有个关键注入点出现了,也就是else后面的$photo用base64加密把photo读出来,这里就有个思路,把这个photo想办法换成前面的config.php,不就能读flag了吗?而且还有个unserialize的关键反序列化函数,这里思路就出来了,显然要用反序列化字符串逃逸把photo参数换成config.php,猜想update.php有文件上传和序列化函数:

猜对了。看看判断条件,username/email都被写死了,不可控了。但是nickname只有个简单的判断,只需要写数字和字母,那对我们要插入的字符串来说等于啥都没过滤,而且strlen函数有个经典的数组绕过,传nickname[],就能卡出NULL,绕过长度限制。

分析一下流程,register.php显然就是简单注册进去然后我们再登录进去,直接再update.php上修改东西,然后bp上改nickname,传入序列化字符串,接着就会触发profile.php的反序列化函数然后打出base64加密的config.php。

 

关键就是,如何构造这个序列化字符串。

这里我使用的是键值逃逸,因为看到有个过滤函数:

对!就是这个,这里的精髓就是,输入一个黑名单字符串,换成了hacker,加入我输入5个字符的where,它会换成6个字符的hacker,这样就逃逸出了一个字符,以小换大。

而且这里也只有where可以用来逃逸,其他的跟hacker一样是6字符。

 

然后就是序列化字符串分析了,我们可以本地跑一下,简单的序列化就是:

逃逸精髓还有一个就是闭合。

原始:

O:1:"a":4:{s:8:"username";s:8:"admin111";s:5:"email";s:11:"111@123.com";s:8:"nickname";s:12:"Eddie_Murphy";s:5:"photo";s:5:"1.png";}

先想好要插入什么,肯定是s:10:"config.php";}直接闭合后面的东西,而且我们传到的是nickname里面,也就是Eddie_Murphy这部分,我们的目的是把photo部分黑了。

同时考虑引号和右花括号闭合,得到真正插入的完整字符串是:

s:8:"nickname";s:12:"";s:5:"photo";s:10:"config.php";}";s:5:"photo";s:5:"1.png";}

有效语句是(右花括号前):

s:8:"nickname";s:12:"";s:5:"photo";s:10:"config.php";}

插入的部分是:

";s:5:"photo";s:10:"config.php";}

一共34个字符,但是前面原始的数据并没有这凭空插入的34个字符,但是前面分析知道where以小换大hacker能逃逸一个字符,那么我们写34次where就能逃逸出34个字符,插入的payload就生效了。

完整payload:

wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php";}

然后就是按流程来,然后在update.php里数组绕过nickname,改包传payload:

 

 

或者说放包:

 

点进去查看源码得到:

丢赛博厨子里就出来了:

 

posted @ 2023-10-14 19:42  Eddie_Murphy  阅读(19)  评论(0编辑  收藏  举报