выводить данные из базы данных с помощью htmlspecialchars(), которые были отфильтрованы с помощью filter_input()

Я узнал из разных блогов, что настоятельно рекомендуется использовать htmlspecialchars() для вывода любых данных на экран, чтобы обезопасить себя от XSS Attack.

Я использую filter_input() для фильтрации любых данных, поступающих от пользователя, перед вставкой в ​​database. filter_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%CD%A2ck) и некоторые другие предлагали не использовать эти functions для вывода данных на экран.

Обратите внимание, что я использую prepared statement и parameterized 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

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

person Coder    schedule 28.02.2015    source источник
comment
stackoverflow.com/questions/1162491/   -  person Sony Mathew    schedule 28.02.2015


Ответы (4)


Я использую 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') для достижения наилучших результатов.

Рекомендуемая литература: Безопасность веб-приложений Тейлора Хорнби.

person Scott Arciszewski    schedule 04.03.2015
comment
Я уже использую prepared statement и parameterized query. Но я не хочу оставлять дыр в безопасности, поэтому фильтрую данные перед отправкой в ​​базу данных. - person Coder; 04.03.2015
comment
И HTMLPurifier следует использовать для textarea, где я хочу разрешить ограниченное HTML Tags. Я использую HTMLPurifier для текстовой области, но не для текстового поля. Потому что это 2015 год. Спасибо за ваш ответ, чувак. мое замешательство. - person Coder; 04.03.2015
comment
Вы должны htmlentities() содержимое текстовой области в любом случае. если вы используете подготовленные операторы, вам не нужно очищать ввод. Он отделяет данные от инструкций. - person Scott Arciszewski; 05.03.2015
comment
Я просто хочу еще раз подчеркнуть, что очистка вывода — это то, что вам нужно делать на выходе, а не при вставке его в базу данных. Очистка перед вставкой просто приводит к повреждению данных. - person Sven Slootweg; 09.03.2015
comment
@SvenSlootweg Вы имели в виду вставлять введенные пользователем данные как есть в базу данных? И просто используйте htmlspecialchars для вывода на экран пользователей. разве вредоносные данные не могут быть вставлены даже после использования prepared statement? - person Coder; 10.03.2015
comment
Что вы подразумеваете под вредоносными данными? - person Scott Arciszewski; 10.03.2015
comment
@Coder Да, это то, что я имею в виду. Это не вредоносные данные, пока они находятся в базе данных — база данных понятия не имеет, что такое HTML или Javascript, ей все равно, и поэтому ее не нужно защищать от них. Это всего лишь байты, это может быть что угодно, если речь идет о базе данных. XSS становится проблемой только тогда, когда вы пытаетесь вывести данные на веб-страницу, поэтому вы очищаете их при выводе. Просто сохраните исходные данные в своей базе данных, чтобы у вас были «неповрежденные» данные для работы, если вам когда-нибудь понадобится что-то изменить. - person Sven Slootweg; 11.03.2015
comment
Я просто хочу сохранить простоту и не хочу разрешать html tags для любого поля. - person Coder; 13.03.2015
comment
Если вы это сделаете, это не позволит НИКАКИХ тегов. Он превращает < в &lt; и т. д. в соответствии со спецификацией HTML5. Ты в безопасности. eval.in/300124 - person Scott Arciszewski; 13.03.2015

Я думаю, что проблема с вашей стратегией.

Вам, конечно, нужно фильтровать входные и выходные данные, но вы накладываете их друг на друга - двойной экран.
Проблема в том, что ваш входной фильтр выполняет также работу выходного фильтра.

Поскольку я использовал filter_input() для фильтрации данных перед отправкой в ​​базу данных, безопасно ли выводить данные напрямую ($post=$posted_data;) из базы данных без использования htmlspecialchars?

Нет. Не доверяйте своей базе данных, по крайней мере, не всегда. Это не первый случай, когда SQL-инъекция вызвала огромный XSS.

Если мне нужно использовать htmlspecialchars для вывода данных, то как я могу это сделать в этом случае?

Как я уже сказал выше, прекратите использовать входной фильтр для фильтрации вывода. Ваш входной фильтр должен просто убедиться, что данные безопасны для внутреннего использования, чтобы защитить ваше приложение от операций без отступов. Таким образом, вам не нужно экранировать HTML перед вставкой в ​​базу данных, и в качестве бонуса вы сэкономите место.

С другой стороны, выходной фильтр заботится о конечном пользователе. Вы берете данные из БД и отправляете их пользователю. Мы говорим о htmlspecialchars, что хорошо с ENT_QUOTES, но, на мой взгляд, этого недостаточно. Вам также следует экранировать такие символы, как ( ) [ ] = + - \, так как в некоторых случаях вам не нужно открывать/закрывать любой тег или использовать кавычки для успешной атаки XSS. Например, когда вы выводите данные в onclick и т. д.

Я только что увидел, что htmlspecialchars имеет параметр double_encode, который в конечном итоге решит вашу проблему:

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

Это всегда будет экранировать специальные символы HTML и не будет экранировать уже экранированные вещи.

person Zaffy    schedule 05.03.2015

Вы хотите пойти наоборот :) htmlspecialchars_decode()

person Patrick Webster    schedule 28.02.2015
comment
Но мне сказали, что htmlspecialchars_decode это плохая идея для вывода данных.XSS риск - person Coder; 28.02.2015
comment
А, теперь я понял, мои извинения. Это менее плохой php.net/manual/en/function.html -entity-decode.php - person Patrick Webster; 28.02.2015
comment
Если вы хотите справиться с этим самостоятельно, чтобы быть более безопасным, вы можете просмотреть текст в mysql, сверив его с php.net/manual/en/function.get-html-translation-table.php -- я не знаю, более или менее безопасно использовать обычный html_entity_decode( ), не глядя на базовый код C. - person Patrick Webster; 28.02.2015

Вам не нужно, когда вы кодируете их и сохраняете в БД, они будут отображаться на веб-странице (когда вы используете echo $result['message'];), как и должны. Браузеры автоматически декодируют их.

Я использую эту функцию для ввода данных:

function stripinput($text) {
    if (!is_array($text)) {
        $text = trim($text);
        $text = preg_replace("/(&amp;)+(?=\#([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;
}
person MiChAeLoKGB    schedule 28.02.2015