使用已使用filter_input()过滤的htmlspecialchars()从数据库输出数据

时间:2015-02-28 00:51:59

标签: php security mysqli xss htmlspecialchars

我从不同的博客中发现,强烈建议您使用htmlspecialchars()在屏幕上输出任何数据,以免XSS Attack安全。

我正在使用filter_input()过滤来自用户的任何数据,然后再插入databasefilter_input()'等特殊字符转换为'并以此方式保存,例如

 I'm going to shopping with Molly's sister;Dolly

。我的问题是

How can I print(output) apostrope or quotes and specific special characters to users screen using htmlspecialchars so that the output would be user friendly

我尝试使用htmlspecialchars($post,ENT_NOQUOTES);,但它为我提供了存储在数据库中的相同数据副本。如果我不使用htmlspecialchars(),只需$post即可获得预期结果,我认为容易受到XSS Attack

的攻击

感谢您的时间,并期待从同行那里获得帮助。

修改

我得到了在答案中使用htmlspecialchars_decode()html_entity_decode()的建议,但是 (https://stackoverflow.com/users/1338292/ja͢ck) 还有一些人建议不要使用这些functions在屏幕上输出数据。

请注意,我正在使用prepared statementparameterized query。但我不想保留任何安全漏洞,这就是为什么在发送到数据库之前过滤数据。

由于我在发送到数据库之前使用filter_input()来过滤数据,因此在不使用$post=$posted_data;的情况下从数据库直接输出数据(htmlspecialchars)是否安全?

如果我必须使用htmlspecialchars输出数据,那么在这种情况下我该怎么办呢?

代码示例

 $stmt1=mysqli_stmt_init($connect_dude);

 /*Inserting into database*/

 if(isset($_POST['titlex']) && isset($_POST['pricex'])  && isset($_POST['detailx'])){
  $tit=filter_input(INPUT_POST,'titlex',FILTER_SANITIZE_STRING);
  $pri=preg_replace('#[^0-9]#','',$_POST['pricex']);
  $det=filter_input(INPUT_POST,'detailx',FILTER_SANITIZE_STRING); 

  $query2="INSERT INTO `hotel1`.`dine` (user_id,title,price,detail) VALUES (?,?,?,?)";

    mysqli_stmt_prepare($stmt1,$query2);
    mysqli_stmt_bind_param($stmt1, "isis", $logged_id, $tit, $pri, $det);
    mysqli_stmt_execute($stmt1);    
 }

 /*Get Data from DB*/

 $query1="SELECT id101,title,price,detail FROM `hotel1`.`dine` WHERE user_id=?";

    mysqli_stmt_prepare($stmt1,$query1);
    mysqli_stmt_bind_param($stmt1, "i", $user_idx);
    mysqli_stmt_execute($stmt1);
    mysqli_stmt_store_result($stmt1);
    mysqli_stmt_bind_result($stmt1, $id101, $title,$price, $detail);

    while(mysqli_stmt_fetch($stmt1)){
     $id101=$id101;
     $title=$title;        //htmlspecialchars needed
     $price=$price;       //htmlspecialchars needed
     $detail=$detail;    //htmlspecialchars needed

     ........................
     ........................
     }

4 个答案:

答案 0 :(得分:8)

  

我正在使用filter_input()过滤来自用户的任何数据,然后再插入database

这是一种不好的做法。在将数据插入数据库之前,请不要破坏数据。这是2015年;不要消毒,而是使用准备好的陈述。

$db = new \PDO(
    'mysql:host=localhost;dbname=mydatabase;charset=UTF-8',
     $username,
     $password
);

// other stuff in between

$statement = $db->prepare(
    "INSERT INTO yourtable (email, username) VALUES (:email, :username);"
);
$success = $statement->execute([
    ':email'    => $_POST['email'],
    ':username' => $_POST['username']
]);

准备好的陈述消除了对filter_input() 的需求。你不是通过这样做来加深防御,你只是在破坏数据完整性并让自己头疼。

渲染输出时,如果要允许HTML,请使用HTML Purifier

否则,请使用htmlspecialchars($output, ENT_QUOTES | ENT_HTML5, 'UTF-8')以获得最佳效果。

推荐阅读:Taylor Hornby的Web Application Security

答案 1 :(得分:0)

我认为您的策略存在问题。

你当然需要过滤输入和输出内容,但是你要覆盖它们 - 双重逃避 问题是你的输入过滤器也在做输出过滤器的工作。

  

由于我在发送到数据库之前使用了filter_input()来过滤数据,因此可以安全地从数据库直接输出数据($ post = $ posted_data;)而不使用htmlspecialchars吗?

没有。不要相信你的数据库,或者至少不要总是如此。它不会是SQL注入导致巨大XSS的第一种情况。

  

如果我必须使用htmlspecialchars输出数据,那么在这种情况下我该怎么办呢?

如上所述,停止使用输入过滤器进行输出过滤。您的输入过滤器应确保数据对内部使用是安全的 - 以保护您的应用程序免受非缩进操作。因此,在插入数据库之前,您不需要转义HTML,作为奖励,您可以节省空间。

另一方面,输出过滤器关心最终用户。您从db获取数据并将其发送给用户。我们正在谈论htmlspecialchars这对ENT_QUOTES来说没问题,但我认为还不够。您还应该转义( ) [ ] = + - \等字符,因为有些情况您不需要成功的XSS攻击来打开/结束任何标记或使用引号。例如,当您将数据输出到onclick

我刚看到htmlspecialchars有double_encode参数,这最终会解决您的问题:

htmlspecialchars($string, ENT_QUOTES, "UTF-8", false);

执行此操作将始终保持HTML特殊字符转义,并且不会逃脱已转义的内容。

答案 2 :(得分:-1)

你想要反过来:) htmlspecialchars_decode()

答案 3 :(得分:-1)

您不需要,当您对它们进行编码并将其保存到数据库时,它们将显示在网页上(当您使用echo $ result ['message'];)时,它们应该如此。浏览器自动解码它们。

我正在使用此功能去除输入:

function stripinput($text) {
    if (!is_array($text)) {
        $text = trim($text);
        $text = preg_replace("/(&)+(?=\#([0-9]{2,3});)/i", "&", $text);
        $search = array("&", "\"", "'", "\\", '\"', "\'", "<", ">", "&nbsp;");
        $replace = array("&amp;", "&quot;", "&#39;", "&#92;", "&quot;", "&#39;", "&lt;", "&gt;", " ");
        $text = str_replace($search, $replace, $text);
    }else{
        foreach ($text as $key => $value) {
            $text[$key] = stripinput($value);
        }
    }
    return $text;
}