平台:buuoj.cn
打开靶机如下:
弱密码,sql乱试一波没反应,注册个账号进去之后让我们更新信息
提交跳转到profile.php
扫一下网站目录。(我们在做题扫目录的时候经常会遇见429的情况,这时候就需要调整一下扫描参数,比如dirsearch添加个延时参数,这样就大大提高了扫描效率)
最后结果如下:
还是有好多没扫出来(逃)
有个www.zip源码泄露,下载下来解压如下:
在config.php里看见了flag,但不可读
profile.php里有反序列化
后面我们看到了$photo变量有经过file_get_contents处理,这里出现了利用点,如果我们把$profile[‘photo’]替换为config.php,那么我们就能读取config.php里的flag
在源码里整理一下逻辑结构
register->login->update->profile
登录和注册不看,从update开始对各个参数进行一些过滤,然后序列化$profile,跟进update_profile
跟进过滤
这里正则把一些操纵函数替换成hacker
分析
前面已经知道,我们的目的是要读取config.php从而得到flag,读取config.php需要替换$profile[‘photo’],也就是要让config,php成为序列化的一部分,可以利用的是反序列化字符串逃逸
在后端中,反序列化是以";}结束的,因此如果我们把";}带入需要反序列化的字符串中(除了结尾处),就能让反序列化提前结束而后面的内容就会被丢弃
由
可以得知他序列化后的字符串应为:
a:4:{s:5:"phone";s:11:"12345678901";s:5:"email";s:12:"12345@qq.com";s:8:"nickname";s:3:"123";s:5:"photo";s:39:"upload/07cc694b9b3fc636710fa08b6922c42b";}
把config.php从nickname塞进去就变成了
a:4:{s:5:"phone";s:11:"12345678901";s:5:"email";s:12:"12345@qq.com";s:8:"nickname";s:3:"123";s:5:"photo";s:10:"config.php";}s:39:"upload/07cc694b9b3fc636710fa08b6922c42b";}
虽然给他反序列化之后结果photo的部分是config,php,但这样是读不到config.php的,因为更新profile的时候根本没地方插进去,因此就需要从nickname入手把这些数据悄悄带进去
首先解决nickname的长度限制问题
直接将nickname变成数组就可突破限制
a:4:{s:5:"phone";s:11:"12345678901";s:5:"email";s:12:"12345@qq.com";s:8:"nickname";a:1:{i:0;s:3:"123";}s:5:"photo";s:10:"config.php";}s:39:"upload/07cc694b9b3fc636710fa08b6922c42b";}
现在我们考虑怎么让";}s:5:“photo”;s:10:“config.php”;}这34个字符逃逸出来
前面提到Fliter会将where一类的函数替换成hacker,也就是说where在被正则替换后,其本身的长度会加1,如果我们构造34个where
34*5 = 170 170+34个字符=204=len(''hacker")*34
那么在传入后端之后hacker的长度就会将我们目标逃逸字符挤掉
过程如下
传入:
s:8:"nickname";a:1:{i:0;s:204:"34*where";}s:5:"photo";s:10:"config.php";}
此时34*where";}s:5:"photo";s:10:"config.php";}都作为nickname存在
正则替换:
s:8:"nickname";a:1:{i:0;s:204:"34*hacker";}s:5:"photo";s:10:"config.php";}
因为s只有204个字符,所以读取第34个hacker之后就停止,34个字符";}s:5:"photo";s:10:"config.php";}不再包含在nickname内
既然从nickname逃逸出,"};
将前面的nickname数组闭合之后,剩下的s:5:"photo";s:10:"config.php";}
就会被当作photo的部分了,至于后面的upload,由于被后面";}
结束反序列化,也就被丢弃,这样就实现了config.php的读取
解题
登陆注册之后用burp抓个包将nickname改为数组,构造内容
访问profile后在源码里发现base字符串
解码即得flag