Skip to content

🪝 04-03: TCP Session Hijacking


📌 Definition

TCP session hijacking is an attack where an adversary takes over an already-established TCP connection between two parties by injecting forged packets that the receiving side accepts as legitimate — without ever needing to know a password or complete a new handshake of their own.

👉 Instead of attacking the login process, session hijacking attacks the already-authenticated session that comes afterward. If a victim already typed their password and logged into a Telnet or web session, the hijacker rides in on that trust.


🔑 The Core Weakness: Sequence Numbers Are the Only "Proof"

Every TCP segment carries a sequence number and an acknowledgment number, which the receiving side uses to keep data in order and detect duplicates/loss. Critically, these numbers are also the only thing that "proves" a packet belongs to an existing connection — TCP has no separate authentication token or session key of its own.

👉 If an attacker can produce a packet with:

  • The correct source/destination IP addresses
  • The correct source/destination ports
  • A sequence number the receiver currently expects
  • A plausible acknowledgment number

...then, as far as the receiving TCP stack is concerned, that packet is a completely legitimate continuation of the session — indistinguishable from something the real sender transmitted.

💡 This is the TCP equivalent of the ARP trust problem from Module 03: the protocol accepts data based on matching a few numeric fields, with no cryptographic proof of identity behind them.


🙈 Blind Hijacking vs. On-Path Hijacking

This maps directly onto the blind vs. on-path spoofing distinction from 04-02: IP Spoofing in Attacks:

Blind Hijacking

The attacker cannot observe the target connection's traffic at all, so they must guess the current sequence number. This depends heavily on how predictable the victim server's Initial Sequence Number (ISN) generation is:

  • Old/naive TCP implementations used predictable, slowly-incrementing ISNs — making sequence numbers guessable within a small search window.
  • Modern systems use strong ISN randomization specifically to make blind hijacking impractical (see 04-05: Mitigations (SYN Cookies & Randomization)).

On-Path Hijacking (Sniffed Sequence Numbers)

The attacker is positioned to sniff the live conversation — for example, having already achieved a Man-in-the-Middle position via ARP spoofing (03-04: ARP Spoofing Attacks). Here, there's no guessing involved at all:

  • The attacker watches the real packets fly by and reads the exact current sequence and acknowledgment numbers directly out of the captured traffic.
  • The attacker crafts a forged packet using those exact numbers and injects it.

👉 On-path hijacking is dramatically more reliable and is by far the more common technique in practice, since Module 03's ARP spoofing already provides everything needed to sniff a target's traffic.


🧩 Step-by-Step: How the Attack Works

Assume two legitimate parties, a User and a Telnet Server, are mid-conversation over an established TCP connection, and the Attacker is sniffing this traffic (having positioned themselves via ARP spoofing).

Step 1: Observe the live connection

The attacker sniffs packets between User and Server, noting:

  • Source/destination IP addresses and ports (identifying the exact TCP connection)
  • The current sequence number (seq) and acknowledgment number (ack)

Step 2: Craft a forged packet

Using Scapy (see 03-02: Sniffing Tools (Scapy/tcpdump)), the attacker builds a packet that spoofs the User's IP and port, with the correct next-expected sequence/ack numbers, and the ACK flag set:

from scapy.all import IP, TCP, send

ip = IP(src="192.168.1.10", dst="192.168.1.20")   # spoofed as the User
tcp = TCP(
    sport=52344,        # the User's real source port for this session
    dport=23,           # Telnet
    flags="A",          # ACK flag — looks like normal data flow
    seq=1450112233,     # the sniffed/current sequence number
    ack=889001122       # the sniffed/current ack number
)
data = "rm -rf /important-files\n"   # malicious injected payload

pkt = ip / tcp / data
send(pkt, verbose=0)

Step 3: The server accepts the injected data

Because every field matches what the server's TCP stack currently expects for this connection, the server has no way to tell this packet apart from something the real User typed. It processes the injected command as if the legitimate user had typed it.

Step 4: Session desync (a side effect)

Once the attacker injects data, the real User's and the Server's sequence number "views" of the conversation diverge (the server has now advanced its expected sequence number based on the attacker's injected bytes, not the User's). This can cause the legitimate connection to behave oddly or drop, which is a common observable side effect of a successful hijack.


🖼️ Worked Scenario

A system administrator has an active Telnet session open to a production server to check on a background job. An attacker, already positioned via ARP spoofing on the same office LAN, has been quietly sniffing the connection. Recognizing this Telnet session by its familiar port 23 traffic, the attacker waits for a lull, then crafts and injects a single forged packet containing a destructive shell command using the sniffed sequence/ack numbers and the admin's spoofed IP/port.

From the server's perspective, the command arrived as an ordinary continuation of the admin's already-authenticated Telnet session — no login prompt, no password, no red flags. The command executes with whatever privileges that Telnet session already had.

⚠️ Note that this danger is specific to unencrypted protocols like Telnet, where sequence numbers and payload are both sent in the clear and can be freely read and matched by a sniffing attacker. Encrypted protocols like SSH prevent this precisely because the attacker cannot make sense of (or forge valid-looking) encrypted application data even if they know the raw TCP sequence numbers.


🔗 Relationship to RST Injection

Session hijacking and RST injection (04-04: RST Injection) are close siblings — both rely on forging a packet with a correctly guessed/sniffed sequence number into an existing connection. The difference is intent:

  • Session hijacking injects data to make the server do something on the attacker's behalf.
  • RST injection injects a reset flag to kill the connection outright, rather than take it over.

📌 Key Takeaways

  • TCP session hijacking injects forged packets into an already-established connection, exploiting the fact that sequence/ack numbers (not cryptographic credentials) are TCP's only "proof" that a packet belongs to a session.
  • Blind hijacking requires guessing sequence numbers and depends on weak/predictable Initial Sequence Number generation.
  • On-path hijacking uses sniffed sequence numbers from direct observation of the traffic — far more reliable, and commonly paired with ARP spoofing for positioning.
  • A forged packet with matching IP/port/sequence/ack fields is indistinguishable to the receiver from a legitimate continuation of the session.
  • Successful injection can cause visible session desync as a side effect.
  • This attack works specifically because the protocol/session is unencrypted (e.g., Telnet); encryption (SSH, TLS) defeats it because the attacker cannot construct meaningful encrypted payloads even with known sequence numbers.
  • RST injection (04-04: RST Injection) uses the identical mechanism but aims to kill the connection rather than hijack it.