Несомненно, безопасность программного обеспечения должна быть частью требований каждого разработчика: они должны быть объяснены и детализированы до разработки. К сожалению, в реальной жизни так бывает не всегда. В качестве альтернативы, даже когда это так, разработчики делают ошибки и / или вынуждены совершать жесткие (читай невозможные) планы. При отсутствии проверок безопасности автоматизированных инструментов, рано или поздно, появится проблема.
Я думал о том, как надежно очистить вывод крупномасштабного унаследованного 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 предлагает несколько способов очистки выходных данных, причем каждый параметр области может быть переопределен более узким:
- Область приложения, с параметром логического
defaultHtmlEscape
контекста <context-param><param-name>defaultHtmlEscape</param-name> <param-value>true</param-value> </context-param>
- Область страницы ( т. Е. Все формы на странице), с
<spring:defaultHtmlEscape>
тегом - Область тега с
htmlEscape
атрибутом тега
Есть только один улов; <spring:message>
тег может принимать не только код (ключ в файле свойств) , но и аргументы — однако те не убежали:
Hello, ${0} ${1}
Возможная методика санации состоит из следующих этапов:
- Создать новый
SanitizeMessageTag
:
- Наследовать от весны
MessageTag
- Переопределите соответствующий
revolveArguments(Object)
метод - Use the desired sanitization technique (Spring uses its own
HtmlUtils.htmlEscape(String)
)
- Наследовать от весны
- Copy the existing Spring TagLib Descriptor and create a new one out of it
- Update it to bind the
message
tag to the newly createdSanitizeMessageTag
class - 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:
- Subclasses relevant necessary EL resolvers – those are
ScopedAttributeELResolver
,ImplicitObjectELResolver
andBeanELResolver
, since they may return strings - 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
- Call
- 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.