老规矩,分析代码,一般给你一大堆代码的题目肯定是其中某个函数有漏洞啥的
过滤函数filter,其中implode函数的作用是:将$filter_arr这个数组合并为一个字符串,并以|分割开来;所以这个正则表达式是preg_replace(/php|flag|php5|php4|f1lg/i,”,$img);filter函数作用就是过滤这五个字符串。
如果$_SESSION存在,则销毁它(unset) ,然后是字典的键值对的对应,extract这个函数重中之重!!!它会将你post传入的参数和值形成一个键值对:如:POST方法传入一个/?_SESSION[user]=flag,他会给你变为$_SESSION[“user”]=’flag’,后面我们要用到;
接下来如果不给f参数传参的话,则会返回index.php?f=highlight_file这个界面;如果给img_path不传参数,他会将guest_img.png进行base64编码后赋值给img这个键,如果传参数,会将你传的值进行base64编码后在进行sha1赋值给img,这两种都会阻碍我们获得flag,因此img_path这个变量是我们要思考的地方了
将session数组序列化后进行过滤,然后是f变量的三个值,这里提示叫我们去phpinfo看看,因为这里没有其他条件,我们直接f=phpinfo即可。
可以看到有d0g3_f1ag.php这个文件,再看到f=show_image的时候会输出file_get_contents读书文件内容函数,因此我们这里思路就是如何让 d0g3_f1ag.php这个文件传到这里面去。
逆向思维:
1:将$userinfo[‘img’]的值进行base64编码(也就是将d0g3_f1ag.php进行编码成ZDBnM19mMWFnLnBocA==)
2:userinfo是由serialize_info反序列化得来的
3:serialize_info又是由$_SESSION这个数组经过序列化编码,再进行过滤得来
因此我们现在的目标就是如何让序列化后且过滤后的字符串img的值为ZDBnM19mMWFnLnBocA==
如果我们直接利用extract函数可以post传入/?_SESSION[img]=ZDBnM19mMWFnLnBocA==;从而可以让$_SESSION[‘img’]=’ZDBnM19mMWFnLnBocA==’;
但是由于这个if语句的存在,因为我们没有传入img_path,因此它会将base64编码后的一个字符串覆盖我们传入的img值,因为他是后天的,因此我们这一步算是失败了。所以这里考的是一个反序列化的时候
字符
逃逸
这里借鉴一下网上大佬的payload,我是理解但是写不出来哈哈哈
a:2{s:7:”phpflag”;s:48:”;s:1:”1″;s:3:”img”;s:20:”ZDBnM19mMWFnLnBocA==”;}”;s:3:”img”;s:20:”Z3Vlc3RfaW1nLnBuZw==”;}
有没有发现有两个},但是会默认只算前面那个},跟if语句一样,哪里先括起来就哪里运行结束,后面的就不管了,后面的加的base64就被我们丢弃了,a:2{s:7:”phpflag”;s:48:”;s:1:”1″;s:3:”img”;s:20:”ZDBnM19mMWFnLnBocA==”;}
这里还会经过filter函数,从而变成a:2{s:7:””;s:48:”;s:1:”1″;s:3:”img”;s:20:”ZDBnM19mMWFnLnBocA==”;},phpflag被过滤掉了,因此这里就是字符逃逸的地方了,s:7代表后面有七个字符,但是现在被过滤掉了怎么办呢,会直接继续往后面不管什么字符取七位给他用,意味着a:2{s:7:”
;s:48:;
“s:1:”1″;s:3:”img”;s:20:”ZDBnM19mMWFnLnBocA==”;}将后面的;s:48:;作为他的新键,这就是字符逃逸。将img的键值对藏在phpflag里面,反序列化的时候才会出现
更改flag的名字L2QwZzNfZmxsbGxsbGFn记得带分号,也是20位,更替
记清楚这个思路,看到的时候真的感觉懂了好多哈哈
还是不太理解字符逃逸的,我讲的有点简单,可以看一下
PHP反序列化字符逃逸详解 – SecPulse.COM | 安全脉搏