2012-05-03 3 views
1

У меня есть приложение Spring на бэкэнд и приложение GWT на интерфейсе. Когда пользователь войдет в систему '' index.jsp '', выведет пользовательскую информацию как переменную javascript.Autobean и XSS issue

Я использую AutoBeanFactory для кодирования и декодирования информации о пользователе как json.
Поскольку пользователь может зарегистрироваться и информация пользователя хранится в базе данных, я стараюсь следовать за OWASP XSS Preventing cheat sheet, экранируя информацию пользователя на странице JSP.

Я использую библиотеку 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; 
    } 

Я пытался использовать encodeForHTML и encodeForJavaScript(). Это нормально работает для обычных персонажей, однако, как только я использую символы Umlaute (ü, ä, ö), я сталкиваюсь с проблемами.

Если я использую функцию encodeforHTML() Javascript переменной выглядит следующим образом (обратите внимание 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.

Я благодарен за некоторые отзывы

Update: На основе предложений Томаса Я теперь проходящий JsoSplittable от JSNI, а затем проходящим это функции AutoBeanCodex.decode. Он отлично работает в режиме производства, однако в режиме Hosted Mode я получаю следующее 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 (полезная нагрузка) штраф в режиме производства работ. В режиме Hosted, когда я вхожу в user.getPayload(), я получаю NPE в findOriginalDeclaringClass функции CompilingClassLoader.java.Похоже, что declaringClasses не имеет значения

ответ

2

Вы не должны явно скрывать что-либо; AutoBeans делают это за вас уже. Вернее, если вы хотите что-то избежать, избегайте выхода AutoBean getPayload(), а не внутренних.

Ваша проблема заключается в том, что AutoBeans использует родную JSON.parse(), когда это возможно (для производительности и из соображений безопасности), которые, согласно спецификации, поддерживают только \uNNNN видов побегов, а не \xHH что encodeForJavaScript выходов. Другими словами, ESAPI понадобится encodeForJSON.

+0

Спасибо Томас за ответ. Я попытался использовать '' encodeForJavaScript() '' на полезной нагрузке и, похоже, работает нормально. Имеет ли смысл кодировать полезную нагрузку, когда Autobean уже делает это для меня для каждого поля (безопасность разумна)? BTW: http://www.wijsmullerbros.nl/content/gwt-hostpage-init-data-encoding –

+0

На самом деле я не понимаю, почему вы (и связанная статья) используете полезную нагрузку AutoBean как строку вместо объектного литерала. Затем вы возвращаете свой объект как 'com.google.web.bindery.autobean.gwt.client.impl.JsoSplittable' из метода JSNI (вместо словаря), и вам даже не понадобится' {user :} 'wrapper:' var user = <% = autobeanPayload%> 'и' native JsoSplittable getUser()/* - {return $ wnd.user; } - * /; '. Что касается вашего оригинального вопроса: я бы не использовал 'encodeForJavaScript', но вы должны быть осторожны тогда о вашей кодировке страницы (должен быть UTF-8 уже хотя) –

+0

Спасибо за предложение. Я об этом не думал. Я попытался вернуть Splittable напрямую, и он отлично работает в режиме производства. Однако в режиме Hosted Mode я получаю NPE, когда я вызываю '' Splittable.getPayload() '' (см. Мой вопрос для деталей исключения). –

Смежные вопросы