Preventing Information Leaks, Part 3

Written on 10:44:00 AM by S. Potter

In the third part of the how to prevent information leaks blog post series, we will look for unguarded "hidden" files where we can garnish quite a bit of information. Make sure you check out part 1 and part 2 on how to prevent information leaks in web applications before continuing.

Seek Unguarded Hidden Files

For web applications that use deployment tools that pull code from code repositories, you can find out quite a bit of information about the code repository (e.g. host, path, usernames, file listings), by finding unguarded hidden files. One obvious example especially in the SVN saturated Rails world is the path /.svn/entries and similar URLs. You will want to make sure the following URIs are not accessible on your public sites if you use Subversion (SVN):
  • /.svn/entries
  • /javascripts/.svn/entries
  • /stylesheets/.svn/entries
  • /images/.svn/entries
If you are using a superior SCM for your project like Git you ought to be looking for the following:
  • /.git/config
  • /javascripts/.git/config
  • /stylesheets/.git/config
  • /images/.git/config
If your project is still in the stone-age using CVS, then check the following:
  • /CVS/Entries
  • /javascripts/CVS/Entries
  • /stylesheets/CVS/Entries
  • /images/CVS/Entries
Adapt these patterns for your application framework default structures. The above is for Rails or Rails-based frameworks (e.g. Merb). When I first tried this last week on the Rails top 10 sites, three out of ten of these sites exposed their SVN information (and last week I had only checked SVN, no Git or CVS URIs). Since last week at least one of those sites have fixed the problem! What information is exposed in these files? Quite a lot of information. Do you want potential hackers knowing:
    code repository URL (host, port, protocol, path)
  • usernames of committers
  • code repository listings of files in a directory
All these things are not things you really want the potential hacker knowing. On my travels investigating the top 100 Rails sites I found one top 20 site that exposed enough information from their SVN entries file that I found a prototyping directory that included a "specs.rtf" document, which I was able to download. The document was not very uninteresting (at least not to me), but if they had written more in-depth specifications in the document, it may have served as a nice guide for a potential hacker to garnish enough information about their setup to take over! Moral of this story? Guard hidden files. I recommend "forbidding" access to all troublesome path regex patterns. For example, one of the LigHTTPd servers I administer has the following at the top of the configuration file:

$HTTP["url"] =~ ".*/\..*" {
  url.access-deny = ("")
}
For Apache httpd servers I use something like the following in the httpd.conf:

<DirectoryMatch "^.*\..*">
  ErrorDocument 403 /403.html
  Order allow,deny
  Deny from all
  Satisfy All
</DirectoryMatch>
Nginx configuration might look something like:

location ^~ /\..* {
  deny    all;
}
This guards against URLs like: /.svn/entries, .git/config as well as .htpasswd, etc. This means that only some script-kiddie hackers will mistakenly think you are using one SCM system instead of another, but they will never be able to know for sure which SCM you use or any information about your code repository. Forbidding access to all paths containing "/." somewhere in the URL is generally a good idea (IMHO) as sometimes people change web servers and leave "secret" files in the directory structure, but the new server doesn't know that, for example, .htaccess or .htpasswd is "special", so it will just serve it without thinking.

Preventing Information Leaks, Part 2

Written on 1:04:00 PM by S. Potter

Continuing the series that looks at how to prevent information leakage, today we look at the information leakage from web server HTTP headers.

HTTP Header Leakage

Let's look at the information potential hackers can get from HTTP headers from just a GET / HTTP request. Let us look at http://www.cnn.com:
$ curl -I http://www.cnn.com
HTTP/1.1 200 OK
Date: Thu, 07 Feb 2008 15:22:32 GMT
Server: Apache
Accept-Ranges: bytes
Cache-Control: max-age=60, private
Expires: Thu, 07 Feb 2008 15:23:23 GMT
Vary: Accept-Encoding,User-Agent
Content-Type: text/html
X-Pad: avoid browser bug
Content-Length: 90458
This example is pretty decent. What you want to look for is the Server HTTP header value. In this case it is just "Apache". Now it does identify the web server used, but it doesn't pinpoint the version being used. Now I am going to try a popular Rails website:

HTTP/1.1 200 OK
Date: Thu, 07 Feb 2008 15:25:34 GMT
Server: Apache/2.2.2 (FreeBSD) mod_ssl/2.2.2 OpenSSL/0.9.8b DAV/2 PHP/5.1.4 SVN/1.3.2 mod_vd/2.0 mod_fastcgi/2.4.2 proxy_html/2.5
Last-Modified: Thu, 07 Feb 2008 14:58:58 GMT
ETag: "4da437-36ac-b69b1080"
Accept-Ranges: bytes
Content-Length: 13996
Vary: Accept-Encoding
Content-Type: text/html
In this case we can see what OS Apache is running on and the version of Apache. Not only this, but we see all the enabled modules in Apache and their respective versions. IMHO this is too much information especially considering this site supposedly (at least as far as I know) host the site on a fully controlled environment (either dedicated or VPS with root access). Applications on shared hosts cannot help this much without assistance from the shared hosting company. I have a couple of very small sites that get little traffic on a shared host, so I appreciate this obstacle. Moral of this story: If you have full control over your environment you should always either change the "Server" HTTP header to something generic (e.g. "Apache" as in the CNN example) or disable it from being returned to the client. This setting is very easy in Apache, LigHTTPd and NGinx. I assume this wouldn't be difficult in LiteSpeed either, but I do not have configuration experience with LiteSpeed. Apache configuration:
Header unset Server
LigHTTPd configuration:
server.tag = ""
NGiNX configuration:
server_tokens off;
Also make sure there aren't any other headers that give away too much information. Especially look at the X- HTTP headers.

DataMapper vs. ActiveRecord

Written on 12:17:00 PM by S. Potter

Today I came across a thread on ruby-talk where I responded to the age old question of which Ruby ORM (specifically DM vs. AR). I responded based on my production use of AR, development use of DM and my understanding of Fowler's PoEA of the same names that I have applied in Java and Python countless times. As some readers of this blog might find this discussion interesting, I am linking to my response to the DataMapper vs. ActiveRecord discussion here. The executive summary (for the infinitely lazy) is:

It appears that if DataMapper (the Ruby library) is able to sufficiently hide enough database logic in more complex business logic scenarios, then the DM library might be more beneficial to use when using a legacy database schema where you are not able to create primarily isomorphic relationships between class attributes and table columns. Whereas AR would be a slam dunk and simpler to use in isomorphic schema scenarios where you have control over the database schema.
I will be returning to the Preventing Information Leaks series on Monday/Tuesday (it is already written, I just need to publish).

Preventing Information Leaks, Part 1

Written on 10:04:00 AM by S. Potter

Before I start I want to mention that the techniques suggested in this blog post are for readers to use to secure their own web applications. This does not mean that you can take over the server with these techniques without further hacking, but these steps provide a lot of information about the environment the web application is deployed to or developed using, unless system administrators/engineers or software engineers prevent this information leakage. Some of these techniques exploit settings that are usually found in Rails when default settings are used, but web applications written in different frameworks may also use these settings, which leak information. This all just comes down to thinking through the security scenarios. Just like developers need to consider the usage of their applications or APIs or frameworks from the user perspective, those tasked with securing up their applications need to consider how potential hackers might try to access key information to help them hack your systems.

Identifying the framework or "stack"

Let us check if your application smells too much like you are using a particular framework or another. This may or may not be terrible, BUT if you can tell which version of the framework you are using from publicly accessible information on your site, then you are leaking too much information. In fact, some firms/developers advertise very publicly which frameworks or stacks they use, but they usually try not to talk too much about the exact versions they use. For example, if an application responds with a 200 OK HTTP status for the majority of the following URLs, it is VERY likely it is a Rails application:
  • /javascripts/application.js
  • /404.html
  • /500.html
  • /422.html
In the case of the last URL, we can identify that the application is written using Rails 2.0. We can also look at the 404 to see if it looks like the default looking 404 file for different versions of Rails. If /422.html doesn't exist we might still be able to tell the difference between Rails 1.1 and 1.2 applications by what /404.html looks like. Moral of this story: At a minimum always change the default error pages in your Rails application to fit your design. Also consider changing the URLs of the error pages too. Not only does the redesign prevent potential hackers from identifying which version of Rails you might be using it also looks more professional and makes the user experience in case of an error a little more acceptable! If you are not using Rails, think about what files are created by default by your framework and change things around a little to prevent information leakage. I will continue this series in subsequent parts. Stay tuned!