[网鼎杯 2020 青龙组]AreUSerialz
2014 年 3 月 4 日
题目分析
process(); } public function process() { if($this->op == "1") { $this->write(); } else if($this->op == "2") { $res = $this->read(); $this->output($res); } else { $this->output("Bad Hacker!"); } } private function write() { if(isset($this->filename) && isset($this->content)) { if(strlen((string)$this->content) > 100) { $this->output("Too long!"); die(); } $res = file_put_contents($this->filename, $this->content); if($res) $this->output("Successful!"); else $this->output("Failed!"); } else { $this->output("Failed!"); } } private function read() { $res = ""; if(isset($this->filename)) { $res = file_get_contents($this->filename); } return $res; } private function output($s) { echo "[Result]:
"; echo $s; } function __destruct() { if($this->op === "2") $this->op = "1"; $this->content = ""; $this->process(); } } function is_valid($s) { for($i = 0; $i = 32 && ord($s[$i]) <= 125)) return false; return true; } if(isset($_GET{'str'})) { $str = (string)$_GET['str']; if(is_valid($str)) { $obj = unserialize($str); } }
1.传入str,经过处理反序列化。 2.is_valid过滤:传入的string要是可见字符ascii值为32-125。 3.$op:op=="1"的时候会进入write方法处理,op=="2"的时候进入read方法处理。
利用php>7.1版本对类属性的检测不严格(对属性类型不敏感)
1.正常构造payload的话因为$op、$fliename、$content都是protected属性,序列化的的结果的属性名前面会有/00 /00(或者%00 %00),/00的ascii为0不可见的字符如下图,就会被is_valid方法拦下来。
2.php>7.1版本对类属性的检测不严格来绕过,将序列化里的portected属性换成public属性,就不会有/00。
3.弱类型绕过
然后$obj = unserialize($str);会调用__destruct魔术方法,如果$op=
“2”的话就把$op=”1″
这时候要使op
=”2″不成立且op==”2″成立,这里可以自己使用op等于整数2使得进入read方法里面。
构造payload
1.非预期的解法
2.通过php伪协议读取
比赛的是通过读取/proc/self/cmdline下的配置文件得到网站的绝对路径然后通过php伪协议读取flag的
参考:( https://blog.csdn.net/Oavinci/article/details/106998738 )[ https://blog.csdn.net/Oavinci/article/details/106998738 ]