服务端字符过滤 与 SQL PDO防注入

注入示例

复制代码
# step 1 SQL
SELECT * FROM users WHERE username = 'admin' AND password = 'e10adc3949ba59abbe56e057f20f883e'
# step 2 SQL
SELECT * FROM users WHERE username = 'admin'#' AND password = '96e79218965eb72c92a549dd5a330112'

关键点是这2个SQL的区别.其中第二步由于前台传入特殊字符单引号(')及#,在数据库中#为语句注释部分,则后续SQL语句不会被执行,可直接跳过我们的密码验证逻辑。

username还可以是 'admin' OR 1='1 跳过验证

1. PHP端防注入

++1.1 字符型过滤++

复制代码
/*discuz过滤函数*/
function inject_check($sql_str)  
{  
	return preg_match('/^select|insert|and|or|create|update|delete|alter|count|\'|\/\*|\*|\.\.\/|\.\/|union|into|load_file|outfile/i', $sql_str); // 进行过滤  
} 

$data[] = $_GET['username'];
$data[] = $_GET['passwd'];
function inject_checks($data) {
    foreach($data as $key => $val){
        if(preg_match('/^select|insert|and|or|create|update|delete|alter|count|\'|\/\*|\*|\.\.\/|\.\/|union|into|load_file|outfile/i', $val)){
            return true;
        }
    }
    
    return false;
}

上面是discuz过滤字符型注入的函数 ,返回检测结果,1 or 0

1就是存在特殊字符

示例:

复制代码
if(inject_check($str)){
    exit('非法字符!');
}

foreach($_POST as $key => $value){
    if(inject_check($value)){
        echo '非法字符';
        exit();
    }
}

这种要求比较严格的过滤,一般应用在注册和登陆环节

++1.2 数字型的过滤++

复制代码
$id = intval($_GET['id']);

数字型的就比较简单了。只需要转换一下

++1.3 富文本的过滤++

复制代码
$html = "<a href='test'>Test</a>";
$html = addslashes($html);

输出:

<a href=\'test\'>Test</a>

需要显示的时候再用 stripslashes 处理

复制代码

++1.4 统一转义++

复制代码
if (!get_magic_quotes_gpc())
{
    if (!empty($_GET))
    {
        $_GET  = addslashes_deep($_GET);
    }
    if (!empty($_POST))
    {
        $_POST = addslashes_deep($_POST);
    }

    $_COOKIE   = addslashes_deep($_COOKIE);
    $_REQUEST  = addslashes_deep($_REQUEST);
}

function addslashes_deep($value)
{
    if (empty($value))
    {
        return $value;
    }
    else
    {
        return is_array($value) ? array_map('addslashes_deep', $value) : addslashes($value);
    }
}
复制代码

array_map() 函数将用户自定义函数作用到数组中的每个值上,并返回用户自定义函数作用后的带有新值的数组。

这样数组中的每个值都得到转义处理

2. PDO方式防止注入

pdo中的预处理语句

复制代码
$servername = "localhost";
$username = "root";
$password = "";
$dbname = "haha";
 
try {
    $conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
    // 设置 PDO 错误模式为异常
    $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
 
    // 预处理 SQL 并绑定参数
    $stmt = $conn->prepare("select * from dw_user where `username`=:username and `password`=:password");
    $stmt->bindParam(':username', $firstname);
	$stmt->bindParam(':password', $pass);

    // 插入行
    $firstname = $_POST['username'];
	$pass = $_POST['password'];
    //$lastname = "Doe";
    //$email = "john@example.com";
    $stmt->execute();
    $rs = $stmt->Fetch();
	if($rs['user_id'] > 0 ){
		echo '登陆成功!';
		exit();
	}else{
		echo '登陆失败!';
		exit();
	}
 
    // 插入其他行
    //$firstname = "Mary";
    //$lastname = "Moe";
    //$email = "mary@example.com";
    //$stmt->execute();
 
    // 插入其他行
    //$firstname = "Julie";
    //$lastname = "Dooley";
    //$email = "julie@example.com";
    //$stmt->execute();
 
    //echo "新记录插入成功";
}
catch(PDOException $e)
{
    echo "Error: " . $e->getMessage();
}
$conn = null;

预处理绑定 会变成字符串包起来 不是 简单的 SQL 拼接

复制代码
相关推荐
盟接之桥6 小时前
盟接之桥说制造:引流品 × 利润品,全球电商平台高效产品组合策略(供讨论)
大数据·linux·服务器·网络·人工智能·制造
麦聪聊数据7 小时前
Web 原生架构如何重塑企业级数据库协作流?
数据库·sql·低代码·架构
未来之窗软件服务7 小时前
数据库优化提速(四)新加坡房产系统开发数据库表结构—仙盟创梦IDE
数据库·数据库优化·计算机软考
Fcy6487 小时前
Linux下 进程(一)(冯诺依曼体系、操作系统、进程基本概念与基本操作)
linux·运维·服务器·进程
袁袁袁袁满7 小时前
Linux怎么查看最新下载的文件
linux·运维·服务器
主机哥哥8 小时前
阿里云OpenClaw部署全攻略,五种方案助你快速部署!
服务器·阿里云·负载均衡
Goat恶霸詹姆斯9 小时前
mysql常用语句
数据库·mysql·oracle
大模型玩家七七9 小时前
梯度累积真的省显存吗?它换走的是什么成本
java·javascript·数据库·人工智能·深度学习
曾经的三心草9 小时前
redis-9-哨兵
数据库·redis·bootstrap
明哥说编程9 小时前
Dataverse自定义表查询优化:D365集成大数据量提速实战【索引配置】
数据库·查询优化·dataverse·dataverse自定义表·索引配置·d365集成·大数据量提速