PHP通过表单提交多条SQL时报服务器资源访问被拒绝,单条SQL可正常执行
问题原因
- 服务器端部署的Web应用防火墙(WAF,常见如mod_security)识别到你提交的内容包含多句SQL语句,判定为SQL注入攻击尝试,直接拦截请求返回
Access to this resource on the server is denied错误。 - 代码逻辑存在缺陷:
- 使用
explode(";", $sql)拆分语句后,没有过滤空值,多句SQL末尾的分号会拆分出空字符串,空语句执行会报错,导致最终执行结果判定为失败 - 重复实例化数据库连接、循环中反复开关连接,存在不必要的资源浪费
- 没有使用事务控制,只要有一条语句执行失败,前面已执行成功的语句不会回滚,会导致数据不一致
- 使用
解决方案
第一步:绕开WAF拦截
对提交的SQL内容做base64编码后再提交,避免被WAF识别为SQL注入攻击,前端代码修改如下:
<form action="" method="post"> <textarea name="sorgularMesai" id="sorgularMesai" cols="30" rows="10"></textarea> <br> <input type="hidden" name="sorgularMesai_base64" id="sorgularMesai_base64"> <input type="submit" value="gonder" id="gonder" onclick="document.getElementById('sorgularMesai_base64').value = btoa(document.getElementById('sorgularMesai').value)" /> </form>
第二步:修复后端代码逻辑
修复后的PHP代码如下:
function GenelMesaiAyarla( $sorgular_mesai_sql ) { $yol = $_SESSION[ 'kok_dizin' ] . "DatabaseOperations/ConnectionOperations.php"; require_once( $yol ); $connect = new Connection(); $connect->BaglantiyiAc(); // 开启事务,保证所有语句要么全部执行成功,要么全部回滚 $connect->connectionKey->begin_transaction(); $mesaiGuncellemeDurum = true; // 拆分SQL,过滤空语句和空白内容 $bolunmus_mesai_sql = explode( ";", $sorgular_mesai_sql ); foreach ($bolunmus_mesai_sql as $index => $singleSql) { $singleSql = trim($singleSql); if (empty($singleSql)) { continue; } $queryResult = $connect->connectionKey->query($singleSql); if (!$queryResult) { // 执行失败回滚所有操作 $connect->connectionKey->rollback(); $mesaiGuncellemeDurum = false; break; } echo $index.":".$singleSql."<br>"; } if ($mesaiGuncellemeDurum) { $connect->connectionKey->commit(); } $connect->BaglantiyiKapat(); return $mesaiGuncellemeDurum; } if ($_POST) { // 解码前端提交的base64编码的SQL内容 $sorgular_mesai = base64_decode($_POST["sorgularMesai_base64"]); $genel_mesai_durum = GenelMesaiAyarla($sorgular_mesai); if ($genel_mesai_durum) { echo "Mesai güncellendi"; } else { echo "Mesai Durumu ayarlarken bir sorun oluştuğu için,tüm işlemler durduruldu!"; } }
安全提示
直接接收用户输入的原生SQL执行是极高风险的操作,极易被攻击者利用窃取、篡改、删除数据库数据。如果不是必要场景,建议改成让用户选择业务参数,后端拼接生成SQL执行,不要直接接收原生SQL。如果必须使用该方案,要严格限制数据库账号的权限,仅开放指定表的update权限,禁止所有其他权限。
内容的提问来源于stack exchange,提问作者Emrah Çalışkan
相关产品推荐
相关产品推荐

