Laravel 的路由参数被注入 HTML 代码,页面展示恶意外链?以 Dcat Admin 为例看我是如何解决!

背景

  • 最近上线的项目比较多,而且上线前必须经过几轮漏扫才能符合要求。
  • 好难受,这次还是被攻击了,辛辛苦苦做一个项目,却总会被认定为 易受攻击对象 :facepunch:
  • 没办法,做项目和做工程一样,安全第一☝,生产第二!!!
  • 话不多说,扶我起来,我还能再坚持一下:joy:

问题描述

1. 问题还原

  • 通过修改路由参数值,就可以注入,你想注入的任何内容。
  • 小试牛刀 - 将路由参数的值变为 1',页面居然能正常展示,如 事发现场一 所示。
  • 大刀阔斧 - 将路由参数的值变为长的 HTML事发现场二 所示:
    http://xxxxx.test/admin/merchants/1'11%22%3E%3Ca%20href=https:%5c%5cwww.baidu.com%3E%E8%B7%B3%E8%BD%AC%E5%88%B0%E4%B8%BB%E9%A1%B5%3Cp%3Ehttp:%5c%5coca-to-guoquan-delivery.test%3Cinput%20%20hidden='true'%20/edit

2. 事发现场一:

将路由参数的值变为 1',页面居然能正常展示:
Laravel 的路由参数被注入 HTML 代码,页面展示恶意外链? 以 Dcat Admin 为例看我是如何解决

3. 事发现场二:

页面被注入了 HTML 代码,并且可以展示恶意外链:
Laravel 的路由参数被注入 HTML 代码,页面展示恶意外链?以 Dcat Admin 为例看我是如何解决!

如何解决呢?

  • 既然被注入了一些 奇奇怪怪 的内容,那我们就应该想办法把它给屏蔽掉。正所谓取其精华,去其糟粕。
  • Laravel 有一个路由参数的 正则表达式约束 功能,可以限制路由参数值的格式。芜湖~,此乃正解!!!

具体方式

  • 正则表达式约束 看官方文档示例:
    Route::get('/user/{name}', function (string $name) {
      // ...
    })->where('name', '[A-Za-z]+');
    Route::get('/user/{id}', function (string $id) {
      // ...
    })->where('id', '[0-9]+');
    Route::get('/user/{id}/{name}', function (string $id, string $name) {
      // ...
    })->where(['id' => '[0-9]+', 'name' => '[a-z]+']);
  • 这里有一个问题,官方文档上描述的都是,关于单路由的 - 路由参数的正则限定。可我的代码里面 resources 资源路由居多,这我该怎么办?
  • 哎呀,不行,头有点痒,要长脑子了。 批量全局 等词汇浮现在脑海,我悟了…
  • 全局设置一下,参数名称限制 全局约束

    你应该在 App\Providers\RouteServiceProvider 类的 boot 方法中定义这些模式:

    /**
    * 定义路由模型绑定、模式筛选器等。
    */
    public function boot(): void
    {
         Route::pattern('id', '[0-9]+');
    }
  • 一通操作后,我发现不行。好像这个不管作用,事发现场一事发现场二 照样没有得到改善。
  • Dcat Admin 的路由文件是 app/Admin/routes.php 路径下的,而不是 routes/xxx.php 的。会不会是因为这个原因导致的。
  • 于是乎我在 app/Admin/routes.php 文件中增加关键代码:
    // ####---- 商户管理 - 商户列表
    // 为什么是 pattern 的第一个参数是: merchant,可以通过命令行  php artisan route:list 查看
    Route::pattern('merchant', '[0-9]+');    // 关键代码
    $router->resource('merchants', Merchant\MerchantController::class);
  • 最终 事发现场一事发现场二 得到妥善解决。Nice :heart: !!

总结

  • HTML 注入路由参数中,可以通过 Laravel 自带的 正则表达式约束 进行约束。
  • 如果路由多为 resources 资源路由,可以通过 全局约束 来约束,无需拆分资源路由。
  • 如果全局约束不可以,可将 关键代码 放置到对应的路由文件中。
  • 一般项目 resources 资源路由会很多,所以要批量维护,添加多条即可。

疑问

  • 为什么在 App\Providers\RouteServiceProvider 类的 boot 方法添加关键方法,对在 app/Admin/routes.php 路由不行呢?
    /**
    * 定义路由模型绑定、模式筛选器等。
    */
    public function boot(): void
    {
         Route::pattern('id', '[0-9]+');
    }
  • 有知道的朋友,可以在评论区讨论。谢谢!!!
本作品采用《CC 协议》,转载必须注明作者和本文链接
Xiao Peng
laravel_peng
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 6

页面上只展示经过 Controller 处理过的数据,即时是 id 也是处理过滤过重新再给 view,不要直接在界面上展示用户输入的数据

9个月前 评论
laravel_peng (楼主) 9个月前
ModStart (作者) 9个月前

在 RouteServiceProvider 添加不起作用是因为这里的加载在dcat加载之后吧,所以看起来没效果

9个月前 评论
laravel_peng (楼主) 9个月前
deatil (作者) 9个月前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!
技术员 @ 修炼的漱石
文章
10
粉丝
15
喜欢
93
收藏
171
排名:663
访问:1.1 万
私信
所有博文
社区赞助商