小迪安全46WEB 攻防-通用漏洞PHP 反序列化原生类漏洞绕过公私有属性

本文主要是介绍小迪安全46WEB 攻防-通用漏洞PHP 反序列化原生类漏洞绕过公私有属性,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

#知识点:

1、反序列化魔术方法全解

2、反序列化变量属性全解

3、反序列化魔术方法原生类

4、反序列化语言特性漏洞绕过

-其他魔术方法

-共有&私有&保护

-语言模式方法漏洞

-原生类获取利用配合 

#反序列化利用大概分类三类

-魔术方法的调用逻辑-如触发条件

-语言原生类的调用逻辑-SoapClient

-语言自身的安全缺陷-CVE-2016-7124

#反序列化课程点:

-PHP&Java&Python

序列化:对象转换为数组或字符串等格式

反序列化:将数组或字符串等格式转换成对象

serialize() //将一个对象转换成一个字符串

unserialize() //将字符串还原成一个对象

#PHP 反序列化漏洞

原理:未对用户输入的序列化字符串进行检测,导致攻击者可以控制反序列化过程,从而

导致代码执行,SQL 注入,目录遍历等不可控后果。在反序列化的过程中自动触发了某些

魔术方法。当进行反序列化的时候就有可能会触发对象中的一些魔术方法。

#魔术方法利用点分析:

触发:

unserialize 函数的变量可控,文件中存在可利用的类,类中有魔术方法:

__construct(): //构造函数,当对象 new 的时候会自动调用

__destruct()//析构函数当对象被销毁时会被自动调用

__wakeup(): //unserialize()时会被自动调用

__invoke(): //当尝试以调用函数的方法调用一个对象时,会被自动调用

__call(): //在对象上下文中调用不可访问的方法时触发

__callStatci(): //在静态上下文中调用不可访问的方法时触发

__get(): //用于从不可访问的属性读取数据

__set(): //用于将数据写入不可访问的属性

__isset(): //在不可访问的属性上调用 isset


Ø 方法&属性-调用详解&变量数据详解

Ø CTF-语言漏洞-__wakeup()方法绕过

Ø CTF-方法原生类-获取&利用&配合其他


#方法&属性-调用详解&变量数据详解

对象变量属性:

public(公共的):在本类内部、外部类、子类都可以访问

protect(受保护的):只有本类或子类或父类中可以访问

private(私人的):只有本类内部可以使用

序列化数据显示:

private 属性序列化的时候格式是%00 类名%00 成员名

protect 属性序列化的时候格式是%00*%00 成员名

__destruct方法:

具体代码:

//__construct __destruct 魔术方法 创建调用__construct 2种销毁调用__destruct
class Test{public $name;public $age;public $string;// __construct:实例化对象时被调用.其作用是拿来初始化一些值。public function __construct($name, $age, $string){echo "__construct 初始化"."<br>";$this->name = $name;$this->age = $age;$this->string = $string;}// __destruct:当删除一个对象或对象操作终止时被调用。其最主要的作用是拿来做垃圾回收机制。//     * 当对象销毁时会调用此方法//    * 一是用户主动销毁对象,二是当程序结束时由引擎自动销毁//    *//*function __destruct(){echo "__destruct 类执行完毕"."<br>";}
}
// 主动销毁
$test = new Test("Spaceman",566, 'Test String');
unset($test);
echo '第一种执行完毕'.'<br>';
echo '----------------------<br>';
// 程序结束自动销毁
$test = new test("Spaceman",566, 'Test String');
echo '第二种执行完毕'.'<br>';

分析

__destruct:当删除一个对象或对象操作终止时被调用。其最主要的作用是拿来做垃圾回收机制    

一是用户主动销毁对象(unset),二是当程序结束时由引擎自动销毁

__toString方法

具体代码:

class Test
{public $variable = 'This is a string';public function good(){echo $this->variable . '<br />';}// 在对象当做字符串的时候会被调用public function __toString()
{return '__toString <br>';}
}$a = new Test();
$a->good();
//输出调用
echo $a;

在对象当做字符串的时候会被调用,即输出变量a——则表示以字符串的形式输出

__CALL方法:

具体代码:

class Test{public function good($number,$string){echo '存在good方法'.'<br>';echo $number.'---------'.$string.'<br>';}// 当调用类中不存在的方法时,就会调用__call();public function __call($method,$args){echo '不存在'.$method.'方法'.'<br>';var_dump($args);}
}$a = new Test();
$a->good(566,'nice');
$b = new Test();
$b->spaceman(899,'no');

调用某个方法, 若方法存在,则直接调用;若不存在,则会去调用__call函数。

__get()

具体代码:

class Test {public $n=123;// __get():访问不存在的成员变量时调用public function __get($name){echo '__get 不存在成员变量'.$name.'<br>';}
}$a = new Test();
// 存在成员变量n,所以不调用__get
echo $a->n;
echo '<br>';
// 不存在成员变量spaceman,所以调用__get
echo $a->spaceman;

读取一个对象的属性时,若属性存在,则直接返回属性值;若不存在,则会调用__get函数与__call方法类似,只不过是其对象属性

__set()方法

具体代码:

class Test{public $data = 100;protected $noway=0;// __set():设置对象不存在的属性或无法访问(私有)的属性时调用//__set($name, $value)// * 用来为私有成员属性设置的值// * 第一个参数为你要为设置值的属性名,第二个参数是要给属性设置的值,没有返回值。public function __set($name,$value){echo '__set 不存在成员变量 '.$name.'<br>';echo '即将设置的值 '.$value."<br>";$this->noway=$value;}public function Get(){echo $this->noway;}
}$a = new Test();
// 读取 noway 的值,初始为0
$a->Get();
echo '<br>';
// 无法访问(私有)noway属性时调用,并设置值为899
$a->noway  = 899;
// 经过__set方法的设置noway的值为899
$a->Get();
echo '<br>';
// 设置对象不存在的属性spaceman
$a->spaceman = 566;
// 经过__set方法的设置noway的值为566
$a->Get();

设置一个对象的属性时,若属性存在,则直接赋值;若不存在,则会调用__set函数。

__sleep()方法:

具体代码:

class Test{public $name;public $age;public $string;// __construct:实例化对象时被调用.其作用是拿来初始化一些值。public function __construct($name, $age, $string){echo "__construct 初始化"."<br>";$this->name = $name;$this->age = $age;$this->string = $string;}//  __sleep() :serialize之前被调用,可以指定要序列化的对象属性public function __sleep(){echo "当在类外部使用serialize()时会调用这里的__sleep()方法<br>";// 例如指定只需要 name 和 age 进行序列化,必须返回一个数值return array('name', 'age');}
}$a = new Test("Spaceman",566, 'Test String');
echo serialize($a);

serialize之前被调用,可以指定要序列化的对象属性。

__wakeup方法:

具体代码:

class Test{public $sex;public $name;public $age;public function __construct($name, $age, $sex){$this->name = $name;$this->age = $age;$this->sex = $sex;}public function __wakeup(){echo "当在类外部使用unserialize()时会调用这里的__wakeup()方法<br>";$this->age = 566;}
}$person = new Test('spaceman',21,'男');
$a = serialize($person);
echo $a."<br>";
var_dump (unserialize($a));

Unserialize反序列化恢复对象之前调用该方法

__isset()方法

具体代码:

class Person{public $sex;private $name;private $age;public function __construct($name, $age, $sex){$this->name = $name;$this->age = $age;$this->sex = $sex;}// __isset():当对不可访问属性调用 isset() 或 empty() 时,__isset() 会被调用。public function __isset($content){echo "当在类外部使用isset()函数测定私有成员 {$content} 时,自动调用<br>";return isset($this->$content);}
}$person = new Person("spaceman", 25,'男');
// public 成员
echo ($person->sex),"<br>";
// private 成员
echo isset($person->name);

检测对象的某个属性是否存在时执行此函数。当对不可访问属性调用 isset() 或 empty() 时,__isset() 会被调用

__unset()方法

具体代码:

class Person{public $sex;private $name;private $age;public function __construct($name, $age, $sex){$this->name = $name;$this->age = $age;$this->sex = $sex;}// __unset():销毁对象的某个属性时执行此函数public function __unset($content) {echo "当在类外部使用unset()函数来删除私有成员时自动调用的<br>";echo isset($this->$content)."<br>";}
}$person = new Person("spaceman", 21,"男"); // 初始赋值
echo "666666<br>";
unset($person->name);//调用 属性私有
unset($person->age);//调用 属性私有
unset($person->sex);//不调用 属性共有

在不可访问的属性(private)上使用unset()时触发

__INVOKE()

具体代码:

class Test{// _invoke():以调用函数的方式调用一个对象时,__invoke() 方法会被自动调用public function __invoke($param1, $param2, $param3)
{echo "这是一个对象<br>";var_dump($param1,$param2,$param3);}
}$a  = new Test();
$a('spaceman',21,'男');

将对象当做函数来使用时执行此方法,通常不推荐这样做。

#私有和公有属性——案例
public(公共的):在本类内部、外部类、子类都可以访问

protect(受保护的):只有本类或子类或父类中可以访问

private(私人的):只有本类内部可以使用

序列化数据显示:

private 属性序列化的时候格式是%00 类名%00 成员名

protect 属性序列化的时候格式是%00*%00 成员名

具体代码:

class test{public $name="xiaodi";private $age="29";protected $sex="man";
}
$a=new test();
$a=serialize($a);
print_r($a);

将age改为public

所以通常对于序列化的数据,要进行一次编码,要考虑到%00的因素

#CTF-语言漏洞-__wakeup()方法绕过——案例

https://buuoj.cn/challenges

通过路径扫描,扫到一个www.zip的地址,访问便可进行下载去文件

此页面以GET方式select的变量接收,根据代码逻辑,得知__destruct方法在程序结束后被调用且password需等于100,__construct方法用new进行构造接收name和password 的值,__wakeup方法,在使用unserializ后自动调用,此时这里就出现了问题

我们要的是admin,而自动调用的是wakeup方法里的guest,那么就需想想wakeup方法该怎么绕过,通过历史漏洞得知——语言特性漏洞

靶场PHP版本符合

即将构造的序列化,变量个数改为3个,符合条件即可

(修改原理)

成功

#CTF-方法原生类-获取&利用&配合其他 

参考:浅析PHP原生类-安全客 - 安全资讯平台

版本会与原生类有直接的关系

-PHP有那些原生类-见脚本使用

Get.php

<?php
$classes = get_declared_classes();
foreach ($classes as $class) {$methods = get_class_methods($class);foreach ($methods as $method) {if (in_array($method, array('__destruct','__toString','__wakeup','__call','__callStatic','__get','__set','__isset','__unset','__invoke','__set_state'))) {print $class . '::' . $method . "\n";}}
} 

会将魔术方法里自带的类给打印出来

-常见使用的原生类-见参加案例

1.ctf-xss

从此代码可以猜测要用的方法可能是To_string,由于它的本身代码就只有这一点,那么无法通过其他对象进行触发To_string,故需要用原生类的To_string,通过get.php,可以得到相关的To_string对象

Exception对象

对其进行构造,并加入xss攻击

成功

2.Ctfshow259

由于此题的getflag();方法,不知道它的具体是什么才可触发,所以先把它姑且为不可访问的类型,也就是可被__call()、__get()所触发,

查看自身的原生类

对其进行搜索

找到构造payload(题目中要求,ip为127.0.0.1,token为ctfshow)

将flag.txt发送到本地

-原生类该怎么使用-见官方说明

0、生成原生类

补:phar、字符串逃逸

反序列化:自身不是漏洞,只是一种方法,在方法中会引发一些危险函数。

这篇关于小迪安全46WEB 攻防-通用漏洞PHP 反序列化原生类漏洞绕过公私有属性的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/845538

相关文章

客户案例:安全海外中继助力知名家电企业化解海外通邮困境

1、客户背景 广东格兰仕集团有限公司(以下简称“格兰仕”),成立于1978年,是中国家电行业的领军企业之一。作为全球最大的微波炉生产基地,格兰仕拥有多项国际领先的家电制造技术,连续多年位列中国家电出口前列。格兰仕不仅注重业务的全球拓展,更重视业务流程的高效与顺畅,以确保在国际舞台上的竞争力。 2、需求痛点 随着格兰仕全球化战略的深入实施,其海外业务快速增长,电子邮件成为了关键的沟通工具。

安全管理体系化的智慧油站开源了。

AI视频监控平台简介 AI视频监控平台是一款功能强大且简单易用的实时算法视频监控系统。它的愿景是最底层打通各大芯片厂商相互间的壁垒,省去繁琐重复的适配流程,实现芯片、算法、应用的全流程组合,从而大大减少企业级应用约95%的开发成本。用户只需在界面上进行简单的操作,就可以实现全视频的接入及布控。摄像头管理模块用于多种终端设备、智能设备的接入及管理。平台支持包括摄像头等终端感知设备接入,为整个平台提

滚雪球学Java(87):Java事务处理:JDBC的ACID属性与实战技巧!真有两下子!

咦咦咦,各位小可爱,我是你们的好伙伴——bug菌,今天又来给大家普及Java SE啦,别躲起来啊,听我讲干货还不快点赞,赞多了我就有动力讲得更嗨啦!所以呀,养成先点赞后阅读的好习惯,别被干货淹没了哦~ 🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,助你一臂之力,带你早日登顶🚀,欢迎大家关注&&收藏!持续更新中,up!up!up!! 环境说明:Windows 10

2024网安周今日开幕,亚信安全亮相30城

2024年国家网络安全宣传周今天在广州拉开帷幕。今年网安周继续以“网络安全为人民,网络安全靠人民”为主题。2024年国家网络安全宣传周涵盖了1场开幕式、1场高峰论坛、5个重要活动、15场分论坛/座谈会/闭门会、6个主题日活动和网络安全“六进”活动。亚信安全出席2024年国家网络安全宣传周开幕式和主论坛,并将通过线下宣讲、创意科普、成果展示等多种形式,让广大民众看得懂、记得住安全知识,同时还

【Kubernetes】K8s 的安全框架和用户认证

K8s 的安全框架和用户认证 1.Kubernetes 的安全框架1.1 认证:Authentication1.2 鉴权:Authorization1.3 准入控制:Admission Control 2.Kubernetes 的用户认证2.1 Kubernetes 的用户认证方式2.2 配置 Kubernetes 集群使用密码认证 Kubernetes 作为一个分布式的虚拟

企业安全之WiFi篇

很多的公司都没有安全团队,只有运维来负责整个公司的安全,从而安全问题也大打折扣。我最近一直在给各个公司做安全检测,就把自己的心得写下来,有什么不足之处还望补充。 0×01  无线安全 很多的公司都有不怎么注重公司的无线电安全,有钱的公司买设备,没钱的公司搞人力。但是人的技术在好,没有设备的辅助,人力在牛逼也没有个卵用。一个好的路由器、交换机、IDS就像你装备了 无尽、狂徒、杀人书一

小技巧绕过Sina Visitor System(新浪访客系统)

0x00 前言 一直以来,爬虫与反爬虫技术都时刻进行着博弈,而新浪微博作为一个数据大户更是在反爬虫上不遗余力。常规手段如验证码、封IP等等相信很多人都见识过…… 当然确实有需要的话可以通过新浪开放平台提供的API进行数据采集,但是普通开发者的权限比较低,限制也比较多。所以如果只是做一些简单的功能还是爬虫比较方便~ 应该是今年的早些时候,新浪引入了一个Sina Visitor Syst

PHP原理之内存管理中难懂的几个点

PHP的内存管理, 分为俩大部分, 第一部分是PHP自身的内存管理, 这部分主要的内容就是引用计数, 写时复制, 等等面向应用的层面的管理. 而第二部分就是今天我要介绍的, zend_alloc中描写的关于PHP自身的内存管理, 包括它是如何管理可用内存, 如何分配内存等. 另外, 为什么要写这个呢, 因为之前并没有任何资料来介绍PHP内存管理中使用的策略, 数据结构, 或者算法. 而在我们

HTML5自定义属性对象Dataset

原文转自HTML5自定义属性对象Dataset简介 一、html5 自定义属性介绍 之前翻译的“你必须知道的28个HTML5特征、窍门和技术”一文中对于HTML5中自定义合法属性data-已经做过些介绍,就是在HTML5中我们可以使用data-前缀设置我们需要的自定义属性,来进行一些数据的存放,例如我们要在一个文字按钮上存放相对应的id: <a href="javascript:" d

php中json_decode()和json_encode()

1.json_decode() json_decode (PHP 5 >= 5.2.0, PECL json >= 1.2.0) json_decode — 对 JSON 格式的字符串进行编码 说明 mixed json_decode ( string $json [, bool $assoc ] ) 接受一个 JSON 格式的字符串并且把它转换为 PHP 变量 参数 json