Автобан и XSS выпуск
У меня есть Spring
приложение на бэкэнд и GWT
приложение на веб-интерфейсе. Когда пользователь вошел в систему, index.jsp выведет информацию о пользователе в виде переменной javascript.
я использую AutoBeanFactory
кодировать и декодировать пользовательскую информацию как JSON.
Поскольку пользователь может зарегистрироваться, а пользовательская информация хранится в базе данных, я стараюсь следовать шпаргалке по OWASP XSS Preventing, избегая пользовательской информации на странице 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 выглядит следующим образом (обратите внимание, что имя пользователя имеет ü):
var data = {'user':'{"email":"john.doe@gmail.com","lastname":"Doe","firstname":"Über"}'};
Декодирование с помощью Autobean работает нормально, однако символ ü не отображается должным образом, но HTML-код экранирован (Über
).
Когда я использую encodeForJavaScript()
Функция вывода выглядит следующим образом:
var data = {'user':'{"email":"john.doe@gmail.com","lastname":"Doe","firstname":"\\xDCber"}'};
Когда я пытаюсь декодировать строку JSON, я сталкиваюсь со странной проблемой. В режиме разработки / размещенном режиме декодирование работает нормально, и умлаут отображается правильно. Однако, как только я запускаю код в производственном режиме, я получаю необнаруженное исключение:
java.lang.IllegalArgumentException: Error parsing JSON: SyntaxError: Unexpected token x
{"email":"john.doe@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)
Я могу думать о следующих решениях:
- Положитесь только на проверку входных данных (когда данные хранятся в БД) и удалите выходную кодировку. Но это не рекомендуемый подход.
- Замените Umlaute обычными символами ASCII (ü => ue) и продолжайте использовать выходную кодировку
- используйте некоторую библиотеку, которая экранирует символы XSS, но оставляет Umlaute в покое.
Я благодарен за отзыв
Обновление: на основе предложений Томаса я сейчас прохожу JsoSplittable
от JSNI, а затем передать это 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
нулевой
1 ответ
Вы не должны явно избегать чего-либо; AutoBeans уже сделали это для вас. Вернее, если вы хотите что-то избежать, избегайте вывода AutoBean's getPayload()
а не внутренности.
Ваша проблема в том, что AutoBeans использует нативный JSON.parse()
когда это возможно (по соображениям производительности и безопасности), который, согласно спецификации, поддерживает только \uNNNN
виды побегов, а не \xHH
тот encodeForJavaScript
выходы. Другими словами, ESAPI потребуется encodeForJSON
,