2012-05-03 2 views
1

나는 프론트 엔드에 GWT 응용 프로그램이 있고 백도어에 Spring 응용 프로그램이 있습니다. 사용자가 ''index.jsp ''에 로그인하면 사용자 정보가 javascript 변수로 출력됩니다.Autobean 및 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() 기능을 사용하는 경우 (FIRSTNAME는 ü가주의) :

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

Autobean와 디코딩 그러나 문자 ü가 제대로 표시되지 않지만 HTML 하나를 탈출 잘 작동을 (&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. Umlaute를 일반 ASCII 문자 (ü => ue)로 바꾸고 출력 인코딩을 계속 사용하십시오.
  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()으로 들어가면 NPE가 findOriginalDeclaringClass이되어 CompilingClassLoader.java의 기능을합니다.declaringClasses이 null 인 것 같습니다.

답변

2

명시 적으로 아무 것도 이스케이프해서는 안됩니다. AutoBeans가 이미 그것을 해줍니다. 또는 뭔가를 벗어나고 싶다면 AutoBean의 getPayload()의 출력을 이스케이프해야합니다.

귀하의 문제는 AutoBeans 가능, 사양 당 만 탈출의 \uNNNN 종류의 지원이 아닌 \xHHencodeForJavaScript 그 출력 (성능 및 안전을 이유로 모두) 기본 JSON.parse()를 사용한다는 것입니다. 즉, ESAPI는 encodeForJSON이 필요합니다.

+0

토마스에게 감사의 말을 전합니다. 페이로드에서''encodeForJavaScript()''를 사용하려했으나 정상적으로 작동하는 것 같습니다. Autobean이 각 필드 (보안 현명한)를 위해 이미 그것을 할 때 실제로 페이로드를 인코딩하는 것이 합리적입니까? BTW : http://www.wijsmullerbros.nl/content/gwt-hostpage-init-data-encoding –

+0

실제로 이해가 안되는 것은 여러분과 (링크 된 기사)가 대신 AutoBean의 페이로드를 문자열로 사용하는 이유입니다 객체 리터럴의 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을 직접 반환하려했으나 프로덕션 모드에서는 정상적으로 작동합니다. 그러나 Hosted Mode에서는''Splittable.getPayload()''를 호출 할 때 NPE를 얻습니다 (예외 사항은 내 질문 참조). –