首页 > 解决方案 > php函数htmlspecialchars不起作用

问题描述

在我必须为学校做的一个项目中,需要在我的网站上防止 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);
        } 
    }

标签: phphtmlxsswebsecurity

解决方案


对于您提出的问题以及您的代码中显而易见的问题,我将在这里列出一些有用的答案:

1)

如何正确设置您的 PDO 连接——一个很好的设置使用指南。

如何使用 PDO 准备语句- 准备语句从根本上比以前插入数据的方法更安全。你正在使用 PDO,但你没有准备你的陈述,所以你快到了....

2)

如何使用 PHP 防止 XSS

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

3)

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

4)

有很多 MySQL最佳实践可供查找和使用,我找不到一篇好的文章来解释这一切,但我真正需要向您概述的是

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

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

祝你好运


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

你的流程应该大致是:

保存数据

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

输出数据

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

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

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

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

    $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);
    } 

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


推荐阅读