David Byrne: Intranet Invasion With Anti-DNS Pinning

Published: Jan. 9, 2006, 11:10 p.m.

Cross Site Scripting has received much attention over the last several years, although some of its more ominous implications have not received much attention. Anti-DNS pinning is a relatively new threat that, while not well understood by most security professionals, is far from theoretical. This presentation will focus on a live demonstration of anti-DNS pinning techniques. A victim web browser will be used to execute arbitrary, interactive HTTP requests to any server, completely bypassing perimeter firewalls.

This is NOT a Jickto knockoff. Jickto relies on using a proxy or caching site like Google to place both sites in the same domain. This does not allow for full interaction with dynamic pages, or any interaction with internal web sites. This demonstration allows full interaction with arbitrary web servers in the intranet environment. No browser bugs or plug-ins are required to accomplish this, only JavaScript.

The presenter will demonstrate an automated attack process that provides an HTTP proxy service for the attacker's browser after scanning the internal network for web servers. New requests are retrieved from the attack server by using the width and height of truncated images (only 66 bytes) as a covert channel.*** This bypasses the browser DOM normal behavior of allowing data to be requested only from the server that provided the HTML.

Before demonstrating the tool, anti-DNS pinning will be explained in a way that anyone familiar with the basics of DNS and HTTP will understand. The presenter will describe the presentation environment and attack components, then walk through the steps in an attack. Once the foundation concepts have been established, the live demonstration will be performed.

Towards the end, the presentation will also briefly cover suggested defenses, including changing pinning behavior in browsers, better intranet security, gateway behavioral scanners, increased granularity for IE security zones, and introduction of security zones into Mozilla and other browsers.

Enhancements to the tool are in-progress to add binary socket capabilities using an untrusted Java Applet. These changes will be complete in time for the presentation. This will allow for full access to any TCP protocol via a web browser supporting JavaScript and a JVM. The attacker would access this via a SOCKS proxy interface. The image dimension-based covert transfer is too slow for many protocols, so a second technique involving Cascading Style Sheets is used.*** The data is smuggled in border values of sequentially named classes. This is clearly a superior method, but there is still benefit from demonstrating the image-based method.

*** I developed this technique and couldn't find any reference to it, but others may have used it before.

Several key use-cases are outlined below. The actors involved are:
* Victim browser: Once a malicious or XSS infected site is visited, any browser can be used
* Slave.js: The JavaScript that registers the victim browser with the attack website and polls for new commands
* Proxy.js: The JavaScript that executes arbitrary HTTP commands from the attacker
* Controller.pl: A multipurpose CGI script that acts as the central control point for victim browsers, as a management console for the attacker, and coordinates the firewall & DNS changes required for the anti-pinning attack
* Database: Stores session state and new commands for victim browsers
* Proxy.pl: Runs an HTTP proxy that translates attacker requests into JavaScript commands
* Attacker web server: Hosts controller.pl on primary and secondary IP addresses
* Firewall: Blocks inbound requests to the secondary IP address during the anti-pinning attack
* DNS Server: Serves up the "A" records used for the anti-pinning attack

Initial infection
1. The victim browser visits an attack website and downloads slave.js
2. Slave.js registers with controller.pl and polls for new commands

Port scanning
1. The attacker sends a request to controller.pl to have the victim browser scan a range of addresses for specific ports running web servers
2. Controller.pl generates and inserts the port scan JavaScript code for the victim browser
3. Slave.js polls for new commands and receives the scanning script from controller.pl
4. The scanning script creates a new iframe for each host/port combination and sets the ?onload? event to create an img object. This image has a source of controller.pl with parameters indicating a successful port scan for the host/port combination.
5. Controller.pl receives the image request logs the successful scan event into the database.

Out-of-channel img communications for value retrieval
1. A proxy.js component calls GetValue with a command, unique description, and call-back function as argument
2. GetValue creates an img object
a. The source is set to controller.pl with a query string containing the relevant command
b. The id is set to a string containing a unique description and sequence number
c. The "onload" attribute is set to a callback function with the command, unique description, the counter value, and a secondary call-back function to resume execution
3. GetValue appends the img object to the document
4. The victim browser requests the image from the attack web server
5. Controller.pl processes the request and returns a dynamically generated bitmap with the width and height properties used to encode a two byte integer value as a response. The bitmap only needs to be 66 bytes, regardless of the dimensions.
6. The victim browser loads the image and fires the onload call-back
7. The call-back function checks the width and height of the image, decodes the value and stores it in a global array with the unique description & sequence number as the index
8. The call-back function calls the secondary call-back function and resumes execution within proxy.js

Out-of-channel img communications for string retrieval
1. A proxy.js component calls GetString with a command, unique description, and call-back function as argument
2. GetString requests the string length from controller.pl using out-of-channel img communications, prepending "stringlength" to the relevant command
3. GetString creates an img object for every two bytes of the string (1&2, 3&4, etc)
a. The source is set to controller.pl with a query string containing the relevant command and the string position of the bytes
b. The id is set to a string containing a unique description and sequence number
c. The "onload" attribute is set to a callback function with the image id as the only parameter
4. The victim browser will asynchronously request all of the generated images
a. Controller.pl processes the request and returns a bitmap with the width and height properties used to encode the two byte string.
b. The victim browser loads the image and fires the onload call-back
c. The call-back function checks the width and height of the image, decodes the string segment and stores it in a global array with the img object id as the index
5. As the browser is requesting the images, GetString calls the CompileString function, which checks the global array to see if all string components have been returned & stored.
6. If the string is not complete, CompileString pauses, then calls itself again using SetTimeout.
7. Once the string is complete, CompileString calls the call-back function to resume execution with proxy.js

First request for an iframe proxy
1. The attacker sends a command to controller.pl to activate the proxy for a victim browser
2. Controller.pl starts proxy.pl on a random port and modifies the PAC file to point at that port
3. The attacker browser sends a request to proxy.pl for a target IP address detected in the port scanning phase
4. Proxy.pl checks in the database to see if the victim browser has an iframe proxy for the requested target IP address. Since this is the first request for the target IP address, there will be no iframe record.
5. Proxy.pl creates a random host name record in the DNS server and points it to the attack web server's secondary IP address
6. Proxy.pl inserts a JavaScript command to create a new iframe proxy in the victim browser pointed at the random host name
7. Proxy.pl inserts the attacker's HTTP request in the database and begins to poll for the result
8. Slave.js polls for new commands and receives the iframe command from controller.pl
9. Slave.js creates a new iframe. The source attribute of the iframe points at controller.pl on the random hostname, with the command requesting proxy.js
10. Once proxy.js has been downloaded, controller.pl blocks access from the victim IP address to the web server's secondary IP address, and changes the random hostname to point at the target IP address
11. Using out-of-channel img communications, proxy.js polls controller.pl, until the DNS & firewall changes are confirmed
12. Using out-of-channel img communications, proxy.js requests the next HTTP command
13. Proxy.js uses XMLHttpRequest to process the provided HTTP command, using the random hostname. Because of the firewall rule, the victim browser will timeout after trying to reconnect to the cached secondary IP address.
14. Continue to attempt XMLHttpRequest until the browser realizes the server isn't there, and dumps its host / IP address cache.
15. The victim browser re-queries DNS, this time getting the IP address of the targeted web server
16. The browser runs the request and returns the result to proxy.js
17. Proxy.js creates a new iframe with a unique ID
18. Proxy.js creates a form with a POST method, an action pointing at controller.pl on the primary IP address, a target at the new iframe, and a single textarea input
19. Proxy.js sets the textarea value to the HTTP results and submits the form. Since the target is an iframe, there will be no redirection
20. Controller.pl receives the HTTP response and inserts it into the database
21. Proxy.pl polls the database, finds the response, and returns it to the attacker browser

Proxy requests for an existing iframe are essentially the same, but steps 5-11, 14, 15 are not required." Specializing in web application security, David Byrne is a seven year veteran of the Information Security industry. He is currently the Security Architect for EchoStar Satellite, owner of Dish Network. David is also the founder and current leader of the Denver chapter of the Open Web Application Security Project (OWASP).