JSP/Servlet Web 应用程序中的 XSS 预防

新手上路,请多包涵

如何防止 JSP/Servlet Web 应用程序中的 XSS 攻击?

原文由 newbie 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 823
2 个回答

通过使用 JSTL <c:out> 标记或 fn:escapeXml() EL 功能(重新)显示 用户控制的输入 时,可以在 JSP 中防止 XSS。这包括请求参数、标头、cookie、URL、正文等。您从请求对象中提取的任何内容。此外,存储在数据库中的先前请求的用户控制输入需要在重新显示期间进行转义。

例如:

 <p><c:out value="${bean.userControlledValue}"></p>
<p><input name="foo" value="${fn:escapeXml(param.foo)}"></p>

This will escape characters which may malform the rendered HTML such as < , > , " , ' and & into HTML/XML entities such as &lt; , &gt; , &quot; , &apos; and &amp; .

请注意,您不需要在 Java (Servlet) 代码中对它们进行转义,因为它们在那里是无害的。有些人可能会选择在 请求 处理期间(如您在 Servlet 或 Filter 中所做的那样)而不是 响应 处理(如您在 JSP 中所做的那样)转义它们,但这样您可能会冒数据被不必要地双重转义的风险(例如 & 变成 &amp;amp; 而不是 &amp; 最终用户会看到 &amp; 被呈现,或者当导出 DB-able 时变成不可移植的数据数据到 JSON、CSV、XLS、PDF 等根本不需要 HTML 转义)。您还将失去社交控制,因为您不再知道用户实际填写了什么。作为站点管理员,您真的很想知道哪些用户/IP 正在尝试执行 XSS,以便您可以轻松跟踪他们并采取相应的行动。在请求处理期间转义应该只作为最新的手段,当你真的需要在尽可能短的时间内修复一个开发不良的遗留 Web 应用程序的火车残骸时。不过,您最终应该重写您的 JSP 文件以使其成为 XSS 安全的。

如果您想将用户控制的输入重新显示为 HTML,其中您只想允许 HTML 标记的特定子集,例如 <b> , <i> , <u> 等,那么您需要通过白名单清理输入。为此,您可以使用像 Jsoup 这样的 HTML 解析器。但是,更好的方法是引入一种人性化的标记语言,例如 Markdown(也用于 Stack Overflow)。然后你可以为此使用像 CommonMark 这样的 Markdown 解析器。它还具有内置的 HTML 清理功能。另请参阅 Markdown 或 HTML

服务器端与数据库有关的唯一问题是 SQL 注入 预防。您需要确保永远不要直接在 SQL 或 JPQL 查询中对用户控制的输入进行字符串连接,并且始终使用参数化查询。在 JDBC 术语中,这意味着您应该使用 PreparedStatement 而不是 Statement 。在 JPA 术语中,使用 Query


另一种方法是从 JSP/Servlet 迁移到 Java EE 的 MVC 框架 JSF 。它在所有地方都内置了 XSS(和 CSRF!)预防。另请参阅 JSF 中的 CSRF、XSS 和 SQL 注入攻击预防

原文由 BalusC 发布,翻译遵循 CC BY-SA 4.0 许可协议

我很幸运在我所有的 Spring 控制器上使用 OWASP Anti-Samy 和 AspectJ 顾问来阻止 XSS 进入。

 public class UserInputSanitizer {

    private static Policy policy;
    private static AntiSamy antiSamy;

    private static AntiSamy getAntiSamy() throws PolicyException  {
        if (antiSamy == null) {
            policy = getPolicy("evocatus-default");
            antiSamy = new AntiSamy();
        }
        return antiSamy;

    }

    public static String sanitize(String input) {
        CleanResults cr;
        try {
            cr = getAntiSamy().scan(input, policy);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return cr.getCleanHTML();
    }

    private static Policy getPolicy(String name) throws PolicyException {
        Policy policy =
            Policy.getInstance(Policy.class.getResourceAsStream("/META-INF/antisamy/" + name + ".xml"));
        return policy;
    }

}

您可以从此 stackoverflow 帖子 获取 AspectJ 顾问

我认为这是一种比 c:out 更好的方法,特别是如果您使用大量 javascript。

原文由 Adam Gent 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题