代码之家  ›  专栏  ›  技术社区  ›  Keith

处理安全性和避免使用用户输入URL的XSS的最佳方法

  •  48
  • Keith  · 技术社区  · 16 年前

    我们有一个高安全性的应用程序,我们希望允许用户输入其他用户将看到的URL。

    这就带来了XSS黑客的高风险——用户可能会输入另一个用户最终执行的javascript。因为我们拥有敏感的数据,所以这是绝对不可能发生的。

    处理这个问题的最佳实践是什么?任何安全白名单或逃生模式都足够好吗?

    关于处理重定向的任何建议(例如,在跟踪链接之前,在警告页面上显示“此链接在我们的网站之外”)。

    是否存在根本不支持用户输入链接的参数?


    澄清:

    基本上我们的用户想要输入:

    stackoverflow.com网站

    并将其输出给另一个用户:

    <a href="http://stackoverflow.com">stackoverflow.com</a>
    

    我真正担心的是他们在XSS黑客中使用这个。即输入:

    警报(“黑客!”);

    所以其他用户得到这个链接:

    <a href="alert('hacked!');">stackoverflow.com</a>
    

    我的例子只是为了解释风险——我很清楚JavaScript和URL是不同的,但是通过让它们输入后者,它们可能能够执行前者。

    你会惊讶于你能用这个技巧破解多少网站——HTML更糟。如果他们知道处理链接,他们也知道要消毒吗? <iframe> , <img> 以及巧妙的CSS引用?

    我在一个高安全性的环境中工作——一个XSS黑客可能会给我们造成非常高的损失。我很高兴我能制作一个regex(或者使用到目前为止最好的建议之一),它可以排除我所能想到的一切,但这是否足够?

    9 回复  |  直到 6 年前
        1
  •  52
  •   Keith    8 年前

    如果您认为URL不能包含代码,请重新考虑!

    https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet

    读着读着,然后哭泣。

    下面是在堆栈溢出时的操作方法:

    /// <summary>
    /// returns "safe" URL, stripping anything outside normal charsets for URL
    /// </summary>
    public static string SanitizeUrl(string url)
    {
        return Regex.Replace(url, @"[^-A-Za-z0-9+&@#/%?=~_|!:,.;\(\)]", "");
    }
    
        2
  •  13
  •   Bell    16 年前

    将链接呈现为“安全”的过程应经历三个或四个步骤:

    • unescape/重新编码所给的字符串(rsnake在 http://ha.ckers.org/xss.html 使用转义和UTF编码)。
    • 清除链接:正则表达式是一个很好的开始-确保截断字符串,或者如果字符串中包含“(或用于关闭输出中属性的任何内容),则将其丢弃;如果只作为对其他信息的引用进行链接,则也可以在此过程结束时强制使用协议-如果第一个冒号之前的部分不是“http”或“https”,然后将“http://”附加到开头。这允许您从不完整的输入创建可用的链接,因为用户会在浏览器中键入内容,并为您提供最后一个机会,让您绊倒任何人试图潜入的恶作剧。
    • 检查结果是否为格式正确的URL(protocol://host.domain[:port][/path][[文件]][?queryfield=queryvalue][锚定])。
    • 可能根据网站黑名单检查结果,或者尝试通过某种恶意软件检查器获取结果。

    如果安全性是一个优先事项,我希望用户在这个过程中能够原谅一些偏执,即使它最终会丢弃一些安全链接。

        3
  •  8
  •   Dave Jarvis James Eichele    7 年前

    使用库,如owasp-esapi api:

    阅读以下内容:

    例如:

    $url = "http://stackoverflow.com"; // e.g., $_GET["user-homepage"];
    $esapi = new ESAPI( "/etc/php5/esapi/ESAPI.xml" ); // Modified copy of ESAPI.xml
    $sanitizer = ESAPI::getSanitizer();
    $sanitized_url = $sanitizer->getSanitizedURL( "user-homepage", $url );
    

    另一个例子是使用内置函数。PHP的 filter_var 函数就是一个例子:

    $url = "http://stackoverflow.com"; // e.g., $_GET["user-homepage"];
    $sanitized_url = filter_var($url, FILTER_SANITIZE_URL);
    

    使用 filter_var allows javascript调用,并筛选出既不是 http 也不 https . 使用 OWASP ESAPI Sanitizer 可能是最好的选择。

    还有一个例子是来自 WordPress :

    此外,由于无法知道URL链接的位置(即,它可能是一个有效的URL,但URL的内容可能是有害的),所以Google有一个 safe browsing 您可以调用的API:

    为了卫生而滚动自己的regex有几个问题:

    • 除非你是乔恩·斯基特,否则代码会有错误。
    • 现有的API背后有许多小时的审查和测试。
    • 现有的URL验证API考虑国际化。
    • 现有的API将与新出现的标准保持同步。

    其他需要考虑的问题:

    • 你允许什么计划 file:/// telnet:// 可接受的)?
    • 您希望对URL的内容设置哪些限制(是否接受恶意软件URL)?
        4
  •  3
  •   Patrick McElhaney    16 年前

    输出链接时只需htmlencode。确保你不允许 javascript: 链接。(最好有一个被接受的协议白名单,例如http、http s和mailto。)

        5
  •  3
  •   Brad Patton    12 年前

    如果您没有指定应用程序的语言,我将假定为ASP.NET,为此,您可以使用 Microsoft Anti-Cross Site Scripting Library

    它非常容易使用,您所需要的只是一个include,即它:)

    当你在讨论这个话题时,为什么不读一下 Design Guidelines for Secure Web Applications

    如果有其他语言……如果有一个用于ASP.NET的库,那么它也必须可用于其他类型的语言(PHP、Python、ROR等)。

        6
  •  1
  •   Community CDub    8 年前

    不把它们显示为链接怎么样?只需使用文本。

    再加上一个警告,以你自己的风险继续下去可能就足够了。

    附加 -也见 Should I sanitize HTML markup for a hosted CMS? 有关清理用户输入的讨论

        7
  •  0
  •   jcubic    6 年前

    在用javascript编写的项目中,我使用这个regex作为白名单:

     url.match(/^((https?|ftp):\/\/|\.{0,2}\/)/)
    

    唯一的限制是,对于同一目录中的文件,您需要将./放在前面,但我认为我可以接受。

        8
  •  -1
  •   Shashi    12 年前

    可以使用十六进制代码转换整个URL并将其发送到服务器。这样,客户就无法理解第一眼看到的内容。读取内容后,您可以解码内容url=?并发送到浏览器。

        9
  •  -7
  •   Nick Stinemates    16 年前

    允许URL和允许JavaScript是两个不同的东西。