#介绍
老漏洞了,原理也很简单,随便分析一波。
漏洞编号为CVE-2013-4152,根据官方提示,xxe漏洞,漏洞的位置包括oxm,嗯,现学现卖,直接翻到文档学习一波 https://docs.spring.io/spring/docs/current/spring-framework-reference/data-access.html#oxm 根据官方写一个demo
``` public class Application { private static final String FILE_NAME = "src/main/java/test/settings.xml"; private Settings settings = new Settings(); private Marshaller marshaller; private Unmarshaller unmarshaller; public void setMarshaller(Marshaller marshaller) { this.marshaller = marshaller; } public void setUnmarshaller(Unmarshaller unmarshaller) { this.unmarshaller = unmarshaller; } public void saveSettings() throws IOException { FileOutputStream os = null; try { os = new FileOutputStream(FILE_NAME); this.marshaller.marshal(settings, new StreamResult(os)); } finally { if (os != null) { os.close(); } } } public void loadSettings() throws IOException { FileInputStream is = null; try { is = new FileInputStream(FILE_NAME); this.settings = (Settings) this.unmarshaller.unmarshal(new StreamSource(is)); } finally { if (is != null) { is.close(); } } } public static void main(String[] args) throws IOException { ApplicationContext appContext = new ClassPathXmlApplicationContext("applicationContext.xml"); Application application = (Application) appContext.getBean("application"); application.saveSettings(); application.loadSettings(); } } ---------------------------------- ```` public class Settings { private boolean fooEnabled; public boolean isFooEnabled() { return fooEnabled; } public void setFooEnabled(boolean fooEnabled) { this.fooEnabled = fooEnabled; } } ````
测试完xml解析之后,写了一个web项目,验证一下,核心代码如下:
``` @Controller public class XmlController { @RequestMapping(value = "/login", method = RequestMethod.POST, consumes = "application/xml") @ResponseBody public String login(@RequestBody User user) { String username = user.getUserName(); String userpassword = user.getUserPassword(); String result; if (username.equals("admin") && userpassword.equals("admin888")){ result = "{'status':'ok', 'message': 'login success', 'username': " + username+ "}"; }else { result = "{'status':'error', 'message': 'login fail', username': " + username+ "}"; } return result; } } ```` ----------------------------------- ```` @XmlRootElement(name = "user") public class User { private String userId; private String userName; private String userPassword; @XmlElement public String getUserPassword() { return userPassword; } public void setUserPassword(String userPassword) { this.userPassword = userPassword; } @XmlElement public String getUserId() { return userId; } public void setUserId(String userId) { this.userId = userId; } @XmlElement public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } } ````
正常测试XML如下
curl -i -X POST -H “Content-Type:application/xml” -d “
xml:
有回显 curl -i -X POST -H “Content-Type:application/xml” -d “<!DOCTYPE a [<!ENTITY xxe2 SYSTEM "file:///etc/passwd">]>
” http://127.0.0.1:8080/CVE-2013-4152/login
漏洞造成的原因是由于unmarshal函数中直接解析xml文件,没什么好分析的。
官方修复的补丁 https://github.com/spring-projects/spring-framework/pull/317/commits/2843b7d2ee12e3f9c458f6f816befd21b402e3b9
指的说明的是网上很多关于xxe漏洞的修复方案中只提到
DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance(); dbf.setExpandEntityReferences(false);
各种类型的具体修复方案见下面 DOM
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); documentBuilderFactory.setExpandEntityReferences(false); DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); Document document = documentBuilder.parse(externalSource);
SAX
XMLReader xmlReader = XMLReaderFactory.createXMLReader(); xmlReader.setFeature("http://xml.org/sax/features/external-general-entities", false); xmlReader.parse(new InputSource(externalSource));
StAX
XMLInputFactory factory = XMLInputFactory.newInstance(); factory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, false); XMLStreamReader reader = factory.createXMLStreamReader(externalSource);
Spring OXM
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); documentBuilderFactory.setExpandEntityReferences(false); DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); Document document = documentBuilder.parse(externalSource); DOMSource source = new DOMSource(document); Jaxb2Marshaller jaxb2Marshaller = ... Object unmarshalled = jaxb2Marshaller.unmarshal(source);
CVE-2013-4152补丁设置xmlReader.setFeature(“http://xml.org/sax/features/external-general-entities”,false);可以防止外部实体被解析
###参考文档
http://blog.csdn.net/scmrpu/article/details/50423701 https://security.tencent.com/index.php/blog/msg/69