Almost exactly a year ago I posted a diary called Is XXE the new SQLi? you can read it at https://isc.sans.edu/diary/Is+XXE+the+new+SQLi/17375. In last year, the things have not changed a lot regarding XXE vulnerabilities. They still seem to be popping up here and there, depending on how XML documents are consumed by server side applications.
Recently I had an interesting engagement where the server side web application consumed an XML document submitted by a user (through a web browser, in a POST HTTP request). Of course, whenever you see XML being used, you should always test for existence of XXE vulnerabilities since their impact can be quite serious check the original diary and can lead from Denial of Service attacks to disclosure of arbitrary files.
In this specific case, however, the problem was that while the application processed the submitted XML document, it never outputted anything from the document: the application would only echo back if processing was successful or not.
So the question that came in mind was on how to confirm if the target application was vulnerable to XXE or not? Sure, I could try to launch a DoS attack to see if it works or not, but since I was dealing with a semi-production system, this was not an option.
Almost like blind SQL injection
This case is very similar to blind SQL injection vulnerabilities: we can modify the input and while we cannot see the output directly, we can deduce what happened on the server side. Let">DocumentLayer
Document InternalID=1
DocumentPointerTest/DocumentPointer
/Document
/DocumentLayer
Of course, in the real test the XML document was much more complex and had some logic for the backend application ">DocumentPointer">!DOCTYPE DocumentLayer [
!ELEMENT DocumentLayer ANY
!ENTITY xxe Test ]
DocumentLayer
Document InternalID=1
DocumentPointer/DocumentPointer
/Document
/DocumentLayer
Simple! If this works, it means that we blindly confirmed that the XML processor on the server side used our reference to the xxe entity. Cool.
The next step is to see if we can use external entities. However, again, since we cannot see the results of the XXE injection, its not all that simple. To make things more complex, the backend server is behind a firewall that does not let this machine connect directly to anything on the Internet. This stops us from using a SYSTEM external entity with a URL supplied.
So is there any other way to confirm that external entities are supported? Probably yes there is one protocol that is almost always allowed, in one sense or another: DNS. In this particular case, this means that we can craft external entity which will resolve to a domain name that we control by checking DNS requests we can see if the entity was resolved correctly or not. In this case it does not matter if the backend server cannot access the Internet or not ">!DOCTYPE DocumentLayer [
!ELEMENT DocumentLayer ANY
!ENTITY xxe SYSTEM http://thisdomaindoesnotexist.infigo.hr/test.txt ]
DocumentLayer
Document InternalID=1
DocumentPointer/DocumentPointer
/Document
/DocumentLayer
While this document will not be processed correctly (remember, the DocumentPointer element must contain the text string Test), the reference will be resolved by the XML processor and by observing the DNS traffic on DNS servers for our domain we will see a request for the submitted domain which will allow us to confirm that XXEs are resolved by the target application.
So, to wrap things up we blindly confirmed the XXE vulnerability in the target application. While in this case our exploitation options are unfortunately limited only to DoS, it is worth noting that the vulnerability exists, and that its only a matter of time when it can be abused further, unless patched.
(c) SANS Internet Storm Center. https://isc.sans.edu Creative Commons Attribution-Noncommercial 3.0 United States License.