Выход из вывода безопасно и для HTML и для полей ввода

В моем веб-приложении пользователи могут ввести текстовые данные. Эти данные можно показать другим пользователям, и исходный автор может также возвратиться и отредактировать их данные. Я ищу корректный способ безопасно выйти из этих данных.

Я только sql санирующий на пути в, таким образом, все хранится, поскольку он читает. Скажем, у меня есть "дежа вю" в базе данных. Или, чтобы быть более экстремальным, a <script> тег. Возможно, что это может быть допустимо, и даже злонамеренно предназначенное, ввести.

Я использую htmlentities() на выходе для проверки всего оставляют. Проблема состоит в том, что HTML и поля ввода рассматривают вещи по-другому. Я хочу удостовериться, что это безопасно в HTML, но что автор при редактировании текста, видит точно, что они ввели в полях ввода. Я также использую jQuery для заполнения полей формы данными динамично.

Если я делаю это:

 <p><?=htmlentities("déjà vu");?></p>
 <input type=text value="<?=htmlentities("déjà vu");?>">

Источник страницы помещает d&eacute;j&agrave; vu в обоих местах (я имел к обратной галочке, это или Вы будет видеть "дежа вю"!) Проблема состоит в том что вывод в <p> корректно, но вход просто показывает завершенный текст. Если пользователь повторно отправляет их форму, они двойной Escape, и разрушьте их вход.

Я знаю, что все еще должен санировать текст, который входит в поле, иначе можно закончить кавычку значения и сделать плохие вещи. Единственное решение, которое я нашел, является этим. Снова, я использую jQuery.

var temp = $("<div></div>").html("<?=htmlentities("déjà vu");?>");
$("input").val(temp.html());

Это работает, поскольку это заставляет отделение читать завершенный текст как закодированные символы, и затем jQuery копирует те закодированные символы во входной тег, правильно сохраненный.

Так мой вопрос: это все еще безопасно, или где-нибудь существует ли дыра в системе безопасности? И что еще более важно, действительно ли это - единственное / корректный способ сделать это? Я пропускаю что-то о том, как HTML и работы кодировки символов, которые делают это тривиальной проблемой для решения?

Править

Это на самом деле неправильно, я упростил свой пример на грани его не работа. Проблема состоит на самом деле в том, потому что я использую val jQuery () для вставки текста в поле.

<input>
<script>$("input").val("<?=htmlentities("déjà vu");?>");</script>

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

Таким образом, кажется, что jQuery выходит из данных для входа во вход, но это не совсем достаточно хорошо - если я ничего не делаю сам, пользователь может все еще вставить a </script> тег, уничтожая мой код и вводя вредоносный код. Но существует другой аргумент, который будет сделан здесь. Так как только исходный автор видит текст в поле ввода так или иначе, я должен даже обеспокоиться? В основном единственные люди, на которых они могли выполнить нападение XSS, самостоятельно.

5
задан Josh Stodola 30 June 2010 в 13:30
поделиться

3 ответа

Извините, но я не могу воспроизвести описанное вами поведение. Я всегда использовал htmlspecialchars () (который, по сути, выполняет ту же задачу, что и htmlentities () ), и это никогда не приводит к какому-либо двойному кодированию. Исходный код страницы показывает déjà vu в обоих местах (конечно! В том-то и дело!), Но обработанная страница показывает соответствующие значения, и это то, что отправлено обратно на сервер.

Можете ли вы опубликовать полный автономный фрагмент кода, демонстрирующий такое поведение?

Обновление : некоторый тестовый код:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head><title></title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body>

<?php

$default_value = 'déjà vu <script> ¿foo?';

if( !isset($_GET['foo']) ){
    $_GET['foo'] = $default_value;
}

?>

<form action="" method="get">
    <p><?php echo htmlentities($_GET['foo']); ?></p>
    <input type="text" name="foo" value="<?php echo htmlentities($_GET['foo']); ?>">
    <input type="submit" value="Submit">
</form>

</body>
</html>

Ответ на обновленный вопрос

htmlentities () функция, как следует из названия, используется при генерации вывода HTML. Вот почему во втором примере от него мало пользы: JavaScript - это , а не HTML. Это отдельный язык со своим синтаксисом.

Теперь проблема, которую вы хотите решить, заключается в том, как сгенерировать вывод, который следует этим двум правилам:

  1. Это допустимая строка в JavaScript.
  2. Его можно безопасно встроить в документ HTML.

Ближайшая функция PHP для №1, о которой я знаю, - это json_encode () . Поскольку синтаксис JSON является подмножеством JavaScript, если вы загрузите его строкой PHP, он выведет строку JavaScript.

Как и в случае с №2, когда браузер входит в блок JavaScript, он ожидает, что тег оставит его. Функция json_encode () позаботится об этом и правильно экранирует ( <\ / script> ).

Мой измененный тестовый код:

<?php

$default_value = 'déjà vu </script> ¿foo?';

if( !isset($_GET['foo']) ){
    $_GET['foo'] = $default_value;
}

?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head><title></title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript"><!--
$(function(){
    $("input[type=text]").val(<?php echo json_encode(utf8_encode($_GET['foo'])); ?>);
});
//--></script>
</head>
<body>


<form action="" method="get">
    <p><?php echo htmlentities($_GET['foo']); ?></p>
    <input type="text" name="foo" value="(to be replaced)">
    <input type="submit" value="Submit">
</form>

</body>
</html>

Примечание: utf8_encode () преобразуется из ISO-8859-1 в UTF-8, и это не требуется, если ваши данные уже находятся в UTF-8 (рекомендуется ).

5
ответ дан 14 December 2019 в 13:25
поделиться

Если вам просто нужно отменить кодирование, вы можете использовать html_entity_decode - http://www.php.net/manual/en/function.html-entity-decode.php .

Другая возможность - запускать htmlentities только в то время, когда контент будет отображаться как часть веб-страницы. В противном случае сохраните незакодированный текст в том виде, в котором он был отправлен или загружен из хранилища данных.

1
ответ дан 14 December 2019 в 13:25
поделиться

Я считаю, что проблема в том, как вы применяете значение к входу. Он отображается как закодированный, что имеет смысл, потому что это Javascript, а не HTML. Итак, я бы предложил записать ваш закодированный текст как часть разметки, чтобы он обрабатывался естественным образом (в отличие от инъекции клиентским скриптом). Поскольку ваши текстовые поля недоступны, когда сервер отвечает, вы можете использовать временное скрытое поле ...

<input type="hidden" id="hidEncoded" value="<?=htmlentities("déjà vu");?>" />

Тогда оно будет проанализировано как старый добрый HTML, и когда вы попытаетесь получить доступ к значению с помощью Javascript, оно должно быть декодировано ...

// Give your textbox an ID!
$("#txtInput").val($("#hidEncoded").val());
0
ответ дан 14 December 2019 в 13:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: