最近,我遇到了几个与PHP代码审计相关的问题。 之前没有做过系统的总结,这里补一下。
0x01 基础知识
这里主要讲传统PHP中的“服务器”。至于什么是服务器,什么是客户端,可以看看P神**客户端带来的安全问题
概念:在计算机中,特别是在网络应用中,称为“会话控制”。 该对象存储特定用户会话所需的属性和配置信息。 这样,当用户在应用程序中的网页之间跳转时,存储在对象中的变量不会丢失,而是会在整个用户会话期间持续存在。 当用户从应用程序请求网页时,如果用户还没有会话,则 Web 服务器会自动创建一个对象。 当会话过期或被放弃时,服务器将终止该会话。
机制:内容一般以文件的形式存储在服务器中,本地浏览器会在服务器中存储一个与该文件对应的值。 存储的是键值为“”的值。 当用户访问Web应用程序时,每次跳转发生http请求时,都会自动发送存储的值,因此Web应用程序的所有页面都可以获得该值。 也就是说,可以获取到服务器中存储的值。 当用户关闭浏览器时,存储的值将自动清除。 ,一般情况下服务器上存储的文件会在30分钟后自动清除。
例如在wamp环境下,index.php如下:
<?php
session_start();
phpinfo();
?>
首先了解一下()
当会话自动启动或者通过()手动启动时,PHP内部会根据客户端的输入获取已有的相应会话数据(即文件)。 PHP会自动反序列化文件内容,并将其填充到$super全局变量中。 如果对应的会话数据不存在,则创建一个名为SID的文件(由客户端传递)。 如果客户端没有发送,则创建一个 32 个字母的并返回 set-。
可以在请求中看到对应的:
在服务器端,在/wamp/tmp下,我们可以找到生成的记录文件。 由于没有记录会话信息,因此该文件是一个空文件。
添加一些php相关配置的说明
php.ini中有很多配置。 在这里我们将解释几个重要的点。
描述如下:
session.save_path="" --设置session的存储路径
session.save_handler="" --设定用户自定义存储函数,如果想使用PHP内置会话存储机制之外的可以使用本函数(数据库等方式),默认files以文件存储
session.auto_start boolen --指定会话模块是否在请求开始时启动一个会话,默认为0不启动
session.serialize_handler string --定义用来序列化/
常见的 php 存储位置
/var/lib/php5/
/var/lib/php7/
/var/lib/php/
/tmp/
/tmp//
0x02 可能的攻击面 0x03 序列化攻击
要了解序列化攻击,我们首先了解序列化在机制中是如何处理的。
php中有3个序列化处理引擎
.对应的存储格式
php
键名+竖线+()函数序列化的值
键名+键名+()函数序列化的值的长度对应的ASCII字符
(php >= 5.5.4)
通过 () 函数序列化数组
本地测试如下:
文件内容对应的结果为:
test|s:7:"CoCo1er";
<0x04>tests:7:"CoCo1er";
a:1:{s:4:"test";s:7:"CoCo1er";}
攻击与利用原理
其中数以千计,原则第一。
(这里补充一下,在PHP中实现是没有问题的,危害主要是程序员使用不当造成的,如下)
使用不同的引擎处理文件
如果 PHP 反序列化存储的 $ 数据所使用的引擎与序列化所使用的引擎不同,则数据将无法正确反序列化。 通过精心构造的数据包,可以绕过程序验证或执行某些系统方法。 例如:
在这种情况下:
如果我们在数据存储的时候使用引擎对数据进行序列化,我们就可以得到内容
$_SESSION[‘key’] = ‘Boby’;
a:1:{s:3:”key”;s:4:”Boby”;}
这时候我们的分析使用了另外一个引擎:php
想想这个时候会发生什么? (在PHP引擎中,竖线用于分隔键和值)
如果我们像上面那样改的话,传入的内容和获取到的存储内容如下:
$_SESSION['key'] = '|O:4:"User":0:{}';
a:1:{s:3:"key";s:16:"|O:4:"User":0:{}";}
此时a:1:{s:3:"key";s:16:"被视为密钥。
后面的 O:4:"User":0:{}";} 被当做 value 来反序列化,这里可能有人会问,为什么要反序列化呢?
看一下官方文档
这里可能还会有人问? 该字符串值不符合反序列化字符串的“正常”规则。 不用担心这个。 这里提到的特点之一是以前做题的时候遇到过的。 执行过程中,如果字符串符合可反序列化的规则,则后续的不规则字符将被忽略。
如果不容易理解,为什么不直接看一下网上的测试用例:
综上所述,当PHP由引擎生成并被PHP引擎解析时,我们可能会通过传入$['name'] = | 这样的形式来触发反序列化漏洞。 序列化内容。 当然,这只是提到了反序列化可以被利用的点。 反序列化漏洞是否能够真正被触发,取决于当前的环境以及某些神奇功能是否存在可利用点。 这就涉及到利用PHP反序列化漏洞的知识了,这里不再赘述。 关于反序列化攻击的复杂利用,请参考 的问题。
没有 $ 赋值
从上面的情况我们可以发现我们的赋值是可控的。 那么如果代码中没有给$变量赋值怎么用呢? 我们再看下一点。
PHP还有一种机制,可以在$中自动创建键值对,而值中恰好有用户可控的部分。
写法主要是使用PHP来设置。 具体来说,上传文件时,如果 POST 一个名为 name 的变量,则可以为其赋值。
//上传表单
由于该字段可写,因此满足可控条件。 后续使用情况与上述场景一致。 两个不同的引擎先后起作用,导致恶意序列化字符串被解析。
0x04 文件包含
这也是一个比较老的知识点了。 事实上,这不仅仅是文件包含。 仔细想一想,理论上只要能在文件中写入php代码然后就可以实现了是吧? 只不过我们这里的可控点是文件。 如果我们可以将PHP代码写入其中,我们也可以利用文件包含漏洞。
此处未显示文件中包含的应用程序。 有关这方面的基本信息已经可以在线获取。
值得一提的是,现在的CTF题目往往并不局限于文件中包含的点,而是使用+lfi等形式输入题目来获取源代码。 并且可能会添加它来限制路径。 这时候就需要熟悉机制并使用更改保存路径的功能。 这个想法是 XCTF Final 中出现的一个问题的测试点。 有兴趣的同学可以找一个复现的环境。
0x05 假用户登录
前几天,3CTF正好为此发布了一个测试点。 这里我就借用这个话题来解释一下如何使用它。 (由于没有提供重现环境,所以这只能限于“纸上谈兵”,希望大家能明白利用原理。)
** 使用前提: ** 可控; 知道存储格式。
这里的测试问题是多个攻击面的组合。 在问题中,index.php 提示您以管理员身份登录。
0x06 逻辑漏洞
不幸的是,没有环境可以重现这一点。 (官方买断……)这是最近两周出现在unctf的一个网络问题。 这个逻辑缺陷出现在密码重置区域。 流程大致如下。
密码重置过程分为三个步骤。
这里的逻辑漏洞就在于首页的用户名。 猜测是后台有设定。 相似的:
$['名称'] = $_POST['名称'];
用途:重置管理员密码。
这里逻辑漏洞的原因是,填写验证码后,没有记录相关的用户绑定,在最后一步重置密码时,没有检查可靠性,直接执行了该功能。 而且我们都知道它是存储在服务器端的,所以我们可以通过打开另一个页面(保证在同一个文件夹下)来完成单个文件内容的修改。
0x07 摘要
这只是我学习PHP机制相关的一个记录。 提到的点都是我最近在CTF题中接触到的点,但是怎么可能只有这几个利用点呢? 当您遇到它时,让我们进一步了解。 由于篇幅限制,我们不讨论扩展利用,但说白了,扩展利用就是多个复杂知识点的综合。 我认为只有弄清楚原理问题才能理解复杂的组合攻击。 另外,文中如有理解或表述有误的地方,还望各位大师指正。
不要忘记贡献
大家都有不错的技术原创文章
欢迎将您的文章提交至:
和田将根据文章的时效性、新颖性、行文风格、实用性等方面,奖励200元至800元不等的稿费。
如果你有才华,请来贡献吧!
了解更多投稿详情请点击——