当前位置: 首页 > news >正文

渗透艺术系列之Laravel框架(一)

今天,我们来尝试探索并渗透一款比较知名的PHP框架,它的名字是 Laravel !

本文章仅提供学习,切勿将其用于不法手段!

想要有效防御,必须先要做到有效攻击!有授权的攻击,远比无授权的攻击,要安全得多!

任何软件,任何框架,都是存在漏洞的,Laravel 框架,也不会例外!

那么,就让我们进入 Laravel 的 世界 ,去探索存在于 Laravel 框架内部的 Bug 吧 !

或许,这很像是在玩一场游戏!那么,网络安全爱好者们,让我们一起来尽情狂欢吧!

首先,让我们进入 Laravel 框架 源码 根目录 下 的 public 目录,让我们找到 index.php !

为什么要找到它呢?它是 Laravel 框架 的 执行入口 !

作为一名白帽黑客,作为一名漏洞挖掘者,我们必须从细节入手,从根源开始寻找 它 可能存在的问题 !

首先,我们进入 index.php 的 源码空间 !

我们发现了,下面的代码:

if(file_exists($maintenance = __DIR__ .'/../storage/framework/maintenance.php')){

        require $maintenance;

}

通过分析这段代码,我们可以知道它的用途!

如果 $maintenance 对应的源码文件存在,那么就载入并执行它!

这里,我们可以进行一个假设!

如果 maintenance.php 这个文件的内容,不幸被污染,那么当 Laravel 框架被执行时,是不是意味着 maintenance.php 这个文件,可能会做出一些超乎控制的事情呢?!

更好的做法,是在检测到 maintenance.php 文件存在时,对比一下 它 的  sha1 或者 md5 值,从而判断,它的原始文件内容,是否已被修改(当发现文件内容已被篡改时,应紧急停止程序执行,并做好安全日志记录)!当然,这需要事先计算并保存好原始文件的 sha1 或者 md5 值!这里,可能会使用到 sha1_file 或者 md5_file 函数 !有的童鞋儿会说,sha1_file 和 md5_file 函数,并不太安全,可能被 碰撞攻击 突破!但是,我们不得不承认 它们的 计算速度很快,生成哈希值相对容易,非常适合快速校验!如果在  程序入口 消耗太多校验资源与时间,是并不明智的!虽然 sha256 算法(可以使用 hash_file("sha256",$file)),更加的安全,更加的难以被实施碰撞与逆向攻击,但是对应的,sha256算法 的 计算开销,要比 sha1 和 md5 算法 要大得多!综合分析,在程序执行的入口(可能会面临海量并发的情况,进行 sha256 校验 ,并不比进行 sha1 或 md5 校验 更加合适!

我们继续分析,接下来的一些可以被利用的点,当然,前提是,你可以通过某种方式(例如,文件上传、文件下载、文件修改等)去修改目标文件的内容!

require __DIR__ . '/../vendor/autoload.php';

$app = require_once __DIR__ . '/../bootstrap/app.php';

这两句代码,都存在文件包含漏洞 !当然,前提是,你能够去替换或修改这些文件中的内容!

$app->handleRequest(Request::capture());

让我们来分析上面这句代码!

上面的这句代码,由两部分组成,分别为 $app->handleRequest() 和 Request::capture() 。

鉴于程序代码执行的原则,让我们先来分析 Request::capture() 这个类静态方法的细节实现!

在 Request::capture() 这个类静态方法 中,调用了两个方法!

分别为 static::enableHttpMethodParameterOverride() 和 static::createFromBase(SymfonyRequest::createFromGlobals()) !

我们追踪 static::enableHttpMethodParameterOverride() 方法 的 定义,我们发现,它的作用是 self::$httpMethodParameterOverride 的值 置为 真 true  !

根据代码追踪,我们已知,self 对应的 类 为 http-foundation/Request.php 文件中的 Request 类 !

而 Request 类的 静态成员属性 $httpMethodParameterOverride 的初始值 为 假 False 。

接下来,我们要做什么?我们要分析这个属性的用途!

如果我们没有说明文档,我们怎么去分析呢(并非所有源码,都会提供给我们足够的说明文件或者官方手册,以供参考,我更多分享给大家的,是一种漏洞挖掘的思维!通过代码审计的方式,去挖掘软件源码中可能存在的安全漏洞)?

假设,我们并没有 Laravel 这款框架的官方手册 或者 说明文件!

那么,我们怎么去分析 $httpMethodParameterOverride 这个类静态成员属性的用途呢?

所以,我们先看一下它的类名称,程序员们,往往会存在一个习惯,就是根据它的用途,去定义它的名称!而作为白帽黑客,这恰恰是我们感兴趣的点 ^_^ ,想要挖掘漏洞,我们必须理解它的内部原理以及实现机制!

我们来翻译一下,一些有价值的信息!

namespace Symfony\Component\HttpFoundation;

这句话,定义了一个命名空间!

通过大数据搜索,我们得知 Symfony\Component\HttpFoundation 是 Symfony 框架的核心组件之一,重点来了!Symfony\Component\HttpFoundation 是专门用于处理 HTTP 请求和响应的 !

Request 类,封装了 $_GET、$_POST、$_COOKIE、$_SERVER 等超全局变量,并提供了 链式方法 来访问请求数据!

什么是链式方法呢?

大家可以理解为 ,链式方法 通过 返回对象自身(this)来实现连续调用!

例如,db->from([['table1','t1'],['table2','t2']])->select(['t1','id'],['t2','parent_id'])->where([['t1','id','in',[1,2,3,4,5]],'and',['t2','parent_id',’eq',0]]);

通过封装处理,Request 类 成为了 Request 类中所有类方法调用者 与 $_GET、$_POST、$_COOKIE、$_SERVER 等这些超全局变量之间的一座桥梁!

在 Request::capture() 方法 中,我们发现了 

static::createFromBase(SymfonyRequest::createFromGlobals());

因此,我们先去追踪  SymfonyRequest::createFromGlobals(),在 这个方法中,我们发现了有趣的地方 ,例如 

$request = self::createRequestFromFactory($_GET, $_POST, [], $_COOKIE, $_FILES, $_SERVER);

我们发现,并没有传入 $_REQUEST 这个超全局变量!那么 $_REQUEST 是否可以在渗透时,加以利用呢?但是 self::createRequestFromFactory 传递了 $_GET 和 $_POST ,也就是说,利用 $_REQUEST 可能需要采用一些特殊手段,例如 变量覆盖? 或者 数组内容 新增 或 删除?这方面,有待后续深入研究。

在  self::createRequestFromFactory 这个方法中,我们发现了 

if (self::$requestFactory) {$request = (self::$requestFactory)($query, $request, $attributes, $cookies, $files, $server, $content);if (!$request instanceof self) {throw new \LogicException('The Request factory must return an instance of Symfony\Component\HttpFoundation\Request.');}return $request;
}

self::$requestFactory 有点类似于 C语言中的函数指针,这里使用了间接引用的方式,来执行相应的方法过程!

下面我们来研究一下,请求工厂模式!

class RequestBuilder {protected static ?\Closure $requestFactory = null;public static function setFactory(\Closure $factory): void {self::$requestFactory = $factory;}public static function createRequest(array $data): Request {return self::$requestFactory ? self::$requestFactory($data) : new Request($data);}
}// 使用示例
RequestBuilder::setFactory(fn($data) => new JsonRequest($data));
$request = RequestBuilder::createRequest(['key' => 'value']);

我们定义了一个类静态成员属性(它有点类似于一个函数指针,因为它的类型为 

?\Closure !Closure 是 闭包的意思,这里涉及到了 闭包 的概念! \Closure 是 PHP 内置的闭包类型(匿名函数),支持捕获外部变量并动态执行!?符号代表 要么 为 null 空,要么为 一个 具体类型!

?\Closure ,代表 要么 是 null 空,要么 是 \Closure 闭包类型!闭包类型,是什么?是匿名函数!

?\Closure 表示变量可以是闭包对象,也可以是 null,常用于需要动态绑定逻辑的场景。

闭包类型,这个东西,是在 PHP7以后出现的,所以,我们要去研究它!因为 Larvael 框架中 大量使用了 这种新出现的东西!

闭包,是伪装成函数的对象!至少,在PHP语言中,是这个样子的!

特性匿名函数闭包
定义无名称的函数表达式匿名函数 + 捕获外部作用域变量
变量访问默认无法访问外部变量通过 use 关键字显式捕获外部变量
类型普通函数类型Closure 类的实例
生命周期执行完毕后立即销毁可能因变量引用而延长生命周期

让我们看一下,上面的表格,我们会发现,闭包 是 匿名函数 + 可捕获外部作用域变量 特性 的 新生产物!它的两个特点:一是 匿名函数,二是 可捕获外部作用域变量 !

匿名函数,默认是无法访问外部变量的(这里涉及到了 局部变量 和 全局变量 的概念,外部变量,指的是 在 匿名函数外部 定义的变量!

闭包,可以通过 use 关键字来访问外部变量!

匿名函数,是普通的函数类型,而 闭包 则是 Closure 类的实例对象!

让我们看一下 Closure 类的定义!

它的定义,在 Core_c.php 文件中,下面是这个类定义的内容!

final class Closure
{/*** This method exists only to disallow instantiation of the Closure class.* Objects of this class are created in the fashion described on the anonymous functions page.* @link https://secure.php.net/manual/en/closure.construct.php*/private function __construct() {}/*** This is for consistency with other classes that implement calling magic,* as this method is not used for calling the function.* @param mixed ...$_ [optional]* @return mixed* @link https://secure.php.net/manual/en/class.closure.php*/public function __invoke(...$_) {}/*** Duplicates the closure with a new bound object and class scope* @link https://secure.php.net/manual/en/closure.bindto.php* @param object|null $newThis The object to which the given anonymous function should be bound, or NULL for the closure to be unbound.* @param object|class-string|null $newScope The class scope to which associate the closure is to be associated, or 'static' to keep the current one.* If an object is given, the type of the object will be used instead.* This determines the visibility of protected and private methods of the bound object.* @return Closure|null Returns the newly created Closure object or null on failure*/#[Pure]public function bindTo(?object $newThis, object|string|null $newScope = 'static'): ?Closure {}/*** This method is a static version of Closure::bindTo().* See the documentation of that method for more information.* @link https://secure.php.net/manual/en/closure.bind.php* @param Closure $closure The anonymous functions to bind.* @param object|null $newThis The object to which the given anonymous function should be bound, or NULL for the closure to be unbound.* @param object|class-string|null $newScope The class scope to which associate the closure is to be associated, or 'static' to keep the current one.* If an object is given, the type of the object will be used instead.* This determines the visibility of protected and private methods of the bound object.* @return Closure|null Returns the newly created Closure object or null on failure*/#[Pure]public static function bind(Closure $closure, ?object $newThis, object|string|null $newScope = 'static'): ?Closure {}/*** Temporarily binds the closure to newthis, and calls it with any given parameters.* @link https://php.net/manual/en/closure.call.php* @param object $newThis The object to bind the closure to for the duration of the call.* @param mixed $args [optional] Zero or more parameters, which will be given as parameters to the closure.* @return mixed* @since 7.0*/public function call(object $newThis, mixed ...$args): mixed {}/*** @param callable $callback* @return Closure* @since 7.1*/public static function fromCallable(callable $callback): Closure {}
}

Closure 类,是最终(final)的,这意味着,它不能够被子类集成,也就是说, Closure 类 不会存在子类!

(未完待续)

http://www.dtcms.com/a/300316.html

相关文章:

  • Effective C++ 条款03:尽可能使用const
  • 检验类设备中,交叉导轨如何确保加样精度?
  • mysql-数据表-DDL语句
  • Triton源代码分析 - 目录
  • freeRTOS 静态创建任务
  • TIM 输入捕获
  • pip, github 突然连不上?报错和解决方法如下
  • 【硬件-笔试面试题】硬件/电子工程师,笔试面试题-29,(知识点:非易失存储器)
  • 【AI周报】2025年7月26日
  • CUDA杂记--FP16与FP32用途
  • MoE替代LLM
  • linux内核电源管理
  • 面试150 加一
  • 一文速通《多元函数微分学》
  • C++11 右值引用 Lambda 表达式
  • AutoDL 数据盘清理指南:彻底删除 .Trash-0 内文件释放空间
  • 电脑负载监控接入了IOT物联网平台
  • 深入浅出 MyBatis-Plus Wrapper:让条件构造更简单高效
  • 定义域第一题
  • iview: 对输入框进行Poptip 换行提示
  • python---元组解包(Tuple Unpacking)
  • 银行营销数据预测分析:从数据到精准营销决策
  • 表征工程 中怎么 调整参数或比例
  • 【RHCSA 问答题】第 13 章 访问 Linux 文件系统
  • 水下目标识别准确率↑89%!陌讯多模态融合算法在智慧水务的落地实践
  • ArkData-关系型数据库
  • 测试分类
  • Swagger 配置及使用指南
  • Redis C++客户端——通用命令
  • 多模态大模型与 AI 落地:从技术原理到实践路径的深度解析