php - 防止sql注入

 mobiledu2502854827 发布于 2022-11-19 07:29

在网上看了些关于防止sql注入的文件和提问,比如使用预处理、过滤敏感字符。我一直想不明白的是,解决ssql注入问题非常非常简单啊,只要对用户输入的内容转义一下就可以了,就是讲用户输入的',"转义成\',\"就可以了,搞不懂为什么搞的那么复杂了?还是说我这种方法不能杜绝所有的sql注入

3 个回答
  • 只要对用户输入的内容转义一下就可以了,就是讲用户输入的',"转义成\',\"就可以了,搞不懂为什么搞的那么复杂了?还是说我这种方法不能杜绝所有的sql注入

    你一定不知道有一种注入叫做宽字符注入,int型注入,orderBy注入,
    其次注入其实非常容易防御,主要麻烦的是xss

    2022-11-19 07:49 回答
  • 解决注入,还是PDO来的比较彻底,最不济也得mysqli,上bind,加类型.

    2022-11-19 07:49 回答
  • 用htmlspecialchars/HTMLPurifier防御XSS注入,用预处理参数化查询防御SQL注入.

    调用HTMLPurifier过滤XSS后输出HTML:

    require dirname(__FILE__).'/htmlpurifier/library/HTMLPurifier.auto.php';
    $purifier = new HTMLPurifier();
    echo $purifier->purify($html);
    

    MySQLi绑定参数查询:

    $db = @new mysqli();
    $stmt = $db->prepare('SELECT * FROM posts WHERE id=?'); //预处理
    $stmt->bind_param('i', $id); //绑定参数
    $stmt->execute(); //查询
    var_export($stmt->get_result()->fetch_all());
    

    WireShark里用tcp.port==3306过滤分析PHP和MySQL通信

    <?php
    //MySQLi
    $id = 1;
    $mysqli = new mysqli('127.0.0.1', 'punbb', 'punbb', 'punbb');
    $mysqli->set_charset('utf8');
    $stmt = $mysqli->prepare("SELECT `username` FROM `pb_users` WHERE `id`=?");
    $stmt->bind_param('i', $id);
    $stmt->execute();
    $stmt->store_result();
    $stmt->bind_result($username);
    while ($stmt->fetch()) echo $username;
    $stmt->close();
    $mysqli->close();
    
    <?php
    //PDO
    $id = 1;
    //$dbh = new PDO('sqlite:/path/to/punbb.db3');
    $dsn = "mysql:dbname=punbb;host=127.0.0.1;port=3306;charset=utf8";
    $dbh = new PDO($dsn, 'punbb', 'punbb');
    $dbh->query('SET NAMES utf8');
    $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
    $sth = $dbh->prepare("SELECT `username` FROM `pb_users` WHERE `id`=?");
    $sth->bindParam(1, $id, PDO::PARAM_INT);
    $sth->execute();
    print_r($sth->fetchAll(PDO::FETCH_ASSOC));
    $sth = null;
    $dbh = null;
    

    在 Request Prepare Statement 里可以看到 SELECT username FROM pb_users WHERE id=?
    在 Request Execute Statement 里可以看到 Parameter 内容为:
    Type: FIELD_TYPE_LONGLONG (8)
    Unsigned: 0
    Value: 1
    可见PHP将SQL模板和变量分两次发送给MySQL,由MySQL完成变量的转义处理.
    既然SQL模板和变量是分两次发送的,那么就不存在SQL注入的问题了.

    在MySQL的general_log里可以看到:
    Prepare SELECT username FROM pb_users WHERE id=?
    Execute SELECT username FROM pb_users WHERE id=1
    如果ID绑定为string,则Execute时id赋值是这样的: id='1'
    如果PDO没有关闭模拟预处理,则可以看到:
    Query SELECT username FROM pb_users WHERE id=1

    2022-11-19 07:49 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有