From e6e1c51e839774960598d54cb95dbc3513d8700f Mon Sep 17 00:00:00 2001 From: Darryl Nixon Date: Mon, 3 Jul 2023 00:47:36 -0700 Subject: [PATCH] Add example chat app --- examples/chat.html | 65 ++++++++++++++++++++++++++++++++++++++++++ examples/hijack.py | 70 ++++++++++++++++++++++++++++++++++++++++++++++ examples/server.py | 47 +++++++++++++++++++++++++++++++ 3 files changed, 182 insertions(+) create mode 100644 examples/chat.html create mode 100644 examples/hijack.py create mode 100644 examples/server.py diff --git a/examples/chat.html b/examples/chat.html new file mode 100644 index 0000000..1452384 --- /dev/null +++ b/examples/chat.html @@ -0,0 +1,65 @@ + + + + + WebSocket Chat + + + + +
+ + + + + + + \ No newline at end of file diff --git a/examples/hijack.py b/examples/hijack.py new file mode 100644 index 0000000..72b96bb --- /dev/null +++ b/examples/hijack.py @@ -0,0 +1,70 @@ + +from drawbridge import DrawBridge +from scapy.layers.http import HTTPResponse, HTTP +from scapy.all import IP, TCP +from scapy.packet import Raw +import json + + +def modify_websocket_chat(raw_packet): + pkt = IP(raw_packet) + + tcp0 = pkt.getlayer(TCP) + try: + jsonb = bytes(tcp0.payload)[2:] + if jsonb == b'': + return raw_packet + except IndexError: + return raw_packet + try: + json.loads(jsonb.decode("utf-8")) + except (json.decoder.JSONDecodeError, UnicodeDecodeError): + return raw_packet + + tcp0.payload = Raw(bytes(tcp0.payload)[:2] + b'{"sender": "hackerboy23", "message": "boom"}') + del pkt[IP].len + del pkt[IP].chksum + del pkt[TCP].chksum + + return bytes(pkt) + + +black_png = ( + b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\n\x00\x00' + b'\x00\n\x08\x06\x00\x00\x00\x8d2\xcf\xbd\x00\x00\x00\x0cIDATx' + b'\xda\xed\xc1\x01\r\x00\x00\x00\xc2\xa0\xf5H\xfd\x00\x00\x00' + b'\x00IEND\xaeB`\x82' +) +black_payload = HTTP(bytes( + "HTTP/1.1 200 OK\r\nContent-Type: image/png\r\n\r\n", 'utf-8') + black_png + ) +black_len = str(len(black_png)).encode() + + + +def modify_img_request(raw_packet): + pkt = IP(raw_packet) + + if pkt.haslayer(HTTPResponse): + http_layer = pkt.getlayer(HTTP) + http_response = pkt.getlayer(HTTPResponse) + + if http_response.fields.get('Content_Type') == b'image/png': + print("Found PNG file...") + + # http_layer.payload = black_payload + pkt.show2() + + if pkt.haslayer(TCP): + http_layer.fields['Content_Length'] = black_len + del pkt[TCP].chksum + del pkt[IP].chksum + del pkt[IP].len + else: + return raw_packet + return bytes(IP(bytes(pkt))) + + +db = DrawBridge() +db.add_queue(modify_websocket_chat, queue=2, src_port=80) +db.run() diff --git a/examples/server.py b/examples/server.py new file mode 100644 index 0000000..eb4c0a8 --- /dev/null +++ b/examples/server.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python + +import asyncio +import websockets +import json + +connected = set() + + +def sanitize(message): + # A very secure sanitization function. + return message.replace('<', '').replace('>', '') + + +async def handler(websocket): + try: + connected.add(websocket) + print(f"Connected: {websocket.remote_address[0]}") + while True: + try: + message = await websocket.recv() + sanitized_message = sanitize(message) + sanitized_sender = sanitize(websocket.remote_address[0]) + + payload = json.dumps({ + 'sender': sanitized_sender, + 'message': sanitized_message + }) + + print(f"{websocket.remote_address[0]} says: {message}") + for conn in connected: + await conn.send(payload) + + except Exception: + break + finally: + print(f"Disconnected: {websocket.remote_address[0]}.") + connected.remove(websocket) + + +async def main(): + async with websockets.serve(handler, "", 80, compression=None): + await asyncio.Future() + + +if __name__ == "__main__": + asyncio.run(main())