Spring WebService SOAP请求的XXE防护实现方案咨询
JaxWS-Spring + JAXB 实现XXE防护方案
核心思路
XXE攻击的根源是XML解析器允许加载外部实体,核心解决方向是禁用XML解析器的外部实体解析能力,同时禁止DOCTYPE声明。针对JaxWS-Spring + JAXB的场景,可从XML解析器配置、JAXB解组器配置两个层面入手。
方案一:配置安全SAXParserFactory并注入JAXB
- 在
applicationContext.xml中定义安全的SAXParserFactory Bean,禁用外部实体及DOCTYPE声明:
<bean id="safeSaxParserFactory" class="javax.xml.parsers.SAXParserFactory"> <property name="feature"> <map> <entry key="http://xml.org/sax/features/external-general-entities" value="false"/> <entry key="http://xml.org/sax/features/external-parameter-entities" value="false"/> <entry key="http://apache.org/xml/features/disallow-doctype-decl" value="true"/> <entry key="http://apache.org/xml/features/nonvalidating/load-external-dtd" value="false"/> </map> </property> </bean>
- 自定义JAXB上下文配置类,将安全解析器关联到JAXB的Unmarshaller:
import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Unmarshaller; import javax.xml.parsers.SAXParserFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class SafeJaxbContext { private final SAXParserFactory saxParserFactory; @Autowired public SafeJaxbContext(SAXParserFactory saxParserFactory) { this.saxParserFactory = saxParserFactory; } public Unmarshaller createSafeUnmarshaller(Class<?>... classesToBeBound) throws JAXBException { JAXBContext context = JAXBContext.newInstance(classesToBeBound); Unmarshaller unmarshaller = context.createUnmarshaller(); unmarshaller.setProperty("javax.xml.bind.unmarshaller.SAXParserFactory", saxParserFactory); return unmarshaller; } }
- 修改端点服务类
CustomerEndpointService,注入自定义上下文并使用安全Unmarshaller:
import javax.jws.WebService; import javax.xml.bind.JAXBException; import javax.xml.bind.Unmarshaller; import org.springframework.beans.factory.annotation.Autowired; import org.webservicespring.ws.CustomerRequest; import org.webservicespring.ws.CustomerResponse; @WebService(endpointInterface = "org.webservicespring.ws.CustomerEndpoint") public class CustomerEndpointService implements CustomerEndpoint { @Autowired private SafeJaxbContext safeJaxbContext; @Override public CustomerResponse processCustomerRequest(CustomerRequest request) { // 若需手动解析请求体,使用安全Unmarshaller try { Unmarshaller unmarshaller = safeJaxbContext.createSafeUnmarshaller(CustomerRequest.class); // 执行自定义解组逻辑 } catch (JAXBException e) { throw new RuntimeException("请求解析失败", e); } // 业务逻辑处理 return new CustomerResponse(); } }
方案二:通过JaxWS-Spring扩展配置安全解析器
直接通过Spring配置覆盖JaxWS默认解析行为:
<bean id="safeMessageFactory" class="com.sun.xml.ws.api.message.saaj.SAAJMessageFactory"> <property name="saxParserFactory" ref="safeSaxParserFactory"/> </bean> <wss:binding url="/customer"> <wss:service> <ws:service bean="#customerEndpoint"> <ws:property name="javax.xml.ws.message.factory" ref="safeMessageFactory"/> </ws:service> </wss:service> </wss:binding>
额外保障:全局XML安全配置
添加全局初始化类,强制所有XML解析器启用安全特性:
import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.SAXParserFactory; public class XmlSecurityInitializer { static { // 全局配置SAXParserFactory System.setProperty("javax.xml.parsers.SAXParserFactory", "com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl"); try { SAXParserFactory spf = SAXParserFactory.newInstance(); spf.setFeature("http://xml.org/sax/features/external-general-entities", false); spf.setFeature("http://xml.org/sax/features/external-parameter-entities", false); spf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); } catch (Exception e) { // 异常处理 } // 全局配置DocumentBuilderFactory try { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setFeature("http://xml.org/sax/features/external-general-entities", false); dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false); dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); } catch (Exception e) { // 异常处理 } } }
在项目启动类中调用XmlSecurityInitializer.class完成全局初始化。
内容的提问来源于stack exchange,提问作者Kunu
相关产品推荐
相关产品推荐

