我的编程空间,编程开发者的网络收藏夹
学习永远不晚

[极客大挑战 2019]PHP1

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

[极客大挑战 2019]PHP1

既然提到了备份网站估计也是存在着网站备份文件,可以先用御剑扫一下

啥都没扫出来,但是上回做文件备份的题目时收集了一些关于常用备份文件的文件名和后缀,可以直接使用burp抓包爆破,果然爆破出一个www.zip文件

访问下载好文件就有三个php文件,下面进行代码审计

访问index.php

首先访问一哈index.php 里面主要是网页代码,不过中间插了一段

包含了class.php文件

定义了一个存放GET请求方法的变量select

将select变量的值进行反序化为 PHP 对象 @表示忽略可能出现的错误信息

   

unserialize() 函数

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

语法结构
unserialize ($str )
$str:序列化的字符串
如果传递的字符串不可解序列化,则返回 FALSE,并抛出异常

如果不可解序列化,则返回false

serialize() 函数

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

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

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

可以看到,当序列化以后输出的结果是一串字符。

a:表示一个数组,由array首字符表示,例如int序列化后回显就是i

4:表示数组的元素个数为4

{}:数组元素的集合(下标 +元素)

i:表示是整型,0:表示元素内容,这里是数组下标

s:表示类型为字符串,长度为6,内容为:Google

访问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.php文件,定义了一个叫Name的类,声明了两个私有变量(顾名思义:变量属性或方法只能在Name类中使用)

__construct

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

以下代码大致的意思就是:

定义了一个名为Web的类,该类有三个属性:name、url和title,以及一个构造函数__construct()。构造函数在创建Website对象时自动调用,它接受三个参数并将它们分别赋值给类的属性。

构造函数还调用了类的另一个方法ec(),该方法会输出对象的属性值。

最后,创建了一个Web对象$object,并传入了三个参数。在构造函数中,$object的属性被赋值并输出。因为类无法直接访问,需要得到类的具体对象才能访问,可以通过实例化new来实现对象的创建

__wakeup()

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

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

__destruct():

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

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

所以到现在为止,唯一的问题就是当我们给username赋值后,因为脚本引用了unserialize() 函数,所以,wakeup方法将会再给username赋值为guest,我们得想方法绕过

经过查看wp得知,在反序列化时,当前属性个数大于实际属性个数时,就会跳过__wakeup(),去执行__destruct

但是好像是因为我PHP版本有点高所以不受影响,不能展示了,直接构造吧

解题步骤

首先我们需要获取传入参数的序列化字符串

然后赋值字符串,构造payload,但是并没有成功

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

查看wp后得到有关私有变量的解释

public 、public、protected

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

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

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

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

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

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

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

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

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

所以我们重新构造payload,这里利用%00表示\0

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

获得flag

来源地址:https://blog.csdn.net/qq_49893996/article/details/130670569

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

[极客大挑战 2019]PHP1

下载Word文档到电脑,方便收藏和打印~

下载Word文档

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录