Book Image

Hands-On Penetration Testing on Windows

By : Phil Bramwell
Book Image

Hands-On Penetration Testing on Windows

By: Phil Bramwell

Overview of this book

Windows has always been the go-to platform for users around the globe to perform administration and ad hoc tasks, in settings that range from small offices to global enterprises, and this massive footprint makes securing Windows a unique challenge. This book will enable you to distinguish yourself to your clients. In this book, you'll learn advanced techniques to attack Windows environments from the indispensable toolkit that is Kali Linux. We'll work through core network hacking concepts and advanced Windows exploitation techniques, such as stack and heap overflows, precision heap spraying, and kernel exploitation, using coding principles that allow you to leverage powerful Python scripts and shellcode. We'll wrap up with post-exploitation strategies that enable you to go deeper and keep your access. Finally, we'll introduce kernel hacking fundamentals and fuzzing testing, so you can discover vulnerabilities and write custom exploits. By the end of this book, you'll be well-versed in identifying vulnerabilities within the Windows OS and developing the desired solutions for them.
Table of Contents (25 chapters)
Title Page
Dedication
Packt Upsell
Contributors
Preface
Index

Breaking out of jail – masquerading the stack


Imagine you're trying to get into a guarded door. The moment you open that door, a guard sees you and, identifying you as unauthorized, immediately kicks you out. But, suppose that an authorized person opens the door and props it open, and the guard will only verify the identity of the person walking through every 10 minutes or so, instead of continuously. They assume that an authorized person is using the door during that 10-minute window because they already authenticated the first person who opened it and propped it open. 

Of course, this wouldn't happen in the real world (at least, I sure hope not), but the principle is often seen even in sophisticated industry-standard network access control systems. Instead of people, we're talking about packets on the network. As we learned from our fingerprinting exercise, the fine details of how a packet is formed betrays a particular source system. These details make them handy indicators of a source. It quacks like a duck and it walks like a duck, so it is a duck and definitely not a guy in a duck costume.  

NACs employing this kind of fingerprinting technique will conduct an initial evaluation, and then assume the subsequent packets match the signature, just like our guard who figures the door is being used by the good guy after they do their first check. The reason for this is simple: performance. Whether the follow-up checks are every few minutes or never will depend on the NAC and configuration. 

We're going to introduce a tool called Scapy to demo this particular attack. As we progress through this book, you will see that Scapy could easily replace most of the tools that pen testers take for granted: port scanners, fingerprinters, spoofers, and so on. We're going to do a quick demo for our NAC bypass here, but we will be leveraging the power of Scapy in coming chapters. 

Following the rules spoils the fun – suppressing normal TCP replies

The details of a TCP handshake are beyond the scope of this chapter, but we'll discuss the basics to understand what we need to do to pull off the masquerade. Most of us are familiar with the TCP three-way handshake:

  1. The client sends a SYN request (synchronize)
  2. The receiver replies with a SYN-ACK acknowledgment (synchronize-acknowledge)
  3. The client confirms with an ACK acknowledgment; the channel is established and communication can begin

This is a very simple description (I've left out sequence numbers; we'll discuss those further), and it's nice when it works as designed. However, those of you with any significant Nmap experience should be familiar with the funny things that can happen when a service receives something out of sequence. Section 3.4 of RFC 793 is where the fun is really laid out, and I encourage everyone to read it. Basically, the design of TCP has mechanisms to abort if something goes wrong – in TCP terms, we abort with a RST control packet (reset). This matters to us here because we're about to establish a fraudulent TCP connection designed to mimic one created by the Safari browser on an iPad. Kali will be very confused when we get our acknowledgment back:

  1. Scapy uses our network interface to send the forged SYN packet
  2. The captive portal web service sends a SYN-ACK back to our address
  3. The Kali Linux system itself, having not sent any SYNs, will receive an unsolicited SYN-ACK
  1. Per RFC specification, Kali decides something is wrong here and aborts with a RST packet, exposing our operating system's identity 

Well, this won't do. We have to duct-tape the mouth of our Kali box until we get through validation. It's easy enough with iptables.

iptables is the Linux firewall. It works with policy chains where rules for handling packets are defined. There are three policy categories: input, forward, and output. Input is data destined for your machine; output is data originating from your machine; and forward is for data not really destined for your machine but will be passed on to its destination. Unless you're doing some sort of routing or forwarding – like during our man-in-the-middle attack earlier in the chapter – then you won't be doing anything with the forward policy chain. For our purposes here, we just need to restrict data originating at our machine.

Extra credit if you've already realized that, if we aren't careful, we'll end up restricting the Scapy packets! So, what are we restricting, exactly? We want to restrict a TCP RST packet destined for port 80 on the gateway and coming from our Kali box. For our demonstration, we've set up the listener at 192.168.108.215 and our Kali attack box is at 192.168.108.225.

# iptables -F && iptables -A OUTPUT -p tcp --destination-port 80 --tcp-flags RST RST -s 192.168.108.225 -d 192.168.108.215 -j DROP

Let's break this down:

  • -F tells iptables to flush any currently configured rules. We were tinkering with rules for our ARP attack, so this resets everything.
  • -A means append a rule. Note that I didn't use the potentially misleading term add. Remember that firewall rules have to be in the correct order to work properly. We don't need to worry about that here as we don't have any other rules, so that's for a different discussion.
  • OUTPUT identifies the policy chain to which we're about to append a rule.
  • -p identifies the protocol, in this case TCP.
  • --destination-port and --tcp-flags are self-explanatory: we're targeting any RST control packets destined for the HTTP port.  
  • -s is our source and -d is our destination. 
  • -j is the jump, which specifies the rule target. This just defines the actual action taken. If this were omitted, then nothing would happen but the rule packet counter would increment.

The following screenshot illustrates the output of the preceding command:

We're ready to send our forged packets to the captive portal authentication page.

Fabricating the handshake with Scapy and Python

Kali Linux 2018.1 has Scapy ready to go, but it's good to make sure you have all your dependencies in order. My copy of Kali didn't have the Python ECDSA cryptography installed, for example. We don't need it here, but I don't like to have alerts when I fire up Scapy. You can run this command before we get started:

# apt-get install graphviz imagemagick python-gnuplot python-pyx python-ecdsa

You can bring up the Scapy interpreter interface by simply commanding scapy, but for this discussion, we'll be importing its power into a Python script. 

Scapy is a sophisticated packet manipulation and crafting program. Scapy is a Python program, but Python plays an even bigger role in Scapy as the syntax and interpreter for Scapy's domain-specific language. What this means for the pen tester is a packet manipulator and forger with unmatched versatility because it allows you to literally write your own network tools, on the fly, with very few lines of code – and it leaves the interpretation up to you, instead of within the confines of what a tool author imagined.

What we're doing here is a crash course in scripting with Python and Scapy, so don't be intimidated. We will be covering Scapy and Python in detail later on in the book. We'll step through everything happening here in our NAC bypass scenario so that, when we fire up Scapy in the future, it will quickly make sense. If you're like me, you learn faster when you're shoved into the pool. That being said, don't neglect curling up with Scapy documentation and some hot cocoa. The documentation on Scapy is excellent.

As you know, we set up our captive portal listener and OS fingerprinter at 192.168.108.215. Let's try to browse this address with an unmodified Firefox ESR in Kali and see what p0f picks up:

We can see in the very top line, representing the very first SYN packet received, that p0f has already identified us as a Linux client.  Remember, p0f is looking at how the TCP packet is constructed, so we don't need to wait for any HTTP requests to divulge system information. Linux fingerprints are all over the TCP three-way handshake, before the browser has even established a connection to the site.

In our example, we want to emulate an iPad (specifically, one running iOS 9.3.2 to match our user-agent spoof from earlier).  Putting on our hacker hat (the white one, please), we can put two and two together:

  • p0f has a database of signatures (p0f.fp) that it references in order to fingerprint a source
  • Scapy allows us to construct TCP packets and, with a little scripting, we can tie together several Scapy lines into a single TCP three-way handshake utility

We now have a recipe for our spoofing attack. Now, Scapy lets you construct communications in its interpreter, using the same syntax as Python, but what we're going to do is fire up nano and put together a Python script that will import Scapy. We'll discuss what's happening here after we confirm the attack works:

#!/usr/bin/python
from scapy.all import *
CPIPADDRESS="192.168.108.215"
SOURCEP=random.randint(1024,65535)
ip=IP(dst=CPIPADDRESS, flags="DF", ttl=64)
tcpopt=[("MSS",1460), ("NOP",None), ("WScale",2), ("NOP",None), ("NOP",None), ("Timestamp",(123,0)), ("SAckOK",""), ("EOL",None)]
SYN=TCP(sport=SOURCEP, dport=80, flags="S", seq=1000, window=0xffff, options=tcpopt)
SYNACK=sr1(ip/SYN)
ACK=TCP(sport=SOURCEP, dport=80, flags="A", seq=SYNACK.ack+1, ack=SYNACK.seq+1, window=0xffff)
send(ip/ACK)
request="GET / HTTP/1.1\r\nHost: " + CPIPADDRESS + "\rMozilla/5.0 (iPad; CPU OS 9_3_2 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13F69 Safari/601.1 \r\n\r\n"
PUSH=TCP(sport=SOURCEP, dport=80, flags="PA", seq=1001, ack=0, window=0xffff)
send(ip/PUSH/request)
RST=TCP(sport=SOURCEP, dport=80, flags="R", seq=1001, ack=0, window=0xffff)
send(ip/RST)

Once I'm done typing this up in nano, I save it as a .py file and chmod it to allow execution. That's it – the attack is ready:

The iptables outbound rule is set, and the script is ready to execute. Let it fly:

That's it; not very climactic on this end. But, let's take a look at the receiving end.

Voila! The OS fingerprinter is convinced that the packets were sent by an iOS device. When we scroll down, we can see the actual HTTP request with the user agent data. At this point, the NAC allows access and we can go back to doing our usual business. Don't forget to open up iptables:

# iptables -F

So what happened here, exactly? Let's break it down:

CPIPADDRESS="192.168.108.215"
SOURCEP=random.randint(1024,65535)

We're declaring a variable for the captive portal IP address and the source port. The source port is a random integer between 1024 and 65535 so that an ephemeral port is used: 

ip=IP(dst=CPIPADDRESS, flags="DF", ttl=64)
tcpopt=[("MSS",1460), ("NOP",None), ("WScale",2), ("NOP",None), ("NOP",None), ("Timestamp",(123,0)), ("SAckOK",""), ("EOL",None)]
SYN=TCP(sport=SOURCEP, dport=80, flags="S", seq=1000, window=0xffff, options=tcpopt)
SYNACK=sr1(ip/SYN)

Now we're defining the layers of the packets we will send. ip is the IP layer of our packet with our captive portal as the destination, a don't-fragment flag set, and a TTL of 64. Now, when Scapy is ready to send this particular packet, we'll simply reference ip

We define tcpopt with the TCP options we'll be using. This is the meat and potatoes of the OS signature, so this is based on our signature research.

Next we declare SYN, which is the TCP layer of our packet, defining our randomly chosen ephemeral port, the destination port 80, the SYN flag set, a sequence number, and a window size (also part of the signature). We set the TCP options with our just-defined tcpopt.  

Then, we send the SYN request with sr1. However, sr1 means send a packet, and record 1 reply. The reply is then stored as SYNACK:

ACK=TCP(sport=SOURCEP, dport=80, flags="A", seq=SYNACK.ack+1, ack=SYNACK.seq+1, window=0xffff)
send(ip/ACK)

We sent a SYN packet with sr1, which told Scapy to record the reply – in other words, record the SYN-ACK that comes back from the server. That packet is now stored as SYNACK. So, now we're constructing the third part of the handshake, our ACK. We use the same port information and switch the flag accordingly, and we take the sequence number from the SYN-ACK and increment it by one. Since we're just acknowledging the SYN-ACK and thus completing the handshake, we only send this packet without needing a reply, so we use the send command instead of sr1:

request="GET / HTTP/1.1\r\nHost: " + CPIPADDRESS + "\rMozilla/5.0 (iPad; CPU OS 9_3_2 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13F69 Safari/601.1 \r\n\r\n"
PUSH=TCP(sport=SOURCEP, dport=80, flags="PA", seq=1001, ack=0, window=0xffff)
send(ip/PUSH/request)

Now that the TCP session is established, we craft our GET request for the HTTP server. We're constructing the payload and storing it as request. Note the use of Python syntax to concatenate the target IP address and create returns and new lines. We construct the TCP layer with the PSH + ACK flag and an incremented sequence number. Finally, another send command to send the packet using the same IP layer, the newly defined TCP layer called PUSH, and the HTTP payload as request:

RST=TCP(sport=SOURCEP, dport=80, flags="R", seq=1001, ack=0, window=0xffff)
send(ip/RST)

Finally, we tidy up, having completed our duty. We build a RST packet to tear down the TCP connection we just established, and send it with the send command.

I hope I have whetted your appetite for Scapy and Python, because we will be taking these incredibly powerful tools to the next level later in this book.