基于yii框架的系统审计
字数 1830 2025-08-06 08:34:57
YII框架安全审计与漏洞挖掘实战指南
1. YII框架基础
1.1 控制器基础
在YII框架中,控制器是MVC架构的核心组件之一:
- 网页应用控制器:继承自
yii\web\Controller或其子类 - 控制台应用控制器:继承自
yii\console\Controller或其子类
示例控制器定义:
namespace app\controllers;
use yii\web\Controller;
class SiteController extends Controller {}
1.2 控制器ID规范
控制器ID需遵循特定命名规则:
- 允许字符:英文小写字母、数字、下划线、中横杠和正斜杠
- 有效示例:
article,post-comment - 无效示例:
article?,PostComment,admin\post
1.3 控制器类命名规则
控制器类名生成规则:
- 将正斜杠分隔的每个单词首字母大写(仅最后一个正斜杠后的部分)
- 去掉中横杠,正斜杠替换为反斜杠
- 添加
Controller后缀 - 前面添加控制器命名空间
命名示例(假设命名空间为app\controllers):
article→app\controllers\ArticleControllerpost-comment→app\controllers\PostCommentControlleradmin/post-comment→app\controllers\admin\PostCommentController
2. 路由系统分析
2.1 标准路由格式
- 基本格式:
ControllerID/ActionID - 模块下控制器:
ModuleID/ControllerID/ActionID
示例:http://hostname/index.php?r=site/index 执行site控制器的index操作
2.2 自定义路由实现
审计案例中发现了自定义路由实现,关键代码如下:
public function runAction($route, $params = []) {
$route = ltrim($route, '/');
$pattern = '/^plugin\/.*/';
preg_match($pattern, $route, $matches);
if ($matches) {
// 处理插件路由逻辑
$originRouteArray = mb_split('/', $route);
$pluginId = $originRouteArray[1] ?? null;
// 构建控制器类名
$controllerClass = "app\\plugins\\{$pluginId}\\controllers\\IndexController";
// 创建控制器实例并运行动作
$controller = \Yii::createObject($controllerClass, [$controllerId, $this]);
return $controller->runAction($actionId, $params);
}
return parent::runAction($route, $params);
}
路由解析示例:
index.php?r=plugin/booking/api/index/index →
web/app/plugins/booking/controllers/api/IndexController.php::actionIndex()
3. 高效审计方法论
3.1 自动化审计流程
-
收集所有控制器文件:
- Linux/Mac:
tree -f -i | grep "Controller.php" > url.txt - Windows:
tree /f /a | findstr /i "Controller.php" > url.txt
- Linux/Mac:
-
Python脚本自动化分析:
import os
import re
def getFileNamePath(path):
# 递归查找所有Controller.php文件
pass
def getUri():
# 提取action方法并构建完整URL
pattern = r"public function action(\w+)"
# 处理路径和构建完整路由
pass
3.2 路由特征分析
关键特征:
- URL路径与文件系统路径对应关系
- 控制器文件名需转换为小写
- 多单词组合使用"-"连接
- 方法名去除"action"前缀
示例转换:
/web/app/Api/Controllers/v1/UserController.php::actionGetUser() →
index.php?r=admin/api/v1/user/get-user
4. 漏洞挖掘实战
4.1 SQL注入漏洞案例
漏洞位置:BookingController.php中的actionStoreList方法
漏洞成因:
- 直接拼接SQL查询中的
longitude和latitude参数 - 未对用户输入进行充分过滤
关键代码:
$store = BookingStore::find()
->select([
'*',
"(st_distance(point(longitude, latitude), point($this->longitude, $this->latitude)) * 111195) as distance"
])
->keyword($this->keyword, ['like', 's.name', $this->keyword])
->all();
安全对比:
select()中的参数直接拼接 → 存在SQL注入andWhere()使用参数绑定 → 安全
4.2 漏洞利用方法
-
验证漏洞存在:
- 测试单引号:
longitude=1'→ 观察是否报错
- 测试单引号:
-
构造注入payload:
longitude=1&latitude=1) OR 1=1 -- -
利用报错注入:
longitude=1' AND (SELECT 1 FROM(SELECT COUNT(*),CONCAT((SELECT version()),0x3a,FLOOR(RAND(0)*2))x FROM information_schema.tables GROUP BY x)a) AND '1'='1
5. 防御措施
5.1 安全编码实践
-
始终使用参数化查询:
->select(new Expression("st_distance(point(longitude, latitude), point(:lon, :lat)) * 111195 as distance", [ ':lon' => $this->longitude, ':lat' => $this->latitude ])) -
严格输入验证:
public function rules() { return [ [['longitude', 'latitude'], 'number'], [['longitude', 'latitude'], 'match', 'pattern' => '/^[\d\.]+$/'] ]; }
5.2 框架安全配置
- 启用YII的安全组件
- 配置CSRF保护
- 实现RBAC权限控制
- 日志记录所有敏感操作
6. 审计检查清单
- [ ] 检查所有直接拼接SQL的地方
- [ ] 验证所有用户输入是否经过适当过滤
- [ ] 检查路由配置是否存在未授权访问
- [ ] 确认敏感操作是否有权限控制
- [ ] 检查文件上传功能的安全性
- [ ] 验证XSS防护措施是否到位
通过系统化的审计方法和工具辅助,可以高效发现YII框架应用中的安全漏洞,特别是当面对大型代码库时,自动化工具和脚本能显著提高审计效率。