如何使用HTML / PHP预防XSS?

如何使用仅使用HTML和PHP来防止XSS(跨站点脚本)?

I’ve seen numerous other posts on this topic but I have not found an article that clear and concisely states how to actually prevent XSS.

回答 9

  1. 赞同 330

    基本你需要使用该函数htmlspecialchars()无论何时要将某些东西输出到来自用户输入的浏览器。

    使用此功能的正确方法是这样的:

    echo htmlspecialchars($string, ENT_QUOTES, 'UTF-8');
    

    Google Code University还在Web安全上拥有这些非常教育视频:

    Alix Axel
    @ timtim:大多数情况下,是的。但是,当您需要允许HTML输入的情况时,如果是这样的情况,我建议您使用类似的东西htmlpurifier.org.Alix Axel
    @ Alix Axel,你的答案是使用HTMLSpecialChars或使用htmlpurifier.org.Timtim
    如果需要接受HTML输入,请使用HTML净化器,如果不使用htmlspecialchars().Alix Axel
    htmlspecialchars或htmlentities?检查这里stackoverflow.com/questions/46483/...Kiranvj
    尽管如此,它是正确的,但它并不像那么简单。您应该考虑将不受信任的字符串放入HTML,JS,CSS,并考虑将不受信任的HTML放入HTML中。看这个 :owasp.org/index.php/...堡垒男人
  2. 赞同 19

    最重要的步骤是在处理和/或呈现回浏览器之前消除任何用户输入。 PHP有一些“Filter.“可以使用的功能。

    XSS攻击通常具有的形式是将链接插入到包含对用户的恶意意图的某些异地JavaScript的链接。阅读更多关于它的信息here.

    You'll also want to test your site - 我可以推荐Firefox Add-on [XSS Me].看起来像AERY XS is now the way to go.

    James Kolpack
    我需要确保我完全从中消毒输入。有一个特定的字符/字符串,我要注意吗?Timtim
    @ timtim - 没有。所有用户输入应该Always.被认为是本质上的敌对。Zombat
    基础,内部数据(员工,Sysadmin等)可能是不安全的。您应该识别和监视(使用日志日期和用户)数据以解释显示。Samuel Dauzon
  3. 赞同 15

    从脱机的所以文档测试版中发布这一点作为综合参考。

    Problem

    Cross-Site Scripting是Web客户端的意外执行远程代码。如果它从用户输入并直接在网页上将其输出,则任何Web应用程序都可能将其自身暴露为XSS。如果输入包括HTML或JavaScript,则在Web客户端呈现此内容时,可以执行远程代码。

    例如,如果第三方包含JavaScript文件:

    // http://example.com/runme.js
    document.write("I'm running");
    

    将PHP应用程序直接输出传递到其中的字符串:

    <?php
    echo '<div>' . $_GET['input'] . '</div>';
    

    If an unchecked GET parameter contains <script src="http://example.com/runme.js"></script>然后PHP脚本的输出将是:

    <div><script src="http://example.com/runme.js"></script></div>
    

    第三方JavaScript将运行,用户将在网页上看到“我正在运行”。

    果实

    常规规则,从不信任来自客户的输入。每个GET参数,帖子或PUT内容以及Cookie值都可以是任何内容,因此应该验证。输出任何这些值时,转发它们,以便不会以意想不到的方式进行评估。

    Keep in mind that even in the simplest applications data can be moved around and it will be hard to keep track of all sources. Therefore it is a best practice to Always. escape output.

    PHP提供了几种方法来逃脱输出,具体取决于上下文。

    Filter职能

    phps过滤器功能允许输入数据到PHP脚本杀菌.优秀的方式.它们在保存或输出客户端输入时非常有用。

    HTML编码

    htmlspecialchars将任何“HTML特殊字符”转换为HTML编码,这意味着它们会没有以标准的HTML处理。要使用此方法修复前面的示例:

    <?php
    echo '<div>' . htmlspecialchars($_GET['input']) . '</div>';
    // or
    echo '<div>' . filter_input(INPUT_GET, 'input', FILTER_SANITIZE_SPECIAL_CHARS) . '</div>';
    

    应输出:

    <div>&lt;script src=&quot;http://example.com/runme.js&quot;&gt;&lt;/script&gt;</div>
    

    在里面的一切<div>遗嘱没有BE通过浏览器解释为JavaScript标记,而是作为一个简单的文本节点。用户将安全看到:

    <script src="http://example.com/runme.js"></script>
    

    url编码

    输出动态生成的URL时,PHP提供了urlencode安全地输出有效URL的功能。因此,例如,如果用户能够输入已成为另一个Get参数的一部分的数据:

    <?php
    $input = urlencode($_GET['input']);
    // or
    $input = filter_input(INPUT_GET, 'input', FILTER_SANITIZE_URL);
    echo '<a href="http://example.com/page?input="' . $input . '">Link</a>';
    

    Any恶意输入将转换为编码的URL参数。

    使用专门的外部图书馆或OWASP ANTISAMY列表

    您想要发送HTML或其他类型的代码输入。您需要维护授权单词(白色列表)和未授权(黑名单)列表。

    您可以下载标准列表owasp Anti isamy网站.每个列表适用于特定类型的交互(eBay API,TINYCE等)。它是开源的。

    有用于过滤HTML的图书馆,并防止XSS攻击常规案例,至少以及易于使用的抗血清列表,非常容易使用。例如,你有html净化器

    Matt S
  4. 赞同 12

    偏好的顺序:

    1. 如果您使用的是模板引擎(例如,树枝,Smarty,Blade),请检查它提供上下文敏感的逃逸。我从树枝的经验中知道。{{ var|e('html_attr') }}
    2. If you want to allow HTML, use html净化器.即使您认为您只接受Markdown或RictructUriveText,您仍然希望将HTML净化这些标记语言输出。
    3. Otherwise, use htmlentities($var, ENT_QUOTES | ENT_HTML5, $charset)确保其余文档使用相同的字符集$charset.在大多数情况下,'UTF-8'所需的字符集。

    Also,确保你Ecape在输出上,没有输入.

    Scott Arciszewski
    is this comment still valid Escape输出,没有输入?您认为输入是否可以恶意考虑在应用程序堆栈中处理它们的多种技术?LAKSHMINARAYANAN GUPTHA
    它仍然有效。您应该在显示时存储它,然后在显示时逃生。如果您需要更新您的输出转义代码以减轻漏洞,则更好地存储未存储的未处理输入以更新您的单元测试。Scott Arciszewski
  5. 赞同 11

    Many Frameworks帮助以各种方式处理XSS。滚动自己或如果有一些XSS关注,我们可以利用Filter_Input_Array.(可在PHP 5> = 5.2.0,PHP 7中提供。以这种方式,所有用户输入都会在1个中央位置进行消毒。If this is done at the beginning of a project or before your database is poisoned, you shouldn't have any issues at time of output...stops garbage in, garbage out.

    /* Prevent XSS input */
    $_GET   = filter_input_array(INPUT_GET, FILTER_SANITIZE_STRING);
    $_POST  = filter_input_array(INPUT_POST, FILTER_SANITIZE_STRING);
    /* I prefer not to use $_REQUEST...but for those who do: */
    $_REQUEST = (array)$_POST + (array)$_GET + (array)$_REQUEST;
    

    The above will remove ALLhtml和脚本标记。如果您需要一个允许安全标签的解决方案,请根据白名单,退房HTML净化器.


    If your database is already poisoned or you want to deal with XSS at time of output, owasp.Recommends为自定义包装函数创建echo,并在所有输出用户提供的值的地方使用它:

    //xss mitigation functions
    function xssafe($data,$encoding='UTF-8')
    {
       return htmlspecialchars($data,ENT_QUOTES | ENT_HTML401,$encoding);
    }
    function xecho($data)
    {
       echo xssafe($data);
    }
    

    Webaholik
  6. 赞同 4

    <?php
    function xss_clean($data)
    {
    // Fix &entity\n;
    $data = str_replace(array('&amp;','&lt;','&gt;'), array('&amp;amp;','&amp;lt;','&amp;gt;'), $data);
    $data = preg_replace('/(&#*\w+)[\x00-\x20]+;/u', '$1;', $data);
    $data = preg_replace('/(&#x*[0-9A-F]+);*/iu', '$1;', $data);
    $data = html_entity_decode($data, ENT_COMPAT, 'UTF-8');
    
    // Remove any attribute starting with "on" or xmlns
    $data = preg_replace('#(<[^>]+?[\x00-\x20"\'])(?:on|xmlns)[^>]*+>#iu', '$1>', $data);
    
    // Remove javascript: and vbscript: protocols
    $data = preg_replace('#([a-z]*)[\x00-\x20]*=[\x00-\x20]*([`\'"]*)[\x00-\x20]*j[\x00-\x20]*a[\x00-\x20]*v[\x00-\x20]*a[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2nojavascript...', $data);
    $data = preg_replace('#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*v[\x00-\x20]*b[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2novbscript...', $data);
    $data = preg_replace('#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*-moz-binding[\x00-\x20]*:#u', '$1=$2nomozbinding...', $data);
    
    // Only works in IE: <span style="width: expression(alert('Ping!'));"></span>
    $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?expression[\x00-\x20]*\([^>]*+>#i', '$1>', $data);
    $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?behaviour[\x00-\x20]*\([^>]*+>#i', '$1>', $data);
    $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:*[^>]*+>#iu', '$1>', $data);
    
    // Remove namespaced elements (we do not need them)
    $data = preg_replace('#</*\w+:\w[^>]*+>#i', '', $data);
    
    do
    {
        // Remove really unwanted tags
        $old_data = $data;
        $data = preg_replace('#</*(?:applet|b(?:ase|gsound|link)|embed|frame(?:set)?|i(?:frame|layer)|l(?:ayer|ink)|meta|object|s(?:cript|tyle)|title|xml)[^>]*+>#i', '', $data);
    }
    while ($old_data !== $data);
    
    // we are done...
    return $data;
    }
    

    abdo-host
    You shouldn't use preg_replace as it uses eval您的输入。owasp.org/index.php/php_security_cheat_sheet#code_inepling.Crablab
  7. 赞同 3

    您还能够通过以下方式设置一些XSS相关的HTTP响应头header(...)

    x-xss-protection“1; mode =块”

    可以确保,启用浏览器XSS保护模式。

    Content-Security-Policy“Default-SRC”Self'; ......“

    启用浏览器侧内容安全性。查看此用于内容安全策略(CSP)详细信息:http://content-security-policy.com/截止到块内联脚本和外部脚本源的议员对XSS有用。

    对于有关WebApp的安全性的一系列有用的HTTP响应标题,请查看OWASP:https://www.owasp.org/index.php/list_of_useful_http_headers.

    CHRIS
  8. 赞同 -1

    Use htmlspecialcharsPHP.在HTML上尝试避免使用:

    element.innerHTML = “…”; element.outerHTML = “…”; document.write(…); document.writeln(…);

    varIS.由用户控制.

    Also显然尝试避免eval(var)如果你必须使用任何一个然后尝试JS. escaping them, html.Escape他们,你可能必须做一些但是对于基础而言,这应该足够了。

    Pablo
  9. 赞同 -1

    The best way to protect your input it's use htmlentitiesFunction。例子:

    htmlentities($target, ENT_QUOTES, 'UTF-8');
    

    You can get more information .

    Marco Concas