【问题标题】:Mysql dynamic query [sql injection]Mysql动态查询【sql注入】
【发布时间】:2021-12-20 04:49:40
【问题描述】:

我通常使用准备好的语句,但在特定页面上我使用的是动态查询,我找不到防止 SQL 注入的可靠方法。

if(isset($_GET['sub_cat'])){

    if($_GET['sub_cat'] != '')
        $conditions[] = 'ad_sub_cat='.$_GET['sub_cat'].'';
}

if(isset($_GET['ad_brand'])){

    if($_GET['ad_brand'] != '')
        $conditions[] = "`ad_brand` LIKE CONCAT('%','".$_GET['ad_brand']."','%') ";
}

if(isset($_GET['min_range'])){

    if($_GET['min_range'] != '')
        $conditions[] = 'ad_price >='.$_GET['min_range'].'';
}

if(isset($_GET['max_range'])){

    if($_GET['max_range'] != '')
        $conditions[] = 'ad_price <='.$_GET['max_range'].'';
}

if(isset($_GET['for_r_s'])){
    
    if($_GET['for_r_s'] != '')
        $conditions[] = 'for_r_s ='.$_GET['for_r_s'].'';
}

$query = "SELECT posts.ID, posts.ad_title, posts.ad_price, posts.ad_location, posts.ad_sub_cat FROM `posts` WHERE ". implode(' AND ', $conditions) .""; 

【问题讨论】:

    标签: php mysql sql-injection


    【解决方案1】:

    您可以像处理任何其他查询一样防止 SQL 注入:通过将始终基于硬编码值的 查询数据 分开.唯一的区别是您需要有条件地构建查询和数据参数列表。

    所以而不是:

    if(isset($_GET['sub_cat'])){
    
        if($_GET['sub_cat'] != '')
            $conditions[] = 'ad_sub_cat='.$_GET['sub_cat'].'';
    }
    

    你应该写:

    if(isset($_GET['sub_cat'])){
    
        if($_GET['sub_cat'] != '') {
            $sql_conditions[] = 'ad_sub_cat=:sub_cat';
            $parameters['sub_cat'] = $_GET['sub_cat'];
        }
    }
    

    或者如果使用位置参数而不是命名参数:

    if(isset($_GET['sub_cat'])){
    
        if($_GET['sub_cat'] != '') {
            $sql_conditions[] = 'ad_sub_cat=?';
            $parameters[] = $_GET['sub_cat'];
        }
    }
    

    等等,满足你的所有条件。

    最后,您从 $sql_conditions 构建您的 SQL - 它根本没有用户输入,因此不会被注入 - 并将 $parameters 传递给 PDO/mysqli 以执行查询。

    【讨论】:

    • 好的,我想知道我是否应该这样做,但想问问是否有其他解决方案。谢谢最佳答案 祝您白天或晚上愉快
    • 我可以问$get_posts-&gt;bind_param(' ', ); 我将如何在第一个字段中获得s 我应该为该参数创建另一个$var 吗?
    • @DB_cont 啊,是的,我使用 PDO 而不是 mysqli,所以没有考虑这一点。您可以与参数同时构建它(例如$placeholder_types .= 's';),或者如果它们都是字符串,则在最后构建它str_repeat('s', count($parameters))
    • 第一个是我做的,但将来可能会使用 PDO 这只是一个测试版:)
    【解决方案2】:

    在将参数添加到查询字符串之前使用mysqli_real_escape_string。 例如:

    if(isset($_GET['sub_cat']) && $_GET['sub_cat'] != ''){
    
        $sub_cat = mysqli_real_escape_string($connection, $_GET['sub_cat']);
    
        $conditions[] = 'ad_sub_cat='.$sub_cat.'';
    }
    

    【讨论】:

    • 没有。即使使用mysqli_real_escape_string,您仍然可以注入
    • @DB_cont 在极少数情况下,是的。
    • @Afsal 就像我们知道我们应该始终考虑那些罕见的情况,因为优秀的黑客会尝试它,然后当您的网站被入侵时,您就会遇到问题
    • @DB_cont 如果您想坚持使用过程方法而不是 PDO,我认为这是推荐的最佳选择。 (总是感谢更正 :) )或者您可以更多地解决 PDO 以使用 switch 语句生成所需的查询。这是您将根据权重(确定组合的标识符)生成并绑定案例内的参数。毕竟,如何实现解决方案取决于开发人员。查询生成可以通过多种方式实现。
    • @Afsal 我非常感谢您花时间写这个答案,我并不是说它错了,只是说它不如第一个答案好,但您仍然帮助了我,我希望您有一个美好的一天
    猜你喜欢
    • 2021-02-14
    • 2018-08-21
    • 1970-01-01
    • 2023-04-03
    • 1970-01-01
    • 1970-01-01
    • 2022-01-20
    • 1970-01-01
    • 2016-11-11
    相关资源
    最近更新 更多