【问题标题】:Php function htmlspecialchars doesn't work [duplicate]PHP函数htmlspecialchars不起作用[重复]
【发布时间】: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 上下文的那一刻。但是您甚至还没有向我们展示 那个 部分,目前您从服务器返回给客户端的唯一内容是会话中的用户名,所有其他值仍然是客户端的开始。

标签: php html xss websecurity


【解决方案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
猜你喜欢
  • 2012-07-06
  • 1970-01-01
  • 1970-01-01
  • 2015-04-16
  • 2017-06-30
  • 2013-03-22
  • 2018-09-04
  • 2015-01-14
  • 1970-01-01
相关资源
最近更新 更多