VYPR
High severityNVD Advisory· Published Sep 22, 2009· Updated Apr 23, 2026

CVE-2009-3287

CVE-2009-3287

Description

Thin web server before 1.2.4 trusts X-Forwarded-For header, enabling remote attackers to spoof client IP addresses.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Thin web server before 1.2.4 trusts X-Forwarded-For header, enabling remote attackers to spoof client IP addresses.

Vulnerability

In Thin web server versions before 1.2.4, the lib/thin/connection.rb file relies on the X-Forwarded-For HTTP header to determine the client's IP address. This is used in the Connection#remote_address method. The code path is reachable for any request that includes the X-Forwarded-For header [1][2].

Exploitation

An attacker can send a crafted HTTP request with a modified X-Forwarded-For header to spoof the client IP address. No authentication or special network position is required; the attacker only needs to make a request to the Thin server [1][3].

Impact

By spoofing the IP address, an attacker can hide their true identity and location. This can be used to bypass IP-based access controls, logging, or rate limiting. The vulnerability does not directly lead to code execution or data disclosure, but enables further malicious activities to be attributed to a false source [1][3].

Mitigation

The fix was released in Thin version 1.2.4. The commit [2] shows that the remote_address method was changed to use the socket address instead of the forwarded-for header. Users should upgrade to Thin 1.2.4 or later. No workarounds are documented for earlier versions [2][4].

AI Insight generated on May 23, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
thinRubyGems
< 1.2.41.2.4

Affected products

22
  • Macournoyer/Thin21 versions
    cpe:2.3:a:macournoyer:thin:*:*:*:*:*:*:*:*+ 20 more
    • cpe:2.3:a:macournoyer:thin:*:*:*:*:*:*:*:*range: <=1.2.2
    • cpe:2.3:a:macournoyer:thin:0.4.0:*:*:*:*:*:*:*
    • cpe:2.3:a:macournoyer:thin:0.4.1:*:*:*:*:*:*:*
    • cpe:2.3:a:macournoyer:thin:0.5.0:*:*:*:*:*:*:*
    • cpe:2.3:a:macournoyer:thin:0.5.1:*:*:*:*:*:*:*
    • cpe:2.3:a:macournoyer:thin:0.5.2:*:*:*:*:*:*:*
    • cpe:2.3:a:macournoyer:thin:0.5.3:*:*:*:*:*:*:*
    • cpe:2.3:a:macournoyer:thin:0.5.4:*:*:*:*:*:*:*
    • cpe:2.3:a:macournoyer:thin:0.6.0:*:*:*:*:*:*:*
    • cpe:2.3:a:macournoyer:thin:0.6.3:*:*:*:*:*:*:*
    • cpe:2.3:a:macournoyer:thin:0.6.4:*:*:*:*:*:*:*
    • cpe:2.3:a:macournoyer:thin:0.7.0:*:*:*:*:*:*:*
    • cpe:2.3:a:macournoyer:thin:0.7.1:*:*:*:*:*:*:*
    • cpe:2.3:a:macournoyer:thin:0.8.0:*:*:*:*:*:*:*
    • cpe:2.3:a:macournoyer:thin:0.8.1:*:*:*:*:*:*:*
    • cpe:2.3:a:macournoyer:thin:0.8.2:*:*:*:*:*:*:*
    • cpe:2.3:a:macournoyer:thin:1.0.0:*:*:*:*:*:*:*
    • cpe:2.3:a:macournoyer:thin:1.1.0:*:*:*:*:*:*:*
    • cpe:2.3:a:macournoyer:thin:1.1.1:*:*:*:*:*:*:*
    • cpe:2.3:a:macournoyer:thin:1.2.0:*:*:*:*:*:*:*
    • cpe:2.3:a:macournoyer:thin:1.2.1:*:*:*:*:*:*:*
  • ghsa-coords
    Range: < 1.2.4

Patches

1
7bd027914c5f

Fix Remote address spoofing vulnerability in Connection#remote_address [Alexey Borzenkov]

https://github.com/macournoyer/thinmacournoyerAug 12, 2009via ghsa
5 files changed · +7 10
  • CHANGELOG+1 0 modified
    @@ -1,4 +1,5 @@
     == 1.2.3
    + * Fix Remote address spoofing vulnerability in Connection#remote_address [Alexey Borzenkov]
      * Fix uninitialized constant ActionController::Dispatcher error with Rails 1.2.3 [Chris Anderton] [#103 state:resolved]
     
     == 1.2.2 I Find Your Lack of Sauce Disturbing release
    
  • lib/thin/connection.rb+1 1 modified
    @@ -180,7 +180,7 @@ def threaded?
     
         # IP Address of the remote client.
         def remote_address
    -      @request.forwarded_for || socket_address
    +      socket_address
         rescue Exception
           log_error
           nil
    
  • lib/thin/request.rb+0 5 modified
    @@ -21,7 +21,6 @@ class Request
         HTTP_VERSION      = 'HTTP_VERSION'.freeze
         HTTP_1_0          = 'HTTP/1.0'.freeze
         REMOTE_ADDR       = 'REMOTE_ADDR'.freeze
    -    FORWARDED_FOR     = 'HTTP_X_FORWARDED_FOR'.freeze
         CONTENT_LENGTH    = 'CONTENT_LENGTH'.freeze
         CONNECTION        = 'HTTP_CONNECTION'.freeze
         KEEP_ALIVE_REGEXP = /\bkeep-alive\b/i.freeze
    @@ -123,10 +122,6 @@ def remote_address=(address)
           @env[REMOTE_ADDR] = address
         end
     
    -    def forwarded_for
    -      @env[FORWARDED_FOR]
    -    end
    -
         def threaded=(value)
           @env[RACK_MULTITHREAD] = value
         end
    
  • lib/thin/version.rb+2 2 modified
    @@ -6,11 +6,11 @@ class PlatformNotSupported < RuntimeError; end
       module VERSION #:nodoc:
         MAJOR    = 1
         MINOR    = 2
    -    TINY     = 2
    +    TINY     = 3
         
         STRING   = [MAJOR, MINOR, TINY].join('.')
         
    -    CODENAME = "I Find Your Lack of Sauce Disturbing".freeze
    +    CODENAME = "Astroboy".freeze
         
         RACK     = [1, 0].freeze # Rack protocol version
       end
    
  • spec/connection_spec.rb+3 2 modified
    @@ -40,9 +40,10 @@
         @connection.process
       end
       
    -  it "should return HTTP_X_FORWARDED_FOR as remote_address" do
    +  it "should not return HTTP_X_FORWARDED_FOR as remote_address" do
         @connection.request.env['HTTP_X_FORWARDED_FOR'] = '1.2.3.4'
    -    @connection.remote_address.should == '1.2.3.4'
    +    @connection.stub!(:socket_address).and_return("127.0.0.1")
    +    @connection.remote_address.should == "127.0.0.1"
       end
       
       it "should return nil on error retreiving remote_address" do
    

Vulnerability mechanics

Root cause

"The `remote_address` method in `Connection` trusts the `X-Forwarded-For` HTTP header over the actual socket address, allowing client IP spoofing."

Attack vector

An attacker sends an HTTP request to the Thin server with a crafted `X-Forwarded-For` header containing an arbitrary IP address. The vulnerable `Connection#remote_address` method [patch_id=21] returns the value of `HTTP_X_FORWARDED_FOR` (via `Request#forwarded_for`) instead of the actual TCP socket address. This allows the attacker to masquerade as any IP address, bypassing IP-based access controls, rate limiting, or audit logging. No authentication or special network position is required; the attacker only needs to be able to send HTTP requests to the server.

Affected code

The vulnerability is in `lib/thin/connection.rb` at the `remote_address` method, which previously returned `@request.forwarded_for || socket_address`. The `forwarded_for` method in `lib/thin/request.rb` simply read `HTTP_X_FORWARDED_FOR` from the environment without any validation. The patch removes both the `forwarded_for` method and the fallback logic.

What the fix does

The patch removes the `forwarded_for` method from `Request` [patch_id=21] and changes `Connection#remote_address` to always call `socket_address` instead of falling back to the `X-Forwarded-For` header. The spec test is updated to assert that even when `HTTP_X_FORWARDED_FOR` is set, the returned address is the socket address (127.0.0.1). This closes the spoofing vector by no longer accepting client-supplied header values as the authoritative remote address.

Preconditions

  • networkAttacker must be able to send HTTP requests to the Thin server.
  • inputAttacker must include a crafted X-Forwarded-For header in the HTTP request.

Generated on May 19, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

6

News mentions

0

No linked articles in our index yet.