关于将用户提交的内容转义为 html、javascript 和 PHP 的概述、流程图

发布于 2024-11-16 06:10:59 字数 673 浏览 1 评论 0原文

任何人都可以向我指出有关将用户提交的内容转义为 HTML、JavaScript 和 PHP 的 StackOverflow 良好答案和其他资源(包括书籍)吗?

例如,假设用户在文本框中键入信息,然后单击提交按钮。然后文本由 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/逃逸/

can anyone point me to good StackOverflow answers and other resources, including books, on escaping user submitted content for HTML, JavaScript, and PHP?

For example, say a user types information in a text box, and clicks a submit button. Then the text is written by JavaScript into a div on the page, and is also sent via GET to PHP, and by PHP is put into a MySQL database.

I am looking for a good, broad, but also detailed overview all the different types of escaping involved. A flowchart would help too!

Thanks!


Thanks! I'm looking for someone to make like a cheatsheet, with sections on 1) escaping for html display, 2) escaping for putting in a URL 3), sending the URL to PHP, 4) inserting data from the URL into a database. Each section should have 1) examples on potential problematic situations and characters that should be escaped, 2) examples on how to escape the characters, and 3) how to decode the characters if necessary later.

The benefit would be a one-stop source with many examples and solutions on escaping so that other users don't have to go through tons of different sites and answers and resources which have few examples and solutions. I think it would be great.


This chart looks pretty good so far
http://www.the-art-of-web.com/javascript/escape/

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

不再见 2024-11-23 06:10:59

我自己总是对用户数据使用“POST”,而不是“GET”,下面的讨论反映了这一点,但无论哪种方式,您仍然可以使用我下面所说的大约 90%。所以这里是......

一般规则:在转义数据时不要“提前思考”。只进行立即必要的转变。规范示例:在执行数据库插入时不要转义为 HTML,因为您最终会得到“&”等内容变成“&”经过几次往返之后。

一般规则:始终使用 UTF-8。当有人第一次从包含 unicode 省略号的电子邮件中进行复制粘贴时,您会对此表示感谢。 (您会惊讶于这种情况发生的频率。)所需的典型设置;这可能因 PHP/MySQL/HTML 版本而异:

  • PHP: php_value default_charset "UTF-8"
  • MySQL: 创建数据库时选择 utf8。
  • HTML:

一般规则:未经清理(尽管正确转义)的用户数据只能进入五个位置:(

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

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

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

最后,我的回答的要点是:用于将数据移入和移出未修改的用户数据可以移动的五个特殊位置的特定转义函数:

  • HTML 表单值属性 -> PHP $_POST 变量:无需转义。
  • PHP 变量 ->数据库字段:PDO 准备语句:

    $stmt = $db->prepare('插入往返 (id, name) 值 (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'])); // 用户数据需要转义。
    while ($result = $stmt->fetch()) {
        回显$结果['名称']; // 数据库结果没有。
    }
    
  • PHP 变量 -> JavaScript 变量:json_encode:

    var data = ;
    
  • PHP 变量 -> HTML textNode 或表单值:htmlspecialchars:

  • Javascript <-> HTML textNode 或表单值:浏览器内置的textNode 和.value 属性/函数:

    data = source_div.textContent; // 火狐浏览器
    数据 = source_div.innerText; // 其他浏览器
    target_div.textContent = 数据; // 火狐浏览器
    target_div.innerText = 数据; // 其他浏览器
    
    // 往返表单元素。
    数据 = source_form.value;
    target_form.value = 数据;
    
    // 附加到元素。
    target_div.appendChild(document.createTextNode(data)); // 所有浏览器
    
    // jQuery 文本节点
    数据 = $('#source_div_id').text();
    $('#target_div_id').text(数据);
    
    // jQuery 表单值
    数据 = $('#source_form_id').val();
    $('#target_form_id').val(数据);
    

使用这样的字符串进行重复的往返测试,以确保它始终遍历整个 HTML->PHP->DB-> ;PHP->[Javascript->]HTML 每次循环都完全相同:

&ДЖäüöéè<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>

I'd always use "POST" for user data myself, not "GET", and the following discussion reflects that, but you'll still be able to use about 90% of what I say below either way. So here goes...

General rule: Don't "think ahead" when escaping data. Only make the immediately necessary transformation. Canonical example: Don't escape for HTML when doing a database insertion, since you'll end up with, for example, '&' turning into '&amp;' after a couple of round trips.

General rule: Use UTF-8 throughout. You'll be thankful for this the first time someone does a copy-paste from an email that has a unicode ellipsis in it. (You'd be surprised how often that happens.) Typical settings needed; this may vary with PHP/MySQL/HTML version:

  • PHP: php_value default_charset "UTF-8"
  • MySQL: Choose utf8 when creating the database.
  • HTML: <meta http-equiv="Content-type" content="text/html;charset=UTF-8"/>

General rule: There are only five places that unsanitized (though properly escaped) user data can go:

  • The value of a (properly-typed) database field (i.e. a UTF-8 text field or blob field).
  • The value of a PHP variable.
  • The value of a Javascript variable.
  • The value of an HTML form element's 'value' attribute.
  • The content of an HTML element's textNode child.

If you want to put user data in any other place, it must be sanitized. This is beyond the scope of the question, but in a typical case you might use a regular expression to replace anything that isn't an ASCII letter or number with an underscore. In cases where uniqueness matters, like a filename or an HTML 'id' attribute, additional work has to be done to make sure that the sanitized names are unique (e.g. make sure that the clash that happens when'a^b' and 'a&b' are both sanitized to 'a_b' is resolved). A typical solution looks something like:

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

And, finally, the meat of my response: The specific escape functions to use to move data to and from those Five Special Places where unmodified user data can go:

  • HTML form value attribute -> PHP $_POST variable: No escaping necessary.
  • PHP variable -> database field: PDO prepared statement:

    $stmt = $db->prepare('insert into roundtrip (id, name) values (NULL, :data)');
    $stmt->execute(array('data' => $_POST['name']));
    
  • Database field -> PHP variable: No escaping necessary, but use PDO prepared statement to escape query values:

    $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 variable -> Javascript variable: json_encode:

    var data = <?php echo json_encode(data); ?>;
    
  • PHP variable -> HTML textNode or form value: htmlspecialchars:

    <div><?php echo htmlspecialchars(data); ?></div>
    <input type="text" name="name" value="<?php echo htmlspecialchars(data); ?>"/>
    
  • Javascript <-> HTML textNode or form value: Browser's built-in textNode and .value attributes/functions:

    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);
    

Do a repeated round-trip test with a string like this to make sure it always goes through the whole HTML->PHP->DB->PHP->[Javascript->]HTML cycle exactly the same every time:

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

Here's my script that tests escaping every which way; it obviously needs a database, a table with name 'roundtrip' and columns 'id' and 'name', and single row with id=1 to be created before running it:

<?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>
浮云落日 2024-11-23 06:10:59

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

如果您想直接在 div 框中显示用户输入并转义输入(我猜这样 HTML 标签不会被解释),您可以检查 本文中的第 4 点 或使用 Google。

To insert escaped things in a MySQL-Database using PHP (and other programming languages), there are the PreparedStatements.

If you want to directly display the users input in a div box and escape the input (so that HTML-Tags aren't interpreted i guess), you can check Point #4 in this article or use Google.

回眸一笑 2024-11-23 06:10:59

OWASP 有一个 XSS 预防备忘单,涵盖了大部分(全部? )您似乎正在寻找的内容。不直接处理 PHP。

OWASP has an XSS Prevention Cheat Sheet which covers most (all?) of what you seem to be looking for. Does not address PHP directly.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文