广泛的概述,关于转义用户提交的html,javascript和PHP内容的流程图

时间:2011-06-18 22:17:02

标签: php javascript mysql html escaping

有人能指出我的好StackOverflow答案和其他资源,包括书籍,以逃避用户提交的HTML,JavaScript和PHP内容吗?

例如,假设用户在文本框中键入信息,然后单击提交按钮。然后,文本由JavaScript写入页面上的div,并通过GET发送到PHP,并通过PHP放入MySQL数据库。

我正在寻找一个好的,广泛的,但也详细的概述所涉及的所有不同类型的逃逸。流程图也有帮助!

谢谢!


谢谢!我正在寻找一个像cheatsheet一样制作的人,其中包括1)转义为html显示,2)转义为放入URL 3),将URL发送到PHP,4)将数据从URL插入数据库。每个部分都应该有1)关于潜在问题情况和应该转义的字符的示例,2)如何转义字符的示例,以及3)如果以后必要时如何解码字符。

这样做的好处是一站式资源,其中包含许多关于转义的示例和解决方案,以便其他用户无需经历大量不同的网站和答案以及几乎没有示例和解决方案的资源。我认为这会很棒。


到目前为止,这张图表看起来还不错 http://www.the-art-of-web.com/javascript/escape/

3 个答案:

答案 0 :(得分:2)

我自己总是使用“POST”来获取用户数据,而不是“GET”,以下讨论反映了这一点,但无论如何,你仍然可以使用我所说的约90%。所以这里......

一般规则:在转义数据时不要“提前考虑”。只做必要的立即改造。典型示例:在进行数据库插入时不要为HTML转义,因为你最终会得到'&'变成'& amp; amp;'经过几次往返旅行。

一般规则:始终使用UTF-8。第一次有人通过其中包含unicode省略号的电子邮件进行复制粘贴时,您会感激不尽。 (你会惊讶地发生这种情况。)需要的典型设置;这可能因PHP / MySQL / HTML版本而异:

  • PHP:php_value default_charset“UTF-8”
  • MySQL:创建数据库时选择utf8。
  • HTML:< meta http-equiv =“Content-type”content =“text / html; charset = UTF-8”/>

一般规则:只有五个地方可以使用未经过规范化(尽管已正确转义)的用户数据:

  • (正确类型化)数据库字段的值(即UTF-8文本字段或blob字段)。
  • PHP变量的值。
  • Javascript变量的值。
  • HTML表单元素的'value'属性的值。
  • HTML元素的textNode子项的内容。

如果您想将用户数据放在任何其他位置,则必须对其进行清理。这超出了问题的范围,但在典型情况下,您可以使用正则表达式将任何非ASCII字母或数字替换为下划线。如果唯一性很重要,例如文件名或HTML“id”属性,则必须进行额外的工作以确保已清理的名称是唯一的(例如,确保在'a ^ b'和'a&'时发生冲突;''被清理为'a_b'被解决)。典型的解决方案类似于:

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

最后,我回答的内容:特定的转义函数用于将数据移入和移出未经修改的用户数据的五个特殊地点:

  • 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变量 - &gt; HTML textNode或表单值:htmlspecialchars:

    <div><?php echo htmlspecialchars(data); ?></div>
    <input type="text" name="name" value="<?php echo htmlspecialchars(data); ?>"/>
    
  • Javascript&lt; - &gt; HTML textNode或表单值:Browser的内置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-&gt; PHP-&gt; DB-&gt; PHP-&gt; [Javascript-&gt;] 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>

答案 1 :(得分:0)

要使用PHP(和其他编程语言)在MySQL数据库中插入转义内容,有PreparedStatements

如果您想直接在div框中显示用户输入并转义输入(以便我不想解释HTML-Tags),您可以查看Point #4 in this article或使用Google。

答案 2 :(得分:0)

OWASP有一个XSS Prevention Cheat Sheet,涵盖了你似乎正在寻找的大部分(全部?)。不直接解决PHP。