PHP函数htmlspecialchars不起作用[重复]

Posted

技术标签:

【中文标题】PHP函数htmlspecialchars不起作用[重复]【英文标题】:Php function htmlspecialchars doesn't work [duplicate] 【发布时间】:2020-12-15 01:58:20 【问题描述】:

在我必须为学校做的一个项目中,它需要防止我的网站上的 XSS(跨站点脚本)攻击,所以标签如 <script type="text/javascript">alert("hello");</script>(我可以在我的网站的每个输入标签中插入)应该'不起作用(在这种情况下我不应该看到警报窗口)。在学校,有人建议我使用 php 函数 htmlspecialchars,但当我在网站的评论中插入此标签时,浏览器仍会显示警报窗口。我不明白我做错了什么。 (注意:我也插入了js代码,但我认为问题出在php上,所有代码都能正常工作)

$("#new-comment").on('click',function() 
  var $newReview = $("<input class='new-input' type='text' id='insert' name='insert' placeholder='write here...'>");  
  $("#reviews").append($newReview);   
  $newReview.on('keypress',function(e)
    if(e.which == 13)
      var comm = $(this);
      var datatime = new Date($.now());
      correctHour = printmysqlFormat(datatime);
      $.ajax(
        url:'reviews/reviews_query.php',
        data: put:true, title: $("#right_title").text(), script: comm.val(), time: correctHour,     
        datatype:'json',
        success: function(json)
          var output = jQuery.parseJSON(json);
          var newName = "<span class='rev_name'>"+ output + "</span>";
          var newComment = "<span class='rev_comment'>"+ comm.val() + "<div class='rev_time'>" + correctHour + "</div></span>";
          $("#reviews > ul").html($("#reviews > ul").html()+"<li style='margin-bottom:20px'>" + newName + " " + newComment + "</li>");
        ,
        error: function(e)
          console.log(e.message);
        
      );
      $newReview.remove(); 
    
  );
);

    if(isset($_GET["show"]) && isset($_GET["title"]))  //to show all comments
        $db = new PDO("mysql:host=localhost;dbname=music", "username", "password");
        $titolo = $_GET["title"];
        $ti = $db->quote($titolo);
        $rows = $db->query("SELECT * FROM reviews WHERE titolo=$ti ORDER BY ora ASC");
        if($rows->rowCount() == 0) 
            echo 0;
        else
            $res = $rows->fetchALL(PDO::FETCH_ASSOC);
            echo json_encode($res);
         
    
    
    if(isset($_GET["put"]) && isset($_GET["title"]) && isset($_GET["script"]) && isset($_GET["time"]))  //to write a new comment
        $db = new PDO("mysql:host=localhost;dbname=music", "username", "password");
        $username = $_SESSION["name"];
        $us = $db->quote($username);
        $titolo = $_GET["title"];
        $ti = $db->quote($titolo);
        $commento = $_GET["script"];
        $commento = htmlspecialchars($commento);
        $comm = $db->quote($commento);
        $timestamp = $_GET["time"];
        $tim = $db->quote($timestamp);
        $rows = $db->query("INSERT into reviews VALUES ($us, $ti, $comm, $tim)");     
        $res = $_SESSION["name"];
        echo json_encode($res); 
     

编辑:我已尝试使用此代码,但没有任何变化:

    if(isset($_GET["show"]) && isset($_GET["title"]))  
        $db = new PDO("mysql:host=localhost;dbname=music", "username", "password");
        $titolo = $_GET["title"];
        $ti = $db->quote($titolo);
        $rows = $db->query("SELECT * FROM reviews WHERE titolo=$ti ORDER BY ora ASC");
        if($rows->rowCount() == 0)
            echo 0;
        else
            $res = $rows->fetchALL(PDO::FETCH_ASSOC);
            $res['comment_clean'] = htmlspecialchars($res['commento'], ENT_QUOTES, 'UTF-8'); //commento is an attribute of my table, where I save the comment
            echo json_encode($res);
         
    

【问题讨论】:

请注意:虽然您可能已经(尝试)保护它免受脚本注入,但您未能充分保护它免受 SQL 注入。 嗯,你的老师错了,你应该让他/她知道。 无论如何关于脚本注入...我可以在您的“成功”功能中看到您正在执行newComment = "&lt;span class='rev_comment'&gt;"+ comm.val(),然后将其放入您的页面。因此,在这段代码中,您只是直接从输入中获取原始评论值。您没有使用保存到数据库中的编码版本。 遗憾的是,教育工作者和教育机构在 IT 主题上极度过时是很常见的,因为 IT 主题每 1-2 年更新和更新一次,而其他教育主题(木工/科学/历史)几十年甚至几个世纪都没有太大的变化,导师们不习惯必须真正探索和重新探索 最佳实践。这样你作为学生就会陷入困境;要么按照你的导师的期望去做,做最佳实践。这不是一个很好的选择,并导致许多 IT 公司每次都将经验超过成绩。祝你好运 htmlspecialchars 应用于插入数据库的数据,从根本上说是错误的。这应该发生在从数据库中读回数据时,即数据放入 HTML 上下文的那一刻。但是您甚至还没有向我们展示 那个 部分,目前您从服务器返回给客户端的唯一内容是会话中的用户名,所有其他值仍然是客户端的开始。 【参考方案1】:

我将在此处列出一些有用的答案,这些答案既适用于您提出的问题,也适用于您的代码中显而易见的问题:

1)

How to correctly set up your PDO connection -- 一个很好的设置使用指南。

How to use PDO prepared statements - 准备好的语句从根本上比以前插入数据的方法更安全。您正在使用 PDO,但您没有准备您的声明,所以您快到了....

2)

How to prevent XSS with PHP

注意:您应该在输出数据时使用htmlspecialchars,而不是在输入数据到数据库时。

3)

如果您想在源输入中允许任何 HTML,那么您应该在表单数据上使用HTML Purifier,一旦将其发送回您的服务器并在插入数据库之前。

4)

有很多 MySQL Best Pactise 可供查找和使用,我找不到一篇好的文章来解释这一切,但我真的需要 给你概述是

您不应该使用root 登录来通过网站访问/保存数据。始终使用其他自定义用户,该用户仅具有所需的有限权限

如果有人有指向 4 的 URL 引用的链接,那就太好了!

祝你好运


是的,但是在 php 或 jquery 中?我知道这是一个 php 函数,所以我在考虑我的 php 代码的第一部分。如果你也可以写我必须插入的行,那将非常有用

你的流程应该大致是:

保存数据

HTML:通过HTML&lt;form&gt;(等)收集数据,数据通过表单提交发送到服务器。 PHP 根据需要对数据进行可选处理(检查有效性等) PHP 根据需要使用 HTMLPurifier 或类似工具来安全地删除不需要的 HTML。 PHP 此收集的数据应放入PDO Prepared Statement SQL 数据保存到数据库中。

输出数据

PHP 为您想要的数据构建 SQL 请求,通常使用 id 引用调用。 PHP 加载要返回给客户端(用户浏览器)的数据 PHP 对此数据运行 htmlspecialchars 以禁用 HTML 元素 HTML 数据显示到客户端浏览器。

我理解这个过程,我也读过那个线程,但我不知道如何在我的代码中编写它

这是您代码中的一个示例:

还值得注意的是,您应该始终在 SQL 查询中手动引用所有列名和 NOT SELECT * FROM

    $rows = $db->prepare("SELECT id, name, htmlcode FROM reviews WHERE titolo=:title ORDER BY ora ASC");
    $rows->execute(['title' => $ti]); //SAFE SQL query.
    if((int)$rows->rowCount() === 0) 
        echo 0;
     else
        $res = $rows->fetchALL(PDO::FETCH_ASSOC);
        // Res will be a multilevel array so you need to apply changes to each subarray key. 
        foreach($res as &$resRow)
        //disable HTML. For example only this is saved into a new array value.
            $resRow['commento'] = htmlspecialchars($resRow['commento'], ENT_QUOTES, 'UTF-8'); 
        
        echo json_encode($res);
     

您还应该习惯使用绝对比较运算符===,而不是模糊比较运算符==

【讨论】:

对不起,但我是这些语言的新手,所以我有一些困难,但我应该在我的 php 代码的第一部分使用 htmlspecialchars(当我显示所有 cmets 时)?你能帮我解决这个问题吗? @Titania,当您显示/输出数据库中的 HTML 数据时,您应该使用htmlspecialchars。不是当你把它保存到数据库时。 是的,但是在 php 或 jquery 中?我知道这是一个 php 函数,所以我在考虑我的 php 代码的第一部分。如果你也可以写我必须插入的行,那将非常有用 @Titania 我已经更新了我的答案,这能让你更好地了解这个过程吗? @Titania 我强烈推荐reading this thread

以上是关于PHP函数htmlspecialchars不起作用[重复]的主要内容,如果未能解决你的问题,请参考以下文章

php 使用htmlspecialchars() 和strip_tags函数过滤HTML标签的区别

PHP表单安全过滤和防注入 htmlspecialchars() 和test_input()

php urlencode 和 htmlspecialchars 在 html <a href> 中启动函数内的变量

PHP htmlentities 和 htmlspecialchars的区别

PHP如何防止XSS攻击

为啥这个 PHP 递归函数不起作用