Широкий обзор, блок-схема по экранированию пользовательского контента для html, javascript и PHP - PullRequest
3 голосов
/ 19 июня 2011

Кто-нибудь может подсказать мне хорошие ответы на StackOverflow и другие ресурсы, включая книги, по экранированию пользовательского контента для HTML, JavaScript и PHP?

Например, скажем, пользователь вводит информацию в текстовое поле и нажимает кнопку отправки. Затем текст записывается JavaScript в div на странице, а также отправляется через GET в PHP, а PHP помещается в базу данных MySQL.

Я ищу хороший, широкий, но также подробный обзор всех возможных видов побега. Блок-схема тоже поможет!

Спасибо!


Спасибо! Я ищу кого-то, похожего на шпаргалку, с разделами: 1) экранирование для отображения html, 2) экранирование для ввода URL-адреса 3), отправка URL-адреса в PHP, 4) вставка данных из URL-адреса в базу данных. В каждом разделе должны быть 1) примеры потенциальных проблемных ситуаций и символов, которые следует экранировать, 2) примеры того, как экранировать символы, и 3) как декодировать символы, если это необходимо позже.

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


Этот график пока выглядит довольно хорошо http://www.the -art-of-web.com / JavaScript / побег /

Ответы [ 3 ]

2 голосов
/ 21 февраля 2012

Я бы всегда использовал «POST» для пользовательских данных сам, а не «GET», и следующее обсуждение отражает это, но вы все равно сможете использовать около 90% того, что я скажу ниже в любом случае.Итак, вот так ...

Общее правило: не думайте заранее, избегая данных.Только сделайте немедленно необходимые преобразования.Канонический пример: не переходите на HTML при вставке базы данных, так как в итоге вы получите, например, '&', превратившись в '& amp;'после пары туров.

Общее правило: Используйте UTF-8 повсюду.Вы будете благодарны за это в первый раз, когда кто-то сделает копию вставки из электронного письма с многоточием Юникода.(Вы будете удивлены, как часто это происходит.) Необходимы типичные настройки;это может варьироваться в зависимости от версии PHP / MySQL / HTML:

  • PHP: php_value default_charset "UTF-8"
  • MySQL: при создании базы данных выберите utf8.
  • HTML:

Общее правило: только пять мест, куда могут перемещаться неанизированные (хотя и должным образом экранированные) пользовательские данные:

  • Значение (правильно типизированного) поля базы данных (т. е. текстовое поле UTF-8 или поле большого двоичного объекта.)
  • Значение переменной PHP.
  • Значение переменной Javascript.
  • Значение формы HTMLАтрибут 'value' элемента.
  • Содержимое дочернего элемента textNode элемента HTML.

Если вы хотите поместить пользовательские данные в любое другое место, оно должнобыть продезинфицированным.Это выходит за рамки вопроса, но в типичном случае вы можете использовать регулярное выражение для замены всего, что не является буквой или цифрой ASCII, подчеркиванием.В тех случаях, когда уникальность имеет значение, например, имя файла или атрибут «id» в HTML, необходимо выполнить дополнительную работу, чтобы убедиться, что очищенные имена являются уникальными (например, убедитесь, что столкновение происходит, когда 'a ^ b' и 'a & b'оба очищаются до' a_b ').Типичное решение выглядит примерно так:

filename = original_filename;
while(already_exists(filename)) {count++; filename = original_filename + count;}

И, наконец, смысл моего ответа: специальные функции escape, используемые для перемещения данных в те пять специальных мест, куда могут попадать неизмененные пользовательские данные:1034 *

  • Атрибут значения HTML-формы -> переменная PHP $ _POST: экранирование не требуется.
  • Переменная PHP -> поле базы данных: подготовленный оператор PDO:

    $stmt = $db->prepare('insert into roundtrip (id, name) values (NULL, :data)');
    $stmt->execute(array('data' => $_POST['name']));
    
  • Поле базы данных -> PHP-переменная: экранирование не требуется, но используйте подготовленный оператор PDO для экранирования значений запроса:

    $stmt = $db->prepare('select id, name from roundtrip where name = :data');
    $stmt->execute(array('data' => $_POST['name']));  // User data needs escaping.
    while ($result = $stmt->fetch()) {
        echo $result['name']; // DB result doesn't.
    }
    
  • PHP-переменная -> переменная Javascript: json_encode:

    var data = <?php echo json_encode(data); ?>;
    
  • PHP-переменная -> HTML textNode или значение формы: htmlspecialchars:

    <div><?php echo htmlspecialchars(data); ?></div>
    <input type="text" name="name" value="<?php echo htmlspecialchars(data); ?>"/>
    
  • Javascript <-> HTMLtextNode или значение формы: встроенные в браузер атрибуты / функции textNode и .value:

    data = source_div.textContent; // Firefox
    data = source_div.innerText; // Other browsers
    target_div.textContent = data; // Firefox
    target_div.innerText = data; // Other browsers
    
    // To/from form element.
    data = source_form.value;
    target_form.value = data;
    
    // Append to element.
    target_div.appendChild(document.createTextNode(data)); // All browsers
    
    // jQuery textNode
    data = $('#source_div_id').text();
    $('#target_div_id').text(data);
    
    // jQuery form value
    data = $('#source_form_id').val();
    $('#target_form_id').val(data);
    

Выполните повторный тест в обе стороны с такой строкой, чтобы убедиться, что она всегда выполняетсячерез весь HTML-> PHP-> DB-> PHP-> [Javascript ->] HTML-цикл каждый раз точно такой же:

&amp;ДЖäüöéè<script>…</script>™<i>bold</i>

Вот мой скрипт, который тестирует экранирование в разные стороны;ему, очевидно, нужна база данных, таблица с именем 'roundtrip' и столбцами 'id' и 'name', а также одна строка с id = 1, которую необходимо создать перед ее запуском:

<?php
$db = new PDO("mysql:host=$host;dbname=$dbname", $db_user, $db_password);
$stmt_insert = $db->prepare('
update
    roundtrip
set
    name = :name
where
    id = 1
');
$stmt_select = $db->prepare('
select
    name
from
    roundtrip
where
    id = 1
');
if ($_POST['do'] == 'edit') {
    $stmt_insert->execute(array('name' => $_POST['name']));
}
$stmt_select->execute();
while ($result = $stmt_select->fetch()) {
    $data = $result['name'];
}
?>
<!DOCTYPE html>
<html>
<head>
    <title>Roundtrip test</title>
    <script type="text/javascript" src="/js/jquery-1.7.1.min.js"></script>
    <script type="text/javascript">
        function copydiv() {
            // Non-jquery:
            //var source = document.getElementById('divdata');
            //var target = document.getElementById('copydiv');
            //if (typeof(source.textContent) != "undefined") {
            //    target.textContent = source.textContent;
            //} else {
            //    target.innerText = source.innerText;
            //}

            // jquery:
            $('#copydiv').text($('#divdata').text());
        }
        function copyform() {
            // Non-jquery:
            //var source = document.getElementById('formdata');
            //var target1 = document.getElementById('copyform1');
            //var target2 = document.getElementById('copyform2');
            //if (typeof(source.textContent) != "undefined") {
            //    target1.textContent = source.value;
            //} else {
            //    target1.innerText = source.value;
            //}
            //target2.value = source.value;

            // jquery:
            $('#copyform1').text($('#formdata').val());
            $('#copyform2').val($('#formdata').val());
        }
        function copyjson() {

            var data = <?php echo json_encode($data); ?>;

            // Non-jquery:
            //var target = document.getElementById('copyjson');
            //if (typeof(target.textContent) != "undefined") {
            //    target.textContent = data;
            //} else {
            //    target.innerText = data;
            //}

            // jquery:
            $('#copyjson').text(data);
        }
    </script>
</head>
<body>
    <div>Data: <span id="divdata"><?php echo htmlspecialchars($data); ?></span></div>
    <div>JS div copy: <span id="copydiv"/></div>
    <div>JS form copy: <span id="copyform1"/></div>
    <div>JSON copy: <span id="copyjson"/></div>
    <form method="POST">
        <input type="hidden" name="do" value="edit"/>
        <input type="text" name="name" id="formdata" value="<?php echo htmlspecialchars($data); ?>"/>
        <input type="text" id="copyform2"/>
        <input type="button" value="Copy div" onclick="copydiv();"/>
        <input type="button" value="Copy form" onclick="copyform();"/>
        <input type="button" value="Copy json" onclick="copyjson();"/>
        <input type="submit"/>
    </form>
</body>
</html>
0 голосов
/ 22 ноября 2014

OWASP имеет Шпаргалку по профилактике XSS , которая покрывает большую часть (все?) Того, что вы, похоже, ищете. Не обращается к PHP напрямую.

0 голосов
/ 19 июня 2011

Чтобы вставить экранированные объекты в MySQL-Database, используя PHP (и другие языки программирования), есть PreparedStatements .

Если вы хотите напрямую отобразить пользовательский ввод в поле div и экранировать ввод (так что я думаю, HTML-теги не интерпретируются), вы можете проверить Точка # 4 в этой статье или используйте Google.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...