> your AI agent picks dependencies from memory; give it dated facts — try starlog.dev ↗ vet your agent's deps ↗ vibe-coding is fine. vibe-importing isn’t. — try starlog.dev ↗ vibe-importing isn’t fine ↗ your agent has never seen your private packages — try starlog.dev ↗ facts for private packages ↗ a linter for the dependencies your AI agent picks — try starlog.dev ↗ a linter for agent deps ↗

Back to Articles

Squirtle: The 2008 NTLM Attack Toolkit That Exposed Browser Authentication's Fatal Flaw

[ View on GitHub ]

Squirtle: The 2008 NTLM Attack Toolkit That Exposed Browser Authentication's Fatal Flaw

Hook

In 2008, convincing someone to click a link on the company intranet was all it took to capture their Windows password hash—no phishing page required, no credentials typed, just automatic authentication doing exactly what it was designed to do.

Context

Before Squirtle emerged in 2008, enterprise security teams widely trusted NTLM authentication as a convenient single sign-on mechanism for internal applications. The promise was seamless: users logged into their Windows workstation once, and Internet Explorer would automatically authenticate them to any internal web application without additional prompts. No more password fatigue, no more help desk calls for forgotten credentials.

The problem was that this convenience relied on browsers making trust decisions based on network location. When a browser determined it was connecting to an intranet resource—typically anything on the local network or explicitly added to the Trusted Sites zone—it would silently send the user's NTLM credentials without asking. Squirtle weaponized this behavior by setting up a malicious web server inside the corporate network that masqueraded as a legitimate intranet resource. When victims clicked links or loaded images pointing to the Squirtle server, their browsers dutifully handed over NTLM authentication challenges containing password hashes that could be cracked offline. This wasn't a vulnerability in the traditional sense; it was the authentication protocol working exactly as designed, just exploited by an attacker who'd gained a foothold inside the network perimeter.

Technical Insight

Squirtle Core

HTTP Request

No Auth Header

401 + Static Nonce

NTLM Type 3 Response

Parse Credentials

Extract Hash + Metadata

Save to SQLite

Query Captures

Export Hashes

Browser Client

WEBrick Server

NTLM Challenge Handler

Type 3 Message Parser

Credential Storage

ActiveRecord Database

REST API

Penetration Testing Tools

System architecture — auto-generated

Squirtle's architecture is deceptively simple: a WEBrick-based Ruby web server that responds to HTTP requests with NTLM authentication challenges, captures the responses, and stores them in a SQLite database via ActiveRecord. The elegance lies in how it manipulates the NTLM handshake to maximize cryptographic weakness.

The NTLM authentication flow normally works in three phases: the client announces support for NTLM, the server responds with a challenge (a random 8-byte nonce), and the client encrypts this challenge with a hash derived from the user's password. Squirtle's critical design decision was using a static, attacker-controlled nonce instead of a random one. Here's the core of how it sets up the challenge:

class NTLMCaptureServlet < WEBrick::HTTPServlet::AbstractServlet
  STATIC_NONCE = "\x01\x02\x03\x04\x05\x06\x07\x08"
  
  def do_GET(request, response)
    auth_header = request['Authorization']
    
    if auth_header.nil?
      # No auth provided, send NTLM challenge
      challenge = build_ntlm_challenge(STATIC_NONCE)
      response['WWW-Authenticate'] = "NTLM #{Base64.encode64(challenge)}"
      response.status = 401
    elsif auth_header =~ /^NTLM (.+)$/
      # Client sent NTLM response, capture it
      ntlm_response = Base64.decode64($1)
      
      if is_type3_message?(ntlm_response)
        credentials = parse_type3_message(ntlm_response)
        store_capture(credentials, request.peeraddr)
        response.status = 200
        response.body = "<html><body>Authentication successful</body></html>"
      end
    end
  end
end

This static nonce is what makes the captured hashes practical to crack. With a known challenge value, attackers can pre-compute rainbow tables or use GPU-accelerated tools like hashcat to brute-force the password that produced the captured response. A random nonce would require computing attacks from scratch for each capture, but the static approach turns this into a lookup problem for common passwords.

The tool's integration capabilities were ahead of their time. Squirtle exposed an API endpoint that allowed other tools to query captured credentials programmatically. This meant penetration testers could build automated workflows: deploy Squirtle on a compromised internal host, use social engineering or DNS poisoning to redirect traffic to it, then have their attack framework automatically retrieve and crack the captured hashes:

class CredentialsAPI < WEBrick::HTTPServlet::AbstractServlet
  def do_GET(request, response)
    response['Content-Type'] = 'application/json'
    
    case request.path
    when '/api/captures'
      # Return all captured NTLM responses
      captures = NTLMCapture.all.map do |c|
        {
          username: c.username,
          domain: c.domain,
          challenge: Base64.encode64(STATIC_NONCE),
          response: c.ntlm_response,
          timestamp: c.captured_at,
          source_ip: c.source_ip
        }
      end
      response.body = captures.to_json
    when /\/api\/captures\/(\d+)\/crack/
      # Integrate with external cracking service
      capture = NTLMCapture.find($1)
      response.body = format_for_hashcat(capture).to_json
    end
  end
end

The database persistence layer using ActiveRecord was practical for real-world assessments where multiple testers needed to review captured credentials across days-long engagements. It also enabled tracking which users had been compromised and correlating credential captures with network reconnaissance data.

What made Squirtle particularly dangerous was its passive nature. Unlike active attacks that generated network anomalies, Squirtle simply waited for browsers to initiate connections. An attacker could embed a single-pixel image in an internal wiki page pointing to the Squirtle server, and every employee who viewed that page would silently authenticate. The HTTP access logs would show legitimate-looking requests, and most intrusion detection systems in 2008 wouldn't flag internal HTTP traffic as suspicious.

Gotcha

Squirtle's effectiveness depended entirely on network positioning and browser trust configurations. It only works when deployed inside the corporate network or in a network segment that browsers consider "local intranet." External attackers can't leverage it remotely because modern browsers won't send NTLM credentials to internet zones, even if the user clicks a malicious link. You need initial access to the internal network first, making this a post-exploitation tool rather than an initial compromise vector.

The bigger limitation is its age. Written for Ruby 1.8.6 in 2008, Squirtle hasn't been updated in over 15 years. Attempting to run it on modern Ruby versions (2.x or 3.x) will fail due to breaking changes in WEBrick's API and ActiveRecord's interface. Even if you patch it to work with current Ruby, modern browser security controls have evolved significantly. Internet Explorer—which had the most permissive NTLM auto-authentication behavior—is deprecated. Current browsers like Edge, Chrome, and Firefox have stricter zone detection, Extended Protection for Authentication (EPA) support, and better warning systems for authentication prompts outside trusted contexts. Corporate networks that have migrated to Kerberos authentication or enforce NTLMv2-only policies with channel binding make the captured hashes significantly harder to crack, sometimes impossible without relay attacks rather than simple cracking. The static nonce approach that made Squirtle effective against NTLMv1 is less viable against properly configured NTLMv2 with modern safeguards.

Verdict

Use if: You're studying the history of Windows authentication vulnerabilities in a controlled lab environment, teaching a security course on why legacy protocols should be disabled, or documenting why your organization needs to migrate away from NTLM. It's an excellent educational tool for demonstrating why implicit trust based on network location was a flawed security model. Skip if: You're conducting actual red team engagements or penetration tests in 2024. The tool is unmaintained, incompatible with modern environments, and has been superseded by actively developed alternatives like Responder (for LLMNR/NBNS poisoning plus NTLM capture), Inveigh (PowerShell/C# with current Windows support), and Impacket's ntlmrelayx (for sophisticated relay attacks that bypass modern protections). These modern tools handle NTLMv2, support relay attacks that circumvent cracking requirements entirely, and integrate with current attack frameworks. Squirtle belongs in a security museum, not your operational toolkit—but it's worth understanding what it taught us about authentication security.