55

我有一个基于 JSF 的 Web 应用程序,其中 MySQL 作为数据库。我已经在我的应用程序中实现了防止 CSRF 的代码。

现在由于我的底层框架是 JSF,我想我不必处理 XSS 攻击,因为它已经由UIComponent. 我没有在任何视图页面中使用任何 JavaScript。即使我使用我真的需要实现代码来防止 XSS 攻击吗?

对于 DB,我们在所有 DB 交互中使用准备好的语句和存储过程。

为了防止这 3 种常见的攻击,是否还需要处理其他任何事情?我已经浏览过OWASP网站和他们的备忘单

我是否需要处理任何其他潜在的攻击媒介?

4

3 回答 3

118

跨站脚本

JSF 旨在具有内置的 XSS 预防。您可以使用任何 JSF 组件安全地重新显示所有用户控制的输入(请求标头(包括 cookie!)、请求参数(也保存在 DB 中的参数!)和请求正文(上传的文本文件等))。

<h:outputText value="#{user.name}" />
<h:outputText value="#{user.name}" escape="true" />
<h:inputText value="#{user.name}" />
etc...

请注意,当您在 Facelets 上使用 JSF 2.0 时,您可以在模板文本中使用 EL,如下所示:

<p>Welcome, #{user.name}</p>

这也将被隐式转义。你不一定需要<h:outputText>这里。

当您使用以下命令明确转义用户控制的输入时escape="false"

<h:outputText value="#{user.name}" escape="false" />

那么你就有了一个潜在的 XSS 攻击漏洞!

如果您想将用户控制的输入重新显示为 HTML,其中您希望只允许 HTML 标记的特定子集,如<b><i><u>等,那么您需要通过白名单来清理输入。HTML 解析器Jsoup在这方面非常有帮助

itemLabelEscapedMojarra < 2.2.6 中的错误

2.2.6 之前的旧 Mojarra 版本存在错误,提供<f:selectItems itemLabel>via 而不是或作为值时,错误地呈现未转义的List<T>标签<f:selectItems var>List<SelectItem>问题SelectItem[]3143 。换句话说,如果您通过 a 将用户控制的数据重新显示为项目标签List<T>,那么您就有一个潜在的 XSS 漏洞。如果升级到至少 Mojarra 2.2.6 不是一个选项,那么您需要显式设置itemLabelEscaped属性true来防止这种情况发生。

<f:selectItems value="#{bean.entities}" var="entity" itemValue="#{entity}"
    itemLabel="#{entity.someUserControlledProperty}" itemLabelEscaped="true" />

CSRF

JSF 2.x 已经javax.faces.ViewState在使用服务器端状态保存时在表单中的隐藏字段的风格中内置了 CSRF 预防。在 JSF 1.x 中,这个值非常弱且太容易预测(它实际上从未打算用作 CSRF 预防)。在 JSF 2.0 中,这已通过使用长而强的自动生成值而不是相当可预测的序列值来改进,从而使其成为一种强大的 CSRF 预防措施。

在 JSF 2.2 中,这甚至通过使其成为 JSF 规范的必需部分以及用于加密客户端状态的可配置 AES 密钥来进一步改进,以防启用客户端状态保存。另请参阅JSF 规范问题 869Reusing ViewState value in other session (CSRF)。JSF 2.2 中的新功能是对 GET 请求的 CSRF 保护<protected-views>

只有当您使用无状态视图时<f:view transient="true">,或者应用程序中存在 XSS 攻击漏洞时,您才有潜在的 CSRF 攻击漏洞。


SQL注入

这不是 JSF 的责任。如何防止这种情况取决于您使用的持久性 API(原始 JDBC、现代 JPA 或好的 ol'Hibernate),但归根结底,您永远不应该像这样将用户控制的输入连接到 SQL 字符串中

String sql = "SELECT * FROM user WHERE username = '" + username + "' AND password = md5(" + password + ")";
String jpql = "SELECT u FROM User u WHERE u.username = '" + username + "' AND u.password = md5('" + password + "')";

想象一下如果最终用户选择以下名称会发生​​什么:

x'; DROP TABLE user; --

您应该始终在适用的情况下使用参数化查询。

String sql = "SELECT * FROM user WHERE username = ? AND password = md5(?)";
String jpql = "SELECT u FROM User u WHERE u.username = ?1 AND u.password = md5(?2)";

在普通的 JDBC 中,您需要使用PreparedStatement来填充参数值,而在 JPA(和 Hibernate)中,该Query对象也为此提供了 setter。

于 2011-10-11T11:57:12.033 回答
8

我没有在任何视图页面中使用任何 JavaScript。即使我使用 do 我真的需要实现代码来绕过 XSS 攻击。

即使您的页面中没有使用 JavaScript,您也可能容易受到 XSS 攻击。当您在没有正确编码的情况下合并由攻击者控制的内容时,就会发生 XSS。

任何时候你做类似的事情

response.write("<b>" + x + "</b>")

如果攻击者可能导致x包含包含 JavaScript 的 HTML,那么您很容易受到 XSS 的攻击。

解决方案通常是不要编写大量代码。通常,解决方案是对$x攻击者控制的任何其他值进行编码,然后再将它们包含在您生成的 HTML 中。

response.write("<b>" + escapePlainTextToHtml(x) + "</b>")

过滤或清理输入可以帮助提供额外的保护层。

<shameless-plug>

您还可以使用自动编码输出的模板语言来防止 XSS。

闭包模板是 Java 的此类选项之一。

上下文自动转义通过增加闭包模板来根据其出现的上下文正确编码每个动态值,从而防御攻击者控制的值中的 XSS 漏洞。

编辑

由于您使用的是 JSF,因此您应该阅读 JSF 中的XSS 缓解措施

转义输出文本

<h:outputText/>并且<h:outputLabel/>默认情况下将转义属性设置为 True。通过使用此标签显示输出,您可以缓解大部分 XSS 漏洞。

SeamT​​extParser 和<s:formattedText/>

如果您想允许用户使用一些基本的 html 标签来自定义他们的输入,JBoss Seam 提供了一个<s:formattedText/>标签,允许用户指定一些基本的 html 标签和样式。

于 2011-10-11T06:44:24.207 回答
1

当使用<h:outputText escape="false">未转义的值(例如来自 html 文本编辑器)时,您可能会受到讨厌的 XSS 攻击。在这种情况下,我使用了一个 JSF 转换器,它使用 Jsoup 从文本中删除 javascript,使 HTML 保持不变。转换器也可用于清理用户输入。你可以像这样使用它:

<h:outputText value="{bean.value}" escape="false" converter="htmlSanitizingConverter"/>

和转换器本身:

/**
 * Prevents from XSS attack if output text is not escaped.
 */
@FacesConverter("htmlSanitizingConverter")
public class HtmlSanitizingConverter implements Converter {

    private static final Whitelist JSOUP_WHITELIST = Whitelist.relaxed()
            .preserveRelativeLinks(true)
            .addAttributes(":all","style");
            /*
             Optionally - add support for hyperlinks and base64 encoded images.
            .addTags("img")
            .addAttributes("img", "height", "src", "width")
            .addAttributes("a", "href")
            .addProtocols("img", "src", "http", "https", "data");
            */

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String submittedValue) {
        return (submittedValue != null) ? Jsoup.clean(submittedValue, JSOUP_WHITELIST) : null;
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value) {
        return (value != null) ? Jsoup.clean(value.toString(), JSOUP_WHITELIST) : "";
    }

}

注意:当您将 JSF 与 PrimeFaces 一起使用时,请注意<p:textEditor>-默认情况下,旧版本(6.2 之前的版本)不会清理用户输入。

于 2019-09-27T08:42:02.853 回答