首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Autobean和XSS问题

Autobean和XSS问题
EN

Stack Overflow用户
提问于 2012-05-03 09:52:40
回答 1查看 1.2K关注 0票数 1

后端有一个Spring应用程序,前端有一个GWT应用程序。当用户登录时,‘index.jsp’将以javascript变量的形式输出用户信息。

我使用AutoBeanFactory作为json对用户信息进行编码和解码。

由于用户可以注册,并且用户信息存储在数据库中,所以我试图通过在JSP页面中转义用户信息来遵循OWASP防止备忘单

我正在使用esapi库进行编码。服务器端代码如下所示:

代码语言:javascript
复制
public static String serializeUserToJson(CustomUser user) {
        String json;
        AppUserProxy appUserProxy = appUserFactory.appuser().as();
        appUserProxy.setFirstname(encoder.encodeForHTML(user.getFirstname()));
        appUserProxy.setLastname(encoder.encodeForHTML(user.getLastname()));
        AutoBean<AppUserProxy> bean = appUserFactory.appuser(appUserProxy);
        json = AutoBeanCodex.encode(bean).getPayload();
        return json;
    }

我试着使用encodeForHTMLencodeForJavaScript()。对于普通字符来说,这很好,但是,一旦我使用Umlaute字符(ü,接合),我就会遇到问题。

如果我使用encodeforHTML()函数,javascript变量看起来如下(注意,名字有一个ü):

代码语言:javascript
复制
var data = {'user':'{"email":"john.doe&#x40;gmail.com","lastname":"Doe","firstname":"&Uuml;ber"}'};

使用Autobean解码很好,但是字符ü没有正确地显示,但是HTML转义一个(&Uuml;ber)。

当我使用encodeForJavaScript()函数时,输出如下:

代码语言:javascript
复制
var data = {'user':'{"email":"john.doe&#x40;gmail.com","lastname":"Doe","firstname":"\\xDCber"}'};

当我试图解码JSON字符串时,会遇到一个奇怪的问题。在开发模式/主机模式解码工作良好,并正确地显示Umlaut。然而,当我在生产模式下运行代码时,我就得到了一个未提及的异常:

代码语言:javascript
复制
java.lang.IllegalArgumentException: Error parsing JSON: SyntaxError: Unexpected token x
{"email":"john.doe&#x40;gmail.com","lastname":"Doe","firstname":"\xDCber"}
    at Unknown.java_lang_RuntimeException_RuntimeException__Ljava_lang_String_2V(Unknown Source)
    at Unknown.java_lang_IllegalArgumentException_IllegalArgumentException__Ljava_lang_String_2V(Unknown Source)
    at Unknown.com_google_gwt_core_client_JsonUtils_throwIllegalArgumentException__Ljava_lang_String_2Ljava_lang_String_2V(Unknown Source)
    at Unknown.com_google_gwt_core_client_JsonUtils_safeEval__Ljava_lang_String_2Lcom_google_gwt_core_client_JavaScriptObject_2(Unknown Source)
    at Unknown.com_google_web_bindery_autobean_shared_impl_StringQuoter_split__Ljava_lang_String_2Lcom_google_web_bindery_autobean_shared_Splittable_2(Unknown Source)
    at Unknown.com_google_web_bindery_autobean_shared_AutoBeanCodex_decode__Lcom_google_web_bindery_autobean_shared_AutoBeanFactory_2Ljava_lang_Class_2Ljava_lang_String_2Lcom_google_web_bindery_autobean_shared_AutoBean_2(Unknown Source)
    at Unknown.com_gmi_nordborglab_browser_client_mvp_main_UserInfoPresenter_onBind__V(Unknown Source)

我可以想到以下解决办法:

  1. 仅依赖于输入验证(当数据存储在db中时)并删除输出编码。但这不是推荐的方法。
  2. 用普通的ASCII字符(ü=> ue)替换Umlaute,并继续使用输出编码。
  3. 使用一些库,它可以转义XSS字符,但不使用Umlaute。

我很感谢你的反馈

更新:根据托马斯的建议,我现在从JSNI传递一个JsoSplittable,然后将它传递给AutoBeanCodex.decode函数。它在生产模式中工作得很好,但是在托管模式下,我得到了以下NPE:

代码语言:javascript
复制
java.lang.NullPointerException: null
    at com.google.gwt.dev.shell.CompilingClassLoader$MyInstanceMethodOracle.findOriginalDeclaringClass(CompilingClassLoader.java:428)
    at com.google.gwt.dev.shell.rewrite.WriteJsoImpl.isObjectMethod(WriteJsoImpl.java:307)
    at com.google.gwt.dev.shell.rewrite.WriteJsoImpl.visitMethod(WriteJsoImpl.java:289)
    at com.google.gwt.dev.shell.rewrite.WriteJsoImpl$ForJsoInterface.visitMethod(WriteJsoImpl.java:228)
    at com.google.gwt.dev.asm.ClassAdapter.visitMethod(ClassAdapter.java:115)
    at com.google.gwt.dev.shell.rewrite.RewriteJsniMethods.visitMethod(RewriteJsniMethods.java:350)
    at com.google.gwt.dev.asm.ClassReader.accept(ClassReader.java:774)
    at com.google.gwt.dev.asm.ClassReader.accept(ClassReader.java:420)
    at com.google.gwt.dev.shell.rewrite.HostedModeClassRewriter.rewrite(HostedModeClassRewriter.java:251)
    at com.google.gwt.dev.shell.CompilingClassLoader.findClassBytes(CompilingClassLoader.java:1236)
    at com.google.gwt.dev.shell.CompilingClassLoader.findClass(CompilingClassLoader.java:1059)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:247)

导致此异常的代码如下:

代码语言:javascript
复制
private native final JsoSplittable getJsoUserdata() /*-{
    if (typeof $wnd.user   !== 'undefined')
        return $wnd.user;
    return null;
}-*/;

@Override
public JsoSplittable getUserdata() {
    JsoSplittable user = null;
    user = getJsoUserdata();
    if (user != null) {
       String payload = user.getPayload();
       Window.alert(payload);
    }
    return user;
}

Window.alert(有效载荷)在生产模式下工作良好。在托管模式下,当我进入user.getPayload()时,在CompilingClassLoader.javafindOriginalDeclaringClass函数中得到一个NPE。declaringClasses似乎是空的

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-05-03 10:44:27

您不应该显式地转义任何东西;AutoBeans已经为您做过了。或者更确切地说,如果您想转义某物,请转义AutoBean的getPayload()的输出,而不是内部。

您的问题是,AutoBeans在可能的情况下使用本机JSON.parse() (出于性能和安全原因),根据规范,它只支持\uNNNN类型的转义,而不支持encodeForJavaScript输出的\xHH。换句话说,ESAPI需要一个encodeForJSON

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10428997

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档