Статьи

Санитарная обработка выходных данных веб-приложения

Несомненно, безопасность программного обеспечения должна быть частью требований каждого разработчика: они должны быть объяснены и детализированы  до  разработки. К сожалению, в реальной жизни так бывает не всегда. В качестве альтернативы, даже когда это так, разработчики делают ошибки и / или вынуждены совершать жесткие (читай невозможные) планы. При отсутствии проверок безопасности автоматизированных инструментов, рано или поздно, появится проблема.

Я думал о том, как надежно очистить вывод крупномасштабного унаследованного Spring MVC-приложения ( то есть  не заходить на каждую страницу, чтобы исправить проблемы). В основном, есть 4 способа отображения вывода на странице HTML.

# имя Образец фрагмента Описание
1 Форма taglib <form: input path = ”firstName”> Выводит атрибут бина
2 Spring taglib <spring: message code = ”label.name.first”> Выводит сообщение из файла свойств
3 Стандартная библиотека Java Taglib <c: out value = ”$ {pageContext.request.requestURI}» /> Выводит значение
4 Язык выражения <SPAN> $ {pageContext.request.requestURI} </ SPAN> Выводит значение

Spring taglibs

Весенние taglibs — бриз, чтобы работать с По сути, Spring предлагает несколько способов очистки выходных данных, причем каждый параметр области может быть переопределен более узким:

  1. Область приложения, с параметром  логического defaultHtmlEscape  контекста <context-param>
      <param-name>defaultHtmlEscape</param-name>
      <param-value>true</param-value>
    </context-param>
  2. Область страницы ( т. Е.  Все формы на странице), с  <spring:defaultHtmlEscape> тегом
  3. Область тега с  htmlEscape атрибутом тега

Есть только один улов; <spring:message> тег может принимать не только код (ключ в файле свойств) , но и аргументы — однако те  не  убежали:

Hello, ${0} ${1}

Возможная методика санации состоит из следующих этапов:

  1. Создать новый  SanitizeMessageTag:

    • Наследовать от весны MessageTag
    • Переопределите соответствующий  revolveArguments(Object) метод
    • Use the desired sanitization technique (Spring uses its own HtmlUtils.htmlEscape(String))
  2. Copy the existing Spring TagLib Descriptor and create a new one out of it
  3. Update it to bind the message tag to the newly created SanitizeMessageTag class
  4. Last but not least, override the configuration of the taglib in the web deployment descriptor:<jsp-config>
      <taglib>
        <taglib-uri>http://www.springframework.org/tags</taglib-uri>
        <taglib-location>/WEB-INF/tld/sanitized-spring-form.tld</taglib-location>
      </taglib>
    </jsp-config>
    

By default, the JavaEE specifications mandates for the container to look for TLDs insides JARs located under the 
WEB-INF/lib
 directory. It is also possible to configure them in the web deployment descriptor. However, the configuration takes precedence over automatic scanning.

This way, existing JSP using the Spring taglib will automatically benefit from the new tag with no page-to-page update necessary.

JSTL

The <c:out> tag works the same way as the <spring:message> one, the only difference being there’s no global configuration parameter, only a escapeXml tag attribute which defaults to false.

The same technique as above can be used to default to true instead.

EL

The EL syntax enables output outside any taglib so that the previous TLD override technique cannot be used to solve this.

Not known to many developers, EL snippets are governed by so-called EL resolvers. Standard application servers (including servlet containers like Tomcat) provide standard EL resolvers, but it is also possible to add others at runtime.

Note: though only a single EL resolver can be set in the JSP context, the resolver hierarchy implements the Composite pattern, so it’s not an issue.

Steps required to sanitize EL syntax by default are:

  1. Subclasses relevant necessary EL resolvers – those are ScopedAttributeELResolverImplicitObjectELResolver and BeanELResolver, since they may return strings
  2. For each, override the getValue() method:
    • Call super.getValue()
    • Check the return value
    • If it is a string, sanitize the value before returning it, otherwise, leave it as it is
  3. Create a ServletContextListener to register these new EL resolverspublic class SanitizeELResolverListener implements ServletContextListener {
        public void contextInitialized(ServletContextEvent event) {
            ServletContext context = event.getServletContext();
            JspFactory jspFactory = JspFactory.getDefaultFactory();
            JspApplicationContext jspApplicationContext = jspFactory.getJspApplicationContext(context);
            ELResolver sber = new SanitizeBeanELResolver();
            jspApplicationContext.addELResolver(sber);
            // Register other EL resolvers
        }
    }

Summary

Trying to sanitize the output of an application after it has been developed is not the good way to raise developers concerns about security. However, dire situations require dire solutions. When the application has already been developed, the above approaches — one for taglibs, one for EL, show how to achieve this in a way that does not impact existing code and get the job done.