Wednesday, March 30, 2011

web server version obfuscation

It seems that it's harder then I thought.
Suppose we don't want version leakage through http headers, like:

$ curl -v ""
< Server: Microsoft-IIS/7.5
< X-AspNet-Version: 2.0.50727

What we can do is:
  • to change php.ini option expose_php
  • to look at apache's ServerTokens, ServerSignature, TraceEnable options 
  • to "fix" nginx strings in source file src/http/ngx_http_header_filter_module.c (ver. 0.7.x) and src/http/ngx_http_special_response.c (look for NGINX_VER)
  • to make custom error page. Looks like the easiest way but it's also easy to forget about error pages other then 404 and 500. 

Suppose this examples:

 curl -v
< HTTP/1.0 404 Not Found
< Server: Apache
< X-Powered-By: PHP/4.3.9

Apache? No, not really. Let's look at err 400.

$ telnet 80
Escape character is '^]'.
<head><title>400 Bad Request</title></head>
<body bgcolor="white">
<center><h1>400 Bad Request</h1></center>
<hr><center>some garbage instead of nginx version</center>
Connection closed by foreign host.

telnet 80
Connected to
Escape character is '^]'.

HTTP/1.0 400 Bad Request
Content-Type: text/html
Content-Length: 349
Connection: close
Date: Tue, 29 Mar 2011 16:55:45 GMT
Server: httpd/1.4.x Gualala

<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
<html xmlns="" xml:lang="en" lang="en">
  <title>400 - Bad Request</title>
  <h1>400 - Bad Request</h1>
Connection closed by foreign host.

This response pattern from FreeBSD site leaves no doubt that this is some version of apache.