buuctf web [极客大挑战 2019]PHP

buuctf web [极客大挑战 2019]PHP_第1张图片

提示有备份,dirsearch扫描网站备份

GitHub - maurosoria/dirsearch: Web path scanner下载.zip格式文件

解压到python目录下

buuctf web [极客大挑战 2019]PHP_第2张图片

在上图位置cmd打开窗口

buuctf web [极客大挑战 2019]PHP_第3张图片

输入python setup.py install安装dirsearch

buuctf web [极客大挑战 2019]PHP_第4张图片

安装好后输入命令使用dirsearch

python dirsearch.py -u http://44296191-973d-448e-9964-d30eab452926.node4.buuoj.cn:81/ -e php

buuctf web [极客大挑战 2019]PHP_第5张图片

发现了www.zip压缩包

buuctf web [极客大挑战 2019]PHP_第6张图片

网址输入www.zip,下载zip包

buuctf web [极客大挑战 2019]PHP_第7张图片

打开www.zip压缩包,里面的文件挨个看看

buuctf web [极客大挑战 2019]PHP_第8张图片

index.php



  
  I have a cat!
  
      




因为每次猫猫都在我键盘上乱跳,所以我有一个良好的备份网站的习惯
不愧是我!!!

Syclover @ cl4y

这部分代码重点为

buuctf web [极客大挑战 2019]PHP_第9张图片

意思是:引用class.php页面,用get方法传参,获取变量select,将select进行反序列化,@符号表示忽略可能出现的错误信息。

unserialize() 函数
unserialize() 函数用于将通过 serialize() 函数序列化后的对象或数组进行反序列化,并返回原始的对象结构。

(反序列:序列转数组)

unserialize ($str )
$str:序列化的字符串(序列化字符串i表示位置,s表是大小)
如果传递的字符串不可解序列化,则返回 FALSE,并抛出异常

buuctf web [极客大挑战 2019]PHP_第10张图片

buuctf web [极客大挑战 2019]PHP_第11张图片

serialize() 函数
serialize() 函数用于序列化对象或数组,并返回一个字符串。

serialize() 函数序列化对象后,可以很方便的将它传递给其他需要它的地方,且其类型和结构不会改变.

(序列化:数组转序列)

serialize ($value )
$value: 要序列化的对象或数组。

buuctf web [极客大挑战 2019]PHP_第12张图片

class.php页面

username = $username;
        $this->password = $password;
    }

    function __wakeup(){
        $this->username = 'guest';
    }

    function __destruct(){
        if ($this->password != 100) {
            echo "
NO!!!hacker!!!
"; echo "You name is: "; echo $this->username;echo "
"; echo "You password is: "; echo $this->password;echo "
"; die(); } if ($this->username === 'admin') { global $flag; echo $flag; }else{ echo "
hello my friend~~
sorry i can't give you the flag!"; die(); } } } ?>

发现可以输出flag的地方

在_destuct()函数下,要求的条件是password==100,username==='admin',具体来看看各个函数

__construct
构造函数(也称为构造器)是类中的一种特殊函数,当使用 new 关键字实例化一个对象时,构造函数将会自动调用。代码中用到了 $this,它表示当前调用的对象,而且 $this 只能在类的方法中使用.

buuctf web [极客大挑战 2019]PHP_第13张图片

__wakeup()
__wakeup():当类外部使用`unserialize()` 时,会检查是否存在一个 `__wakeup()` 方法。如果存在,则会先调用 `__wakeup` 方法,预先准备对象需要的资源。

题目中的作用:
__wakeup() 经常用在反序列化操作中,例如重新建立数据库连接,或执行其它初始化操作。
这里的作用就是先将username赋值,使我们传入的username永远为guest。

buuctf web [极客大挑战 2019]PHP_第14张图片

__destruct():

析构函数/方法,析构函数的作用和构造函数正好相反,析构函数只有在对象被垃圾收集器收集前(即对象从内存中删除之前)才会被自动调用。析构函数允许我们在销毁一个对象之前执行一些特定的操作,例如关闭文件、释放结果集等。

buuctf web [极客大挑战 2019]PHP_第15张图片

作用:
这里的作用是,在wakeup函数调用完后,进行判断,如果password不为100为真:抛出错误回显,并利用die()函数退出当前脚本
如果为假,也就是password=100,接着强类型比较username是否=== admin 如果为真就打印flag

所以本题主要是,需要绕过wakeup函数强制将username赋值为guest。

因为在反序列化时,当前属性个数大于实际属性个数时,就会跳过__wakeup(),去执行__destruct。

尝试构造payload

buuctf web [极客大挑战 2019]PHP_第16张图片

"O:4:"Name":3:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";s:3:"100";}"

且因为声明变量时使用的时private(私有变量),所以payload应为:

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

ps:补充

public 、public、protected
类中的 公有、私有、受保护成员

public 表示全局,类内部外部子类都可以访问;

private表示私有的,只有本类内部可以使用;

protected表示受保护的,只有本类或子类或父类中可以访问;

不同的访问修饰符对应的序列化也有不同。

各访问修饰符序列化后的区别:

public:属性被序列化的时候属性名还是原来的属性名,没有任何改变

protected:属性被序列化的时候属性名会变成\0*\0字段名

private:属性被序列化的时候属性名会变成\0类名\0字段名

buuctf web [极客大挑战 2019]PHP_第17张图片

你可能感兴趣的:(php,开发语言)