55 lines
1.5 KiB
YAML
55 lines
1.5 KiB
YAML
id: tcp-block-repeated-byte-threshold
|
|
name: Block repeated-byte flood
|
|
protocol: tcp
|
|
description: Closes connections that send suspiciously long runs of the same byte.
|
|
category: tcp
|
|
family: tcp-hardening
|
|
tags:
|
|
- bof
|
|
- repeated-byte
|
|
- tcp
|
|
- block
|
|
action: block
|
|
summary: Closes connections that send suspiciously long runs of the same byte.
|
|
behavior: Measures the longest repeated-byte run in each client message, logs the
|
|
byte and run length, and closes the TCP flow on threshold hit.
|
|
source_url: https://docs.mitmproxy.org/stable/addons/examples/
|
|
code: |
|
|
import logging
|
|
|
|
from mitmproxy import tcp
|
|
|
|
MAX_REPEAT = 128
|
|
|
|
|
|
def longest_run(data: bytes) -> tuple[int, int]:
|
|
best_byte = -1
|
|
best_run = 0
|
|
current_byte = -1
|
|
current_run = 0
|
|
for byte in data:
|
|
if byte == current_byte:
|
|
current_run += 1
|
|
else:
|
|
current_byte = byte
|
|
current_run = 1
|
|
if current_run > best_run:
|
|
best_byte = byte
|
|
best_run = current_run
|
|
return best_byte, best_run
|
|
|
|
|
|
def tcp_message(flow: tcp.TCPFlow) -> None:
|
|
message = flow.messages[-1]
|
|
if not message.from_client:
|
|
return
|
|
repeated_byte, run_length = longest_run(message.content)
|
|
if run_length > MAX_REPEAT:
|
|
logging.warning(
|
|
"[tcp-block-repeated-byte-threshold] blocked byte=0x%02x run=%d",
|
|
repeated_byte,
|
|
run_length,
|
|
)
|
|
message.drop()
|
|
flow.kill()
|