Web应用安全

PHP文件包含漏洞

文件包含概念

什么是文件包含?

  • 在各种开发语言中都提供了内置的文件包含函数,可以使得开发人员在一个代码文件中直接包含(引入)另外一个代码文件
  • 由于文件包含可以达到复用和方便修改的目的,在代码设计中常常使用
  • 大多数情况下,文件包含函数中包含的代码文件是固定的

文件包含漏洞

什么是文件包含漏洞?

  • 如果文件包含的代码文件被设计为一个变量,且这个变量可以由前端用户设置,这种情况下,如果没有做足够的安全过滤设置,则可能会引发文件包含漏洞
  • 攻击者可以设置一个“意想不到”的文件让包含函数去执行,从而造成恶意操作

文件包含漏洞分类

根据不同的配置环境,文件包含漏洞分为如下两种情况

  • 本地文件包含漏洞
  • 远程文件包含漏洞

本地文件包含漏洞

  • 仅能够对服务器本地的文件进行包含,该情况下,攻击者更多的会包含一些固定的系统配置文件,从而读取系统敏感信息
  • 本地文件包含漏洞会结合一些特殊的文件上传漏洞,从而形成更大的威力

远程文件包含漏洞

  • 能够通过url地址对远程的文件进行包含,这意味着攻击者可以传入任意的代码
  • 在web系统的功能设计上尽量不要让前端用户直接传变量给包含函数,即使必须这么做,也一定要做严格的白名单策略进行过滤

文件包含漏洞函数

在PHP常见的文件包含的函数

  • include(),include_once()
  • require(),require_once()

区别:

  • include 引入文件错误,会给出提示,并继续运行剩余的代码
  • require 引入文件错误,也会给出提示,但是停止程序的运行
  • once表示重复包含时,只加载一次

文件包含漏洞靶场

Pikachu是一个带有漏洞的Web应用系统

14.4.1

本地文件包含漏洞实例

按照图示步骤,选择一个选项,关注地址栏中filename的值

14.4.2

可以通过修改url中filename的方式,加载其它文件

  • 在include目录下,创建1.txt文件

14.4.3

  • 通过修改地址栏中的url访问本地1.txt文件

14.4.4

远程文件包含漏洞实例

按照图示步骤,同样关注地址中url的filename的值

14.4.5

需要在php.ini中开启allow_url include 选项

14.4.6

在其它的网站中创建一个文件1.txt,修改filename的值为远程文件地址

14.4.7

文件包含漏洞防范措施

尽量不要将文件包含函数对应的文件放交前端进行选择和操作

  • 过滤各种.././,http://,https://
  • 配置php.ini配置文件
    • allow_url_fopen= off
    • allow_url_include= off
    • magic_quotes_gpc= on
  • 通过白名单策略,仅允许包含运行指定的文件

反序列化漏洞

序列化/反序列化概念

序列化

  • 维基百科中这样定义:序列化(serialization)在计算机科学的数据处理中,是指将数据结构或对象状态转换成可取用格式(例如存成文件,存于缓冲,或经由网络中发送)以留待后续在相同或另一台计算机环境中,能恢复原先状态的过程。

  • 类似于物流快递对物品的处理过程。拆解打包 => 运输 => 拆包组装

  • 在面向对象编程语言中,就是将对象转化为字节流,字节流中包括这个对象的数据和信息,便于传输和存储。需要时,通过反序列化从字节流中恢复对象

14.4.8

反序列化漏洞

漏洞成因

  • 序列化和反序列化本身并不存在问题。但当输入的反序列化的数据可被用户控制,那么攻击者即可通过构造恶意输入,让反序列化产生非预期的对象,在此过程中执行构造的任意代码

PHP序列化和反序列化实例

PHP实现序列化

1
2
3
4
5
6
7
8
9
10
11
12
<?php
// 定义类
class person{
public $name = "pikachu";
}
// 使用类创建对象
$person1 = new Person();
// 把这个对象进行序列化,并输出
$data = serialize($person1);
echo $data;
echo "<br>";
?>

序列化执行结果

1
O:6:"Person":1:{s:4:"name";s:7:"pikachu";}
组成部分 含义 组成部分 含义
O 变量类型为Object(对象) “name” 属性的名称
6 类名称的长度 s 属性值的类型为String(字符串)
“Person” 类名称 7 属性值的长度
1 属性数量 “pikachu” 属性值
s 属性的数据类型为String(字符串)
4 属性的名称长度

PHP实现反序列化

1
2
3
// 反序列化
$obj = unserialize($data);
echo $obj -> name

PHP反序列化相关函数

常见魔法函数

  • 一般两个下划线开头的函数都是魔术方法,所谓魔术无非就是会自动调用而已
  • __construct()当一个对象创建时被调用
  • __destruct()当一个对象销毁时被调用
  • __toString()当一个对象被当作一个字符串使用被调用
  • __sleep()在对象在被序列化之前被调用
  • __wakeup()在反序列化之后立刻被调用

PHP反序列化漏洞实例

反序列化漏洞案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
// 定义类
class Person{
public $name = "pikachu";
function __destruct(){
echo $this -> name;
}
}

$payload = 'O:6:"Person":1:{s:4:"name";s:29:"<script>alert("xss")</script>";}';
// $payload的值可以来自于用户在地址栏的输入
// $data=$_GET['name']
$unser = unserialize($payload);
?>

执行结果

14.4.9