网安之web攻防第四十六天笔记

目录

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

#魔术方法利用点分析:

__construct __destruct 魔术方法 创建调用__construct 销毁调用__destruct

__toString():在对象当做字符串的时候会被调用

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

__get() 魔术方法 读取一个对象的属性时,若属性存在,则直接返回属性值;若不存在,则会调用__get函数

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

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

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

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

__unset():在不可访问的属性上使用unset()时触发 销毁对象的某个属性时执行此函数

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

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

[极客大挑战 2019]PHP CVE-2016-7124

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

本地Demo-xss

ctfshow259


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

对象变量属性:

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

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

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

序列化数据显示:

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

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

这里我们拿个案例演示一下

这里可以发现,序列化之后的值的私有和保护的变量的长度不一样了,本来应该是s:3:"age",这里它变成了s:9:"testage"。根据我们上面说的就可以知道,私有属性序列化之后是%00test%00age,所以这里是9位,%00没有显示占一位。而保护属性同理序列化之后变成%00*%00sex,占六位。而正是这样在序列化之后,我们才可以区分公共,私有和保护,不然他们都一样,都没法分辨了。

#魔术方法利用点分析:

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

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

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

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

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

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

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

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

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

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

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

__toString(): //把类当作字符串使用时触发

__sleep(): //serialize()函数会检查类中是否存在一个魔术方法__sleep() 如果存在,该方法会被优先调用

首先我们先对这个魔术方法进行讲解,上一节只说了三四个,这一节先具体的来说一下。

__construct __destruct 魔术方法 创建调用__construct 销毁调用__destruct

这两个比较简单,上一节也讲过,有一点需要注意的是注意一下主动销毁和程序结束自动销毁的区别。主动销毁的话你会发现,他会先执行__destruct这个魔术方法然后才输出下面这个“第一次执行结束”的语句,而程序执行结束自动销毁则是先输出这个语句,然后再调用这个魔术方法。

主动销毁:

程序结束自动销毁:

__toString():在对象当做字符串的时候会被调用

这里它先把test这个类实例化,然后调用里面的good这个函数了。这时就会输出“This is a string”,而如果执行下面这个echo $a,就相当于把a这个对象当作字符串去执行了。就会执行这个__toString()魔术方法,进而输出__toString。

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

首先这个good这个方法再test这个类里面是存在的,然后spaceman这个方法是不存在的,所以当我们调用这个spaceman这个函数的时候,就会触发这个__call()魔术方法。

__get() 魔术方法 读取一个对象的属性时,若属性存在,则直接返回属性值;若不存在,则会调用__get函数

这里首先把test这个类实例化,然后创建了一个特定的对象a去调用类里面的函数或变量,然后因为类里面没有spaceman这个变量,所以我们也调用不了,这时就会触发__get() 魔术方法。

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

这里因为不可以设置私有属性的值,所以就会触发__set()魔术方法,对象不存在的时候设置属性也是一样的,也会触发这个__set()魔术方法。可以通过__set() 方法用于设置私有属性值。并且私有属性是只能在本类内部可以调用,外部是不能调用访问的。至于输出结果的零是类内部调用的,输出语句直接在类的内部。

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

这个魔术方法就是只要用到序列化函数serialize()就会调用这个魔术方法,因此我们可以看到输出的结果是先输出的"当在类外部使用serialize()时会调用这里的__sleep()方法
"这句话再输出的序列化之后的值。

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

这个和刚才那个魔术方法相反,他是出现反序列化函数unserialize()的时候被触发。

如果把代码的最后一行注释掉,只会输出结果的第一行。

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

这个就是判断对象的某个属性是否存在就会触发这个魔术方法,简单来说就是isset() 或 empty()这两个函数,有这两个函数就可以判断对象里面的属性是否存在,那就会触发这个魔术方法了。这里先输出sex对象的属性值为男,然后因为有这个isset函数判断name是否有值,就触发了__isset()魔术方法。并且这里因为name的对象有属性,所以就输出了1。

__unset():在不可访问的属性上使用unset()时触发 销毁对象的某个属性时执行此函数

这个是当变量的属性不可访问时,并且调用了unset这个函数就会触发这个魔术方法,这里因为name和age是私有的对象,所以是不能在外部调用的,并且也使用了unset这个函数,因此就触发了这个魔术方法。

这个unset和isset这两个魔术方法,通常在ctf中当变量为私有的时候出现。

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

这个就比较简单了,平常我们都是利用这个特定的对象去调用类里面的变量或则函数,而这里直接把这个对象当成函数去执行,所以就触发了这个魔术方法。

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

这个直接在buuctf上面搜索极客大挑战2019即可,php的那个就是,我们打开之后如下图,通过文字信息判断网站源码可能直接被探测工具探测到,直接就下载到了名为www.zip的源码,访问不到的多刷新几次即可。

将源码下载下来之后首先打开index.php,然后发现这里包含了一个class.php这个文件,并且下面接受了一个变量为select。并且使用了反序列化函数unserialize()。

打开class.php,我们可以发现它这里引用了三个魔术方法,想要输出flag的话,就需要保证username为admin,并且password的值为100才可以,那我们直接构造pop链,

直接把我们需要的admin和100写进去,先序列化然后url编码一下即可。然后输入select变量的值等于这个。会发现得不到答案,这是因为__wakeup这个魔术方法只要有unserialize()这个反序列化函数就会把username的值改成guest,所以才得不到flag。

这里就要配合语言自身的安全缺陷去绕过__wakeup这个魔术方法来获取flag了,可以配合CVE-2016-7124这个漏洞去绕过,这里对php的版本有要求,而本靶场的php版本通过抓包得知为5.3,那显然是符合的。当序列化字符串中表示对象属性个数的值大于 真实的属性个数时会跳过__wakeup的执行,就是利用这个来绕过,我们直接把序列化之后的2改成3,也就是说实际是两个变量,我们改成三,就可以去绕过这个魔术方法了。

最后把修改之后的pop链换上去就得到了flag。

回顾一下:

[极客大挑战 2019]PHP CVE-2016-7124

如果存在__wakeup方法,调用unserilize()方法前则先调用__wakeup方法,

但是序列化字符串中表示对象属性个数的值大于真实的属性个数时会跳过__wakeup的执行

1、下载源码分析,触发flag条件

2、分析会触发调用__wakeup 强制username值

3、利用语言漏洞绕过 CVE-2016-7124

4、构造payload后 修改满足漏洞条件触发

Pyload:

select=O%3A4%3A"Name"%3A3%3A%7Bs%3A14%3A"%00Name%00username"%3Bs%3A5%3A"admin"%3Bs%3A14%3A"%00Name%00password"%3Bi%3A100%3B%7D

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

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

对于这个原生类的知识,主要是从一下三个方面去说明。

-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";

}

}

}

直接放到phpstudy里面,用浏览器访问即可。

我们会用两个案例去讲解原生类,一个是本地搭建的,一个上一节的259关的ctfshow。

本地Demo-xss

浏览器访问之后发现就三行代码,里面没有可以利用的魔术方法,但是有两点我们需要注意的,接受参数为k,这里它直接输出的对象a,也就是说可以触发__toString()这个魔术方法,因为把类当作字符串使用了。但是这里也没有能利用的魔术方法,所以就只能看该魔术方法对应的原生类了。

通过查找,发现Exception这个原生类我们可以利用。进而触发该魔术方法,最终实现xss

最后回顾一下流程:

输出对象可调用__toString

无代码通过原生类Exception

Exception使用查询编写利用

通过访问触发输出产生XSS漏洞

ctfshow259

思路:

不存在的方法触发__call

无代码通过原生类SoapClient

SoapClient使用查询编写利用

通过访问本地Flag.php获取Flag

php

$ua="aaa\r\nX-Forwarded-For:127.0.0.1,127.0.0.1\r\nContent-Type:application/x-www-form-urlencoded\r\nContent-Length:13\r\n\r\ntoken=ctfshow";

$client=new SoapClient(null,array('uri'=>'http://127.0.0.1/','location'=>'http://127.0.0.1/flag.php','user_agent'=>$ua));

echo urlencode(serialize($client));

?>

(7条消息) CTFshow 反序列化 web259_Kradress的博客-CSDN博客

到这里php的反序列化就学完了,接下来就是java和python的反序列化了。

反序列化并不是一个漏洞,他只是一个功能把算是,用来传递数据的。反序列化漏洞成因通常是因为一些能够触发的魔术方法,而这个魔术方法里面有一些危险函数,比如sql语句,文件下载函数。那么就会出现相应的漏洞。大部分反序列化漏洞就是触发魔术方法,然后触发了一些危险函数。而这个原生类就是魔术方法内置的基类,可以通过原生类去触发魔术方法,再触发危险函数,进而产生反序列化漏洞。

而反序列化的预防就是说对引用魔术方法的地方去更加严格的检查把算是,能不用就不用,用了就写严格一点,不要被随意调用。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xiaopeisec

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值