mirror of https://gitee.com/karson/fastadmin.git
fix(security): 修复 selectpage 中 FIELD 排序 SQL 注入风险
parent
31088b0758
commit
69b9fdf120
|
|
@ -7,6 +7,7 @@ use think\Config;
|
|||
use think\Controller;
|
||||
use think\Hook;
|
||||
use think\Lang;
|
||||
use think\Db;
|
||||
use think\Loader;
|
||||
use think\Model;
|
||||
use think\Session;
|
||||
|
|
@ -494,6 +495,18 @@ class Backend extends Controller
|
|||
$primarykey = $this->request->request("keyField");
|
||||
//主键值
|
||||
$primaryvalue = $this->request->request("keyValue");
|
||||
// keyValue 与 keyField 必须成对合法,否则退回普通搜索,避免出现 [null => ...] 等异常条件
|
||||
if ($primaryvalue === '') {
|
||||
$primaryvalue = null;
|
||||
}
|
||||
$hasPrimaryInit = false;
|
||||
if ($primaryvalue !== null) {
|
||||
if (is_string($primarykey) && preg_match('/^[a-zA-Z0-9_\-]+$/i', $primarykey) === 1) {
|
||||
$hasPrimaryInit = true;
|
||||
} else {
|
||||
$primaryvalue = null;
|
||||
}
|
||||
}
|
||||
//搜索字段
|
||||
$searchfield = (array)$this->request->request("searchField/a");
|
||||
//自定义搜索条件
|
||||
|
|
@ -511,8 +524,8 @@ class Backend extends Controller
|
|||
}
|
||||
$field = $field ? $field : 'name';
|
||||
|
||||
//如果有primaryvalue,说明当前是初始化传值
|
||||
if ($primaryvalue !== null) {
|
||||
//如果有 primaryvalue 且 keyField 合法,说明当前是初始化传值
|
||||
if ($hasPrimaryInit) {
|
||||
$where = [$primarykey => ['in', $primaryvalue]];
|
||||
$pagesize = 999999;
|
||||
} else {
|
||||
|
|
@ -556,17 +569,26 @@ class Backend extends Controller
|
|||
|
||||
$fields = is_array($this->selectpageFields) ? $this->selectpageFields : ($this->selectpageFields && $this->selectpageFields != '*' ? explode(',', $this->selectpageFields) : []);
|
||||
|
||||
//如果有primaryvalue,说明当前是初始化传值,按照选择顺序排序
|
||||
if ($primaryvalue !== null && preg_match("/^[a-z0-9_\-]+$/i", $primarykey)) {
|
||||
$primaryvalue = array_unique(is_array($primaryvalue) ? $primaryvalue : explode(',', $primaryvalue));
|
||||
//修复自定义data-primary-key为字符串内容时,给排序字段添加上引号
|
||||
$primaryvalue = array_map(function ($value) {
|
||||
return '\'' . $value . '\'';
|
||||
}, $primaryvalue);
|
||||
|
||||
$primaryvalue = implode(',', $primaryvalue);
|
||||
|
||||
$this->model->orderRaw("FIELD(`{$primarykey}`, {$primaryvalue})");
|
||||
// 初始化传值时按 FIELD 顺序排序(值使用 PDO 转义,防止注入)
|
||||
if ($hasPrimaryInit && is_string($primarykey) && preg_match('/^[a-zA-Z0-9_\-]+$/i', $primarykey) === 1) {
|
||||
$primaryValueList = is_array($primaryvalue) ? $primaryvalue : explode(',', (string)$primaryvalue);
|
||||
$primaryValueList = array_values(array_unique(array_filter(
|
||||
$primaryValueList,
|
||||
static function ($v) {
|
||||
return $v !== null && $v !== '';
|
||||
}
|
||||
)));
|
||||
if ($primaryValueList !== []) {
|
||||
$pdo = Db::connect()->getPdo();
|
||||
$quoted = [];
|
||||
foreach ($primaryValueList as $value) {
|
||||
$quoted[] = $pdo->quote((string)$value);
|
||||
}
|
||||
$columnExpr = '`' . str_replace('.', '`.`', $primarykey) . '`';
|
||||
$this->model->orderRaw('FIELD(' . $columnExpr . ', ' . implode(',', $quoted) . ')');
|
||||
} else {
|
||||
$this->model->order($order);
|
||||
}
|
||||
} else {
|
||||
$this->model->order($order);
|
||||
}
|
||||
|
|
@ -592,7 +614,7 @@ class Backend extends Controller
|
|||
}, $result);
|
||||
$list[] = $result;
|
||||
}
|
||||
if ($istree && !$primaryvalue) {
|
||||
if ($istree && !$hasPrimaryInit) {
|
||||
$tree = Tree::instance();
|
||||
$tree->init(collection($list)->toArray(), 'pid');
|
||||
$list = $tree->getTreeList($tree->getTreeArray(0), $field);
|
||||
|
|
|
|||
Loading…
Reference in New Issue