Php 使用已使用filter_input()筛选的htmlspecialchars()从数据库输出数据

Php 使用已使用filter_input()筛选的htmlspecialchars()从数据库输出数据,php,security,mysqli,xss,htmlspecialchars,Php,Security,Mysqli,Xss,Htmlspecialchars,我从不同的博客中发现,强烈建议使用htmlspecialchars()在屏幕上输出任何数据,以防止XSS攻击 我正在使用filter\u input()filter_input()将像'这样的特殊字符转换为'并以这种方式保存,如 I'm going to shopping with Molly's sister;Dolly 1.我的问题是 如何使用htmlspecialchars向用户屏幕打印(输出)撇号或引号以及特定的特殊字符,以使输出对用户友好 我尝

我从不同的博客中发现,强烈建议使用
htmlspecialchars()
在屏幕上输出任何数据,以防止
XSS攻击

我正在使用
filter\u input()
filter_input()
将像
'
这样的特殊字符转换为
'并以这种方式保存,如

 I'm going to shopping with Molly's sister;Dolly
1.我的问题是

如何使用htmlspecialchars向用户屏幕打印(输出)撇号或引号以及特定的特殊字符,以使输出对用户友好

我尝试过使用
htmlspecialchars($post,entnoquotes)
,但它提供了存储在数据库中的相同数据副本。如果我不使用
htmlspecialchars()
,只需
$post
就可以得到预期的结果,我认为这很容易受到
XSS攻击

感谢您的时间,并期待得到同行的帮助

编辑

我得到建议在回答时使用
htmlspecialchars\u decode()
html\u entity\u decode()
,但是 () 还有一些人建议不要使用这些
函数
在屏幕上输出数据


请注意,我正在使用
准备语句
参数化查询
。但我不想保留任何安全漏洞,这就是为什么在发送到数据库之前过滤数据

由于我使用了
filter\u input()
在发送到数据库之前过滤数据,所以不使用
htmlspecialchars
直接从数据库输出数据(
$post=$posted\u data;
)安全吗

如果我必须使用
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

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

您想换一种方式:)

您不需要这样做,当您编码它们并将它们保存到DB时,它们将以应有的方式显示在网页上(当您使用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;
}
函数条带输入($text){
如果(!is_数组($text)){
$text=修剪($text);
$text=preg_replace(“/(&;)+(?=\#([0-9]{2,3}))/i“,”&“,$text);
$search=array(“&”、“\”、“'”、“\ \”、“\”、“\”、“\”、“\”、“,”);
$replace=数组(“&;”,“&;39;”,“&;92;”,“,”,“&;39;”,“,”,”);
$text=str_replace($search,$replace,$text);
}否则{
foreach($key=>$value的文本){
$text[$key]=stripinput($value);
}
}
返回$text;
}
我正在使用
filter\u input()

这是一种不好的做法。在将数据插入数据库之前,不要损坏数据。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']
]);
准备好的语句不再需要
过滤输入()。这样做并没有增加深度防御,只会破坏数据完整性,让自己头疼

呈现输出时,如果希望允许HTML,请使用

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


推荐阅读:泰勒·霍恩比。

我认为你的策略有问题

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

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

不,不要相信你的数据库,或者至少不总是这样。这不是第一个SQL注入导致巨大XSS的案例

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

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

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

我刚刚看到
htmlspecialchars
有双_编码参数,这将最终解决您的问题:

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

这样做将始终保持HTML特殊字符的转义,而不会转义已转义的内容。

但我被告知
htmlspecialchars_decode
输出数据是个坏主意。
XSS
riskAh,我现在明白了,我道歉。这是“不那么糟糕”的,如果你想自己处理它,让它更加“安全”,你可以扫描mysql中的文本,并检查它——我不知道使用普通的html_entity_decode()是否安全不过,我没有查看底层的C代码。我已经在使用
prepared语句
参数化查询
。但我不想保留任何安全漏洞,这就是为什么在将数据发送到数据库之前过滤数据。而且,
HTMLPurifier
应用于
textarea
中我希望允许有限的
HTML标记的位置。我将
HTMLPurifier
用于textarea,但不用于文本字段。