TCP Fuzzing with Scapy

Published: 2012-09-13
Last Updated: 2012-09-13 03:07:16 UTC
by Mark Baggett (Version: 1)
2 comment(s)

Greetings ISC Readers!   Today I wanted to share a technique that I find quite useful when I fuzz TCP applications with scapy.   Scapy is a Python module used for packet parsing and packet crafting.   With scapy you can create just about any packet your heart desires, transmit it to a target, capture the response and respond again accordingly.  It is an excellent tool to use for fuzzing network protocols.    But it does require a bit of work when fuzzing TCP protocols because you need to track the sequence and acknowledgement numbers.   There are countless examples of this on the internet, but let's look at it here briefly.   To establish a three way handshake you could do the following.  

First you start Python, import scapy and craft your SYN packet. 

# python
>>> from scapy.all import *

>>> tcp_syn=IP(src="192.168.1.1", dst="10.1.1.1")/TCP(dport=9000, flags="S", seq=10000)

Then we transmit our SYN packet and capture the SYN/ACK from the remote host.

>>> tcp_syn_ack=srp1(tcp_syn)

Now you can calculate the final ACK and transmit it.


>>> tcp_ack=IP(src="192.168.1.1", dst="10.1.1.1")/TCP(dport=9000, flags="A", seq=tcp_syn_ack.ack, ack=tcp_syn_ack.syn+1)
>>> tcp_pack1=srp1(tcp_ack)

Then you can transmit your crafted packet to the remote listener as long as you calculate and send the correct sequence numbers.   There are a couple of downsides to this technique.   First, you have to track the sequence numbers and acknowledgement numbers yourself and increment them as you transmit data.   Second, because these are crafted packet, the real TCP stack on your host will send RESETS to the unexpected responses.  You have to add some IPTABLES rules to block these RESETS from the real TCP stack.   There is another way to do this that can help with these problems.  

If you just want to shoot your packets at a TCP target, tracking sequence and acknowledgement numbers isn't necessary.  Instead you can use Python sockets to establish the connection, then convert the existing socket to a scapy stream.   Once it is a scapy stream you can use all of the normal scapy methods to transmit crafted packets over the established socket.   Using this method you don't have to track the TCP sequence numbers and can focus on creating and transmitting your fuzzing packets.    

Here is an example.  We start the same way and importing scapy.   Then we establish a normal Python Socket connection like this:

>>> from scapy.all import *
>>> mysocket=socket.socket()
>>> mysocket.connect(("10.1.1.1",9000))

With one simple call to "connect()" the TCP Handshake is completed.  But this is just a normal Python socket object.  To use it in scapy you need to create a  "StreamSocket()" object that is based on the established socket.   You can create a StreamSocket object like this:


>>> mystream=StreamSocket(mysocket)

The resulting "mystream" object is a scapy object that can be used to transmit crafted packets across the existing socket.   The mystream object supports the same .recv(), .send(), .sr(), .sr1() and even the sniff() methods that you have with other scapy objects.  Now all you have to do is craft a packet and send it to your target.


>>> ascapypacket=IP(dst="10.1.1.1")/TCP(dport=9000)/fuzz(Raw())
>>> mystream.send(ascapypacket)
1109
>>> mystream.send(ascapypacket)
1091
>>>

That is all there is to it.   I hope you find this technique as useful as I do for fuzzing TCP services.     Do you have another technique or another way to apply this technique?   Leave a comment.


Join me in San Antonio Texas November 27th for SANS 504 Hacker Techniques, Exploits and Incident Response!  Register Today!!

Mark Baggett

Twitter: @MarkBaggett
 

2 comment(s)

Comments

Just stumbled over that - so sorry, I'm a little late with my comment.

Thank you for the idea & solution. One small question: What is the intention
of sending the IP- and TCP-layer over the socket - or - is it just a typo
to test the attention of the audience?

Anyway: thank you.
Hi Mark,

Excellent writeup!! I am looking for the same thing but instead of connect I need to listen for a connection and then pass that socket details to the scapy sockstream. I have used the python socket module. Any help would be highly appreciated. Thanks.

Diary Archives