diff --git a/admin/ajax.php b/admin/ajax.php index 70027dc..e5f3e21 100644 --- a/admin/ajax.php +++ b/admin/ajax.php @@ -462,6 +462,10 @@ switch ($_GET['mod']){ if (empty($_POST['mod'])){ die('模块标识不能为空'); } + // P0-06: mod 作为动态列名入 SQL,先校验合法标识符,防列名注入 + if (!wq_is_db_field($_POST['mod'])){ + die('不支持修改的字段'); + } if (empty($_POST['gid'])){ die('等级ID不能为空'); } @@ -476,6 +480,10 @@ switch ($_GET['mod']){ if (empty($_POST['mod'])){ die('模块标识不能为空'); } + // P0-06: mod 作为动态列名入 SQL,先校验合法标识符,防列名注入 + if (!wq_is_db_field($_POST['mod'])){ + die('不支持修改的字段'); + } if (empty($_POST['userid'])){ die('用户ID不能为空'); } @@ -561,6 +569,10 @@ switch ($_GET['mod']){ if (empty($_POST['mod'])){ die('模块标识不能为空'); } + // P0-06: mod 作为动态列名入 SQL,先校验合法标识符,防列名注入 + if (!wq_is_db_field($_POST['mod'])){ + die('不支持修改的字段'); + } if (empty($_POST['fid'])){ die('分类ID不能为空'); } @@ -700,6 +712,10 @@ switch ($_GET['mod']){ if (empty($_POST['mod'])){ die('模块标识不能为空'); } + // P0-06: mod 作为动态列名入 SQL,先校验合法标识符,防列名注入 + if (!wq_is_db_field($_POST['mod'])){ + die('不支持修改的字段'); + } if (empty($_POST['aid'])){ die('代理ID不能为空'); } @@ -807,8 +823,9 @@ switch ($_GET['mod']){ } $time = time(); $money = $_POST['sc_money']; - if ($money <= 0){ - die(json_encode(array('code'=>'-1','msg'=>'卡密金额不能为空或者0或者负数'))); + // P0-06: money 会裸拼进 INSERT SQL 与卡密字符串,强制数字 + if (!is_numeric($money) || $money <= 0){ + die(json_encode(array('code'=>'-1','msg'=>'卡密金额格式错误'))); } $keylist=''; for ($x=1; $x<=$_POST['sc_count']; $x++) { @@ -1471,9 +1488,11 @@ switch ($_GET['mod']){ die(json_encode(array('code'=>'-1','msg'=>'卡密金额不能为空或者0或者负数'))); } $keylist=''; + // P0-06: sc_fid 裸拼进 INSERT SQL,强制整型 + $scfid = (int)$_POST['sc_fid']; for ($x=1; $x<=$_POST['sc_count']; $x++) { $key = substr($time,0,6).'-'.rand_str(6).'-'.rand_str(6).'-'.rand_str(6).'-'.rand_str(6).rand_str(6); - $insarray[] = "'{$key}','{$time}','0','{$_POST['sc_fid']}','1'"; + $insarray[] = "'{$key}','{$time}','0','$scfid','1'"; $keylist .= '
'.$key; } $sign = rand_str(32); @@ -1552,7 +1571,8 @@ switch ($_GET['mod']){ die('成功删除'.(int)$db->affected_num().'行'); break; case 'DelUse': - $db->delete('sq_fidkey', '`usetime` > 0 AND `fid` = '.$_POST['fid'].' AND `status` = 1','AND'); + // P0-06: fid 裸拼进 DELETE SQL,强制整型 + $db->delete('sq_fidkey', '`usetime` > 0 AND `fid` = '.(int)$_POST['fid'].' AND `status` = 1','AND'); die('成功删除'.(int)$db->affected_num().'行'); break; } diff --git a/agent/ajax.php b/agent/ajax.php index 7af053a..cf61914 100644 --- a/agent/ajax.php +++ b/agent/ajax.php @@ -1044,9 +1044,11 @@ switch ($_GET['mod']) { } $keylist=''; + // P0-06: sc_fid 裸拼进 INSERT SQL,强制整型(上方 fidinfo 校验保证 fid 有效) + $scfid = (int)$_POST['sc_fid']; for ($x=1; $x<=$_POST['sc_count']; $x++) { $key = substr($time,0,6).'-'.rand_str(6).'-'.rand_str(6).'-'.rand_str(6).'-'.rand_str(6).rand_str(6); - $insarray[] = "'{$key}','{$time}','0','{$_POST['sc_fid']}','1','{$_SESSION['agent_id']}'"; + $insarray[] = "'{$key}','{$time}','0','$scfid','1','{$_SESSION['agent_id']}'"; $keylist .= '
'.$key; } $sign = rand_str(32); @@ -1126,8 +1128,9 @@ switch ($_GET['mod']) { } $time = time(); $money = $_POST['sc_money']; - if ($money <= 0){ - die(json_encode(array('code'=>'-1','msg'=>'卡密金额不能为空或者0或者负数'))); + // P0-06: money 会裸拼进 INSERT SQL 与卡密字符串,强制数字 + if (!is_numeric($money) || $money <= 0){ + die(json_encode(array('code'=>'-1','msg'=>'卡密金额格式错误'))); } $spendmoney = $money * $count; if (!$agentinfo = $db->select_first_row('sq_agent', '*', array('username' => $_SESSION['agent_username']), 'AND')) { @@ -1182,7 +1185,8 @@ switch ($_GET['mod']) { die('成功删除'.(int)$db->affected_num().'行'); break; case 'DelUse': - $db->delete('sq_fidkey', '`usetime` > 0 AND `fid` = '.$_POST['fid'].' AND `aid` = '.$_SESSION['agent_id'].' AND `status` = 1','AND'); + // P0-06: fid 裸拼进 DELETE SQL,强制整型 + $db->delete('sq_fidkey', '`usetime` > 0 AND `fid` = '.(int)$_POST['fid'].' AND `aid` = '.(int)$_SESSION['agent_id'].' AND `status` = 1','AND'); die('成功删除'.(int)$db->affected_num().'行'); break; case 'DelAll': diff --git a/function/function_core.php b/function/function_core.php index 550adf9..9b039c2 100644 --- a/function/function_core.php +++ b/function/function_core.php @@ -251,6 +251,15 @@ function wq_verify_password($plain, $stored, $legacy = 'plain') return hash_equals($stored, $plain); } +/** + * P0-06: 校验动态字段标识(mod)是否为合法 SQL 列名,防列名注入 + * 动态 UPDATE/INSERT 的键来自用户输入时,须先通过本校验 + */ +function wq_is_db_field($name) +{ + return is_string($name) && preg_match('/^[A-Za-z0-9_]{1,64}$/', $name) === 1; +} + /* * 布尔逻辑型转换为数字0或1