The go-to resource for upgrading Ruby, Rails, and your dependencies.

CVE-2008-1891: WEBrick Directory Traversal in Ruby


When engineering robust software systems, developers often implicitly trust the components included in a language’s standard library. WEBrick, Ruby’s built-in HTTP server, is a prime example of a tool developers rely on for quick prototyping, local development, and occasionally, lightweight production services. However, this trust requires verification. In 2008, a critical directory traversal and source code disclosure vulnerability designated as CVE-2008-1891 was discovered in WEBrick, highlighting the risks of complex cross-platform file handling.

This vulnerability permitted remote attackers to read the raw source code of CGI scripts instead of executing them, specifically when WEBrick was hosted on DOS-ish filesystems. By examining the technical mechanics of CVE-2008-1891, engineers can better understand the nuances of cross-platform security and the architectural decisions necessary to protect file-serving applications.

Mechanics of the WEBrick Vulnerability

The core issue in CVE-2008-1891 centered around how WEBrick validated requested file extensions before serving them to the client. The vulnerability exploited a discrepancy between how WEBrick interpreted file paths and how the underlying Windows operating system handled them.

Extension Handling Discrepancies

WEBrick relied on exact file extensions to determine how to serve a file. If a requested file ended in .cgi, WEBrick processed it as an executable script and returned its output. If the extension was not recognized as executable, WEBrick fell back to serving the file as raw static content, essentially plain text.

Windows filesystems — like NTFS and FAT — possess a specific quirk: they silently ignore trailing spaces and trailing dots in file paths. For example, the operating system treats script.cgi, script.cgi., and script.cgi as the exact same file.

The Exploit Vector

Attackers exploited this behavior by crafting HTTP requests that appended a trailing dot, space, or their URL-encoded equivalents to the target script:

  • http://server/script.cgi.
  • http://server/script.cgi%2e (encoded dot)
  • http://server/script.cgi%20 (encoded space)
  • http://server/script.cgi+ (encoded plus, often parsed as space)

When WEBrick received such a request, it saw the requested extension as .cgi. or .cgi rather than .cgi. Because it did not recognize this modified extension as a script, WEBrick::HTTPServlet::FileHandler decided to serve it as static text. However, when WEBrick asked the underlying operating system to open the file, the filesystem stripped the trailing character and returned the actual script.cgi file. The server then sent the raw source code of the script to the attacker.

The Impact of Source Code Exposure

The primary impact of CVE-2008-1891 was the unintended disclosure of arbitrary CGI file source code.

While reading a script’s source code might seem less critical than remote code execution, CGI scripts frequently contained sensitive information. Hardcoded database credentials, API keys, secret tokens, and proprietary business logic were often embedded directly in these files. Access to this information could easily be leveraged by attackers to compromise the broader system or backend databases. The CVSS score for this vulnerability was 5.0 (Medium), reflecting the serious nature of this information disclosure.

Remediation and the Patch

The vulnerability affected Ruby versions 1.8.4 and earlier, as well as unpatched versions of 1.8.5, 1.8.6, 1.8.7, and 1.9.0.

To fix the vulnerability, the Ruby core developers patched lib/webrick/httpservlet/filehandler.rb to explicitly detect and reject files with Windows-ambiguous trailing characters or alternate data streams. They introduced a windows_ambiguous_name? check:

def windows_ambiguous_name?(name)
  return true if /[. ]+\z/ =~ name
  return true if /::\$DATA\z/ =~ name
  return false
end

The server’s file checker was updated to raise a 404 Not Found error if a request matched this pattern. This stopped the exploit before the filesystem could truncate the request and serve the raw file.

The fix was included in the following releases:

  • Ruby 1.8.5-p231
  • Ruby 1.8.6-p230
  • Ruby 1.8.7-p22
  • Ruby 1.9.0-2

By understanding the mechanics of CVE-2008-1891, developers can better appreciate the complexities of relying on filesystem abstractions and the importance of rigorous input validation, especially when dealing with cross-platform applications. Modern Ruby development has since extracted WEBrick into an external gem, but the lessons from this vulnerability remain relevant for any file-serving architecture.

Sponsored by Durable Programming

Need help maintaining or upgrading your Ruby on Rails application? Durable Programming specializes in keeping Rails apps secure, performant, and up-to-date.

Hire Durable Programming