2012-05-03 10 views
1

私はSpringアプリケーションをバックエンドに、GWTアプリケーションをフロントエンドに持っています。 ユーザーが '' index.jsp ''にログインすると、ユーザー情報がjavascript変数として出力されます。AutobanとXSSの問題

私はAutoBeanFactoryを使用して、ユーザー情報をjsonとしてエンコードおよびデコードしています。
ユーザーは登録でき、ユーザー情報はデータベースに格納されているため、JSPページのユーザー情報をエスケープして、OWASP XSS Preventing cheat sheetに従ってください。

私はエンコードを行うためにesapiライブラリを使用しています。サーバー側のコードは次のようになります。

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の変数は、この(FIRSTNAMEがüを持って注意してください)のようになります。Autobeanと復号化が正常に動作します

var data = {'user':'{"email":"john.doe&#x40;gmail.com","lastname":"Doe","firstname":"&Uuml;ber"}'}; 

しかし文字üが正しく表示されますが、HTMLは(1エスケープされていません&Uuml;ber)。

私はencodeForJavaScript()機能を使用する場合は、次のように出力されている:

var data = {'user':'{"email":"john.doe&#x40;gmail.com","lastname":"Doe","firstname":"\\xDCber"}'}; 

私は奇妙な問題に遭遇したJSON文字列をデコードしようとします。開発モード/ホストモードのデコードで正常に動作し、Umlautが正しく表示されます。 は、しかし、すぐに私はプロダクションモードでコードを実行するように私はキャッチされない例外を取得:

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次取得ホスト・モードで本番モードで正常に動作します:

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) 

この例外は以下の通りです原因コード:

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()に入るとfindOriginalDeclaringClassのNPEを取得し、CompilingClassLoader.javaの機能を使用します。declaringClassesがnullであると思われます。

答えて

2

明示的に何もエスケープしないでください。オートビーンズはあなたのために既にそれを行います。あるいは、何かをエスケープしたい場合は、AutoBeanのgetPayload()の出力をエスケープしてください。

あなたの問題はAutoBeansが可能、仕様ごとに、唯一のエスケープの\uNNNN種類をサポートし、ない\xHHencodeForJavaScriptその出力(性能や安全上の理由の両方のための)ネイティブJSON.parse()を使用することです。つまり、ESAPIにはencodeForJSONが必要です。

+0

Thomasさんからの応答に感謝します。 ペイロードに '' encodeForJavaScript() ''を使ってみましたが、うまくいくようです。 Autobeanがすでに各分野(セキュリティ上の賢明さ)で私にそれをしているときに、ペイロードをエンコードすることは実際には意味がありますか? BTW:http://www.wijsmullerbros.nl/content/gwt-hostpage-init-data-encoding –

+0

私が実際に理解していないのは、あなた(そしてリンクされた記事)が代わりに文字列としてオートバイのペイロードを使用する理由ですオブジェクトリテラルのJSNIメソッド( 'Dictionary'ではなく)から' com.google.web.bindery.autobean.gwt.client.impl.JsoSplittable'としてオブジェクトを返し、 '{user :} 'wrapper:' var user = <%= autobeanPayload%> 'と' native JsoSplittable getUser()/ * - {return $ wnd.user; } - * /; '。あなたのオリジナルの質問については、私は 'encodeForJavaScript'を使用しませんが、あなたのページのエンコーディングについて注意する必要があります(UTF-8でなければなりません)。 –

+0

提案をありがとう。私はそれを考えなかった。 Splittableを直接返すようにしました。プロダクションモードで正常に動作します。しかし、ホストモードでは、 '' Splittable.getPayload() ''を呼び出すとNPEを取得します(例外の詳細については私の質問を参照してください)。 –