Browser Pivoting (Get past two-factor auth)

September 26, 2013

Several months ago, I was asked if I had a way to get past two-factor authentication on web applications. Criminals do it, but penetration testers don’t. To solve this problem, I built a man-in-the-browser capability for penetration testers and red teams. I call it browser pivoting.

A browser pivot is an HTTP proxy server that injects into a 32-bit Internet Explorer process. By browsing through this proxy server, I can reach any website my target logged into–as them. If the target logs into their web mail, I’m logged into their web mail. If they send sap stories to their ex-girlfriend on Facebook, I read them. If they use DropBox’s website to store and manage files, I’ll download the best ones. If they’re connected to an intranet portal site; I’m there too. [Update 21 Nov 13: 64-bit IE is now supported as well]


How it Works

Internet Explorer’s architecture makes Browser Pivoting possible. Internet Explorer is an application that consumes several libraries. WinINet is the library Internet Explorer uses to communicate. The WinINet API is popular with malware developers because it allows them to request content from a URL with very little code. WinINet is more than a high-level HTTP library built on top of Windows sockets. WinINet manages a lot of state for the applications that use it.


I became familiar with WinINet during Beacon‘s development. I tried to use the Cookie header to send information. I was baffled when this cookie kept coming back blank. I didn’t know this at the time, but WinINet removed my cookie to insert the cookie from its store into my request. I had to set a INTERNET_FLAG_NO_COOKIES flag before I could programmatically send my cookie.

Cookies aren’t the only thing WinINet forces into a request. WinINet will also retransmit “credential material” which includes a previously provided username/password or client SSL certificate. If WinINet is communicating with a site in the Intranet Zone (and the user’s settings permit it); WinINet will automatically try to logon with the user’s default credentials. The WinINet consumer must set the INTERNET_OPTION_SUPPRESS_SERVER_AUTH flag to disable this behavior.

WinINet is the layer that manages Internet Explorer’s cache, history, cookies, HTTP authentication, and SSL session state. Inheriting this managed state isn’t a bug–it’s a feature.

A browser pivot is an HTTP proxy server that fulfills requests with WinINet. The process this proxy server lives in is important. If I inject this proxy server into notepad.exe, I don’t get anything interesting.


Magic happens when I inject [0] this proxy server into the Internet Explorer process [1]. I inherit Internet Explorer’s WinINet state with each request. If a user’s web session is secured with a stored cookie, session cookie, HTTP authentication, or client SSL certificate–I can use that session with a browser pivot [2].

Two-factor authentication is a non-issue at this point too. WinINet doesn’t care about how this session state was obtained. It just uses it. 


[0] Several people have asked about this mysterious process injection thing I refer to. The Browser Pivot proxy server is compiled as a Reflective DLL. I use the Metasploit Framework’s post/windows/manage/reflective_dll_inject module to inject this DLL into a process I choose.

[1] There’s one nuance to this: Modern versions of Internet Explorer isolate each tab in a separate process. In this case, the parent Internet Explorer process does not have access to WinINet state. The processes associated with a tab share WinINet state with the other tab processes. If you inject into Internet Explorer 10, make sure you inject into a child tab’s process.

[2] WinINet session state is good until the user closes the browser. If the user closes their browser–the proxy server goes away and the attacker must inject into another process. How to keep session state–even after the browser closes, is not part of this work. 

How to Use It

Browser Pivoting is available in today’s Cobalt Strike update. Go to [host] -> Meterpreter -> Explore -> Browser Pivot. Choose the process to inject into. Press Launch. Cobalt Strike will setup the browser pivot and start a port forward through Meterpreter for you. Setup your browser to go through the browser pivot and have at it.

Here’s a demo of Browser Pivoting in action:

To keep this blog post sane, I had to skip a lot of details. If you find Browser Pivoting interesting, you can learn more about it at DerbyCon. I’m speaking on the technology at 2pm on Saturday. [Update 1 Oct 13 – I spoke on the technology… here’s the video]

If you’d like to try Browser Pivoting today, grab a 21-day trial of Cobalt Strike. Licensed users may get the latest with the built-in update program.


  1. Raf, I’m about to drop railgun code for interacting with wininet, plus a post/windows/browser mixin, lemme know if it’s helpful or u want to collab. Could maybe browser pivot w/o injecting. I know that’s counter to having capabilities in the paid version, but hey. And I can theoretically do it w/o help as I’m automating the browser for another project anyways

    • I think something like this would be awesome in the framework (I’d welcome it too–one less thing to maintain on my end). I can’t offer much help because my Ruby skills are non-existent. If there’s any way I can help (e.g., some insight from this project)–let me know and I’m happy to share what I can.

      • I’m assuming it has to do w/the flags/options one can set in some of the wininet functions. I remember seeing one, can’t find it atm, that directs the request to use an existing connection if available. Do you enumerate the handles first then query/reuse them? I know HttpQueryOption has a ton of flags for pulling info from existing handles, but I’m assuming it’s a straight reuse, not a pull info from a handle and reuse that?

  2. @rsmudge nice job as always

  3. As described, the use appears limited: 32-bit is on the way out and IE fairs even worse.

    What happens with Firefox or Chrome on a 64-bit system?

    • In the 64-bit Windows 7 systems I’ve setup; 32-bit Internet Explorer is the default. My understanding is that Microsoft does this for plugin compatibility reasons. If the browser shell runs in a 64-bit process, but the child tabs run in a 32-bit process–I can inject into one of the child tabs and take advantage of this session state. Targeting a 32-bit instance of IE makes sense.

      This is an initial release. If there’s customer demand, it’s not a big leap to make this technology work with 64-bit IE.

      I have a specific use case for this technology. My focus on internet explorer is an acceptable constraint for this use case.

      Firefox and Google Chrome have their own architecture. I did not investigate them for this initial effort.

      • And… it works with 64-bit IE now .

  4. I think my reply to yours didn’t make it thru. I think I would just need to know what calls you made into WinINet.dll to make it happen. I have already railgun’ified pretty much the entire dll and crated a post API for it, I could add the pivoting to the API to simplify the method calls. Let me know if you are willing to send me the source (or just the pertinent parts), or give me some kind of more in-depth description

  5. Oh man, I’m so excited for this release. This could could be huge during certain types of engagements. Thanks again for all your hard (and creative) work!

    • Thanks for being such a great supporter of Armitage and Cobalt Strike (to include beta testing Cobalt Strike during its early development).

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s