This site is the archived OWASP Foundation Wiki and is no longer accepting Account Requests.
To view the new OWASP Foundation website, please visit https://owasp.org

Difference between revisions of "Fingerprint Web Application Framework (OTG-INFO-008)"

From OWASP
Jump to: navigation, search
(Alignment and pictures will be added shortly)
 
Line 27: Line 27:
  
 
==== HTTP headers ====
 
==== HTTP headers ====
The most basic form of identifying a web framework is to look at the X-Powered-By field in the HTTP response header.
+
The most basic form of identifying a web framework is to look at the ''X-Powered-By'' field in the HTTP response header.
 
Many tools can be used to fingerprint a target. The simplest one is netcat utility.  
 
Many tools can be used to fingerprint a target. The simplest one is netcat utility.  
 
Consider the following HTTP Request-Response:  
 
Consider the following HTTP Request-Response:  
Line 45: Line 45:
 
From the ''X-Powered-By'' field, we understand that the web application framework is likely to be Mono.
 
From the ''X-Powered-By'' field, we understand that the web application framework is likely to be Mono.
  
However, although simplicity and quickness of such an approach, this methodology doesn't work in 100% of cases. It is possible to easily disable X-Powered-By header by a proper configuration. There are also several techniques that allow a web site to obfuscate HTTP headers (see an example in Remediation chapter)
+
However, although simplicity and quickness of such an approach, this methodology doesn't work in 100% of cases. It is possible to easily disable ''X-Powered-By'' header by a proper configuration. There are also several techniques that allow a web site to obfuscate HTTP headers (see an example in Remediation chapter)
So in the same example we could either miss the X-Powered-By header or obtain an answer like the following:
+
So in the same example we could either miss the ''X-Powered-By'' header or obtain an answer like the following:
 
<pre>
 
<pre>
 
HTTP/1.1 200 OK
 
HTTP/1.1 200 OK
Line 57: Line 57:
 
</pre>
 
</pre>
  
Sometimes there are more HTTP-headers which point at the certain web framework. In the following example according to the information from HTTP-request one can see that X-Powered-By header contains PHP version. However, ''X-Generator'' header points out the used framework is actually Swiftlet, which helps a penetration tester to expand his attack vectors. When performing fingerprinting, always carefully inspect every HTTP-header for such leaks.
+
Sometimes there are more HTTP-headers which point at the certain web framework. In the following example according to the information from HTTP-request one can see that ''X-Powered-By'' header contains PHP version. However, ''X-Generator'' header points out the used framework is actually Swiftlet, which helps a penetration tester to expand his attack vectors. When performing fingerprinting, always carefully inspect every HTTP-header for such leaks.
 
<pre>
 
<pre>
 
HTTP/1.1 200 OK
 
HTTP/1.1 200 OK
Line 75: Line 75:
 
Another similar and somehow more reliable way to determine the current web framework, are framework-specific cookies.
 
Another similar and somehow more reliable way to determine the current web framework, are framework-specific cookies.
 
Consider the following HTTP-request:
 
Consider the following HTTP-request:
[[Image:burp_cakephp_cookie.png]]
 
  
As we can see, cookie CAKEPHP has automatically been set, which gives us information about what framework is used. List of common cookies names is presented in chapter <a href="#Common Frameworks"> Limitations are the same - it is possible to change the name of the cookie. For example, for the selected CakePHP framework this could be done by the following configuration (excerpt from core.php):
+
[[Image:Cakephp_cookie.png]]
 +
 
 +
 
 +
As we can see, cookie ''CAKEPHP'' has automatically been set, which gives us information about what framework is used. List of common cookies names is presented in chapter [[#Cookies_2]]. Limitations are the same - it is possible to change the name of the cookie. For example, for the selected ''CakePHP'' framework this could be done by the following configuration (excerpt from core.php):
  
 
<pre>
 
<pre>
Line 91: Line 93:
 
</pre>
 
</pre>
  
However from the experience, these changes are less likely to be made than, for example, X-Powered-By header so this approach can be considered as more reliable one.
+
However from the experience, these changes are less likely to be made than, for example, ''X-Powered-By'' header so this approach can be considered as more reliable one.
  
 
==== HTML source code ====
 
==== HTML source code ====
Line 97: Line 99:
 
Ones of the common markers are HTML comments which directly lead to a framework disclosure. More often certain framework-specific paths can be found, i.e. links to framework-specific css and/or js folders. Finally, specific script variables might also point on a certain framework.
 
Ones of the common markers are HTML comments which directly lead to a framework disclosure. More often certain framework-specific paths can be found, i.e. links to framework-specific css and/or js folders. Finally, specific script variables might also point on a certain framework.
 
From the screenshot below one can easily learn the used framework and its version by the mentioned markers: comment, specific paths and script variables can all help an attacker to quickly determine an instance of ZK framework.
 
From the screenshot below one can easily learn the used framework and its version by the mentioned markers: comment, specific paths and script variables can all help an attacker to quickly determine an instance of ZK framework.
[[Image:zk_html_source.png]]
+
 
 +
[[Image:Zk_html_source.png]]
 +
 
  
 
The most frequently such information is placed either between <head></head> and in <meta> tags or in the end of the page. Nevertheless, it is recommended to check the whole document - it can be useful for other purposes (such as inspection of other useful comments and hidden fields)
 
The most frequently such information is placed either between <head></head> and in <meta> tags or in the end of the page. Nevertheless, it is recommended to check the whole document - it can be useful for other purposes (such as inspection of other useful comments and hidden fields)
 
Sometimes, however, web developers don't care much about hiding tracks of a framework. It's still possible to stumble upon something like that at the bottom of the page:
 
Sometimes, however, web developers don't care much about hiding tracks of a framework. It's still possible to stumble upon something like that at the bottom of the page:
 +
 
[[Image:banshee_bottom_page.png]]
 
[[Image:banshee_bottom_page.png]]
 +
  
 
==== Specific files and folders ====
 
==== Specific files and folders ====
Line 107: Line 113:
 
Every framework has its own specific file and folder structure on the server. We pointed out that one can see the specific path from the HTML page source but sometimes they are not explicitly presented there and still reside on the server. In order to uncover them such technique as dirbusting is used. Dirbusting essense is fuzzing target with predictable folder- and filenames and monitoring HTTP-responses thus enumerating server contents. This information can be used both for finding default files and attacking them in next stages and for fingerprinting the web framework.
 
Every framework has its own specific file and folder structure on the server. We pointed out that one can see the specific path from the HTML page source but sometimes they are not explicitly presented there and still reside on the server. In order to uncover them such technique as dirbusting is used. Dirbusting essense is fuzzing target with predictable folder- and filenames and monitoring HTTP-responses thus enumerating server contents. This information can be used both for finding default files and attacking them in next stages and for fingerprinting the web framework.
 
Dirbusting can be done in several ways, example below shows successful dirbusting attack against a WordPress-powered target with the help of defined list and Intruder functionality of Burp Suite.
 
Dirbusting can be done in several ways, example below shows successful dirbusting attack against a WordPress-powered target with the help of defined list and Intruder functionality of Burp Suite.
[[Image:wordpress_dirbusting.png]]
+
 
 +
[[Image:Wordpress_dirbusting.png]]
 +
 
  
 
We can see that for some WordPress-specific folders (i.e. /wp-admin, /wp-content and /wp-includes) HTTP-reponse is 403 (Forbidden), whereas for other predictable names it's 404. This is a good indicator that the target is WordPress-powered. The same way it is possible to dirbust different framework plugin folders and their versions. On a screenshot below one can see a typical CHANGELOG file of a Drupal plugin, which both points out on the used framework and discloses vulnerable plugin version.
 
We can see that for some WordPress-specific folders (i.e. /wp-admin, /wp-content and /wp-includes) HTTP-reponse is 403 (Forbidden), whereas for other predictable names it's 404. This is a good indicator that the target is WordPress-powered. The same way it is possible to dirbust different framework plugin folders and their versions. On a screenshot below one can see a typical CHANGELOG file of a Drupal plugin, which both points out on the used framework and discloses vulnerable plugin version.
[[Image:drupal_botcha_disclosure.png]]
+
 
 +
[[Image:Drupal_botcha_disclosure.png]]
 +
 
  
 
Tip: before starting dirbusting (which is a useful operation anyway), it is recommended to check robots.txt file first. Sometimes framework specific folders and other sensitive information can be found there as well! Example of such robots file is presented on a screenshot below.
 
Tip: before starting dirbusting (which is a useful operation anyway), it is recommended to check robots.txt file first. Sometimes framework specific folders and other sensitive information can be found there as well! Example of such robots file is presented on a screenshot below.
[[Image:robots-info-disclosure.png]]
+
 
 +
[[Image:Robots-info-disclosure.png]]
 +
 
  
 
=== Gray Box testing ===
 
=== Gray Box testing ===
Line 204: Line 216:
 
=== Specific files and folders ===
 
=== Specific files and folders ===
 
Different for each specific framework. It is recommended to install the corresponding framework during penetration tests in order to have better understanding of what infrastructure is presented and which files might be left on the server. However, several good pre-made lists already exist, one good example of them - RAFT Wordlists of predictable files/folders (http://code.google.com/p/raft/)
 
Different for each specific framework. It is recommended to install the corresponding framework during penetration tests in order to have better understanding of what infrastructure is presented and which files might be left on the server. However, several good pre-made lists already exist, one good example of them - RAFT Wordlists of predictable files/folders (http://code.google.com/p/raft/)
 +
  
 
== Tools ==
 
== Tools ==
* WhatWeb - http://www.morningstarsecurity.com/research/whatweb
+
A list of general and well-known tools is presented below. There are also a lot of other utilities, as well as framework-based fingerprinting tools.
 +
 +
=== WhatWeb ===
 +
Website:  http://www.morningstarsecurity.com/research/whatweb <br>
 
Currently one of the best fingerprinting tools on the market. Included in a default Linux Kali build.
 
Currently one of the best fingerprinting tools on the market. Included in a default Linux Kali build.
 
Language: Ruby
 
Language: Ruby
 
Matches for fingerprinting are made with:
 
Matches for fingerprinting are made with:
** Text strings (case sensitive)
+
* Text strings (case sensitive)
** Regular expressions
+
* Regular expressions
** Google Hack Database queries (limited set of keywords)
+
* Google Hack Database queries (limited set of keywords)
** MD5 hashes
+
* MD5 hashes
** URL recognition
+
* URL recognition
** HTML tag patterns
+
* HTML tag patterns
** Custom ruby code for passive and aggressive operations
+
* Custom ruby code for passive and aggressive operations
  
 
Sample output is presented on a screenshot below:
 
Sample output is presented on a screenshot below:
 +
 
[[Image:whatweb-sample.png]]
 
[[Image:whatweb-sample.png]]
  
  
* BlindElephant - https://community.qualys.com/community/blindelephant
+
 
 +
=== BlindElephant ===
 +
Website: https://community.qualys.com/community/blindelephant <br>
 
This great tool works on the principle of static file checksum based version difference thus providing a very high quality of fingerprinting.
 
This great tool works on the principle of static file checksum based version difference thus providing a very high quality of fingerprinting.
 
Language: Python
 
Language: Python
Line 256: Line 275:
 
</pre>
 
</pre>
  
* Framework-dependent scanners
 
  
 +
=== Wappalyzer ===
 +
Website: http://wappalyzer.com <br>
 +
Wapplyzer is a Firefox/Chrome plug-in. It works on only regular expression matching and doesn't need anything other than the page to be loaded on browser. It works completely at the browser level and give results in form of icons. Although sometimes it has false positives, this is very handy to have notion of what technologies were used to construct a target website immediately after browsing a page.
 +
Sample output of a plug-in is presented on a screenshot below.
  
=== Browser plug-in ===
+
[[Image:Owasp-wappalyzer.png]]
* Wappalyzer - http://wappalyzer.com/
 
Wapplyzer is a Firefox/Chrome plug-in. It works on only regular expression matching and doesn’t need anything other than the page to be loaded on browser. It works completely at the browser level and give results in form of icons. Although sometimes it has false positives, this is very handy to have notion of what technologies were used to construct a target website immediately after browsing a page.
 
Sample output of a plug-in is presented on a screenshot below.
 
  
[[Image:whatweb-sample.png]]
 
  
  
Line 277: Line 295:
 
Below you may find specific recommendations by framework marker location and some additional interesting approaches.
 
Below you may find specific recommendations by framework marker location and some additional interesting approaches.
  
*HTTP headers
+
==== HTTP headers ====
 
Check your configuration and disable/obfuscate all HTTP-headers which disclose information about used technologies.
 
Check your configuration and disable/obfuscate all HTTP-headers which disclose information about used technologies.
 
An interesting article about HTTP-headers obfuscation using Netscaler:
 
An interesting article about HTTP-headers obfuscation using Netscaler:
 
http://grahamhosking.blogspot.ru/2013/07/obfuscating-http-header-using-netscaler.html
 
http://grahamhosking.blogspot.ru/2013/07/obfuscating-http-header-using-netscaler.html
  
*Cookies
+
==== Cookies ====
 
It is recommended to change cookie names by making proper changes in corresponding config files.
 
It is recommended to change cookie names by making proper changes in corresponding config files.
  
*HTML source code
+
==== HTML source code ====
 
Check manually the contents of your HTML code and remove everything what explicitly points to the framework.
 
Check manually the contents of your HTML code and remove everything what explicitly points to the framework.
 
General guidelines:
 
General guidelines:
**Make sure you didn't leave any visual markers disclosing used framework
+
*Make sure you didn't leave any visual markers disclosing used framework
**Remove any unnecessary comments (copyrights, bug information, specific framework comments)
+
*Remove any unnecessary comments (copyrights, bug information, specific framework comments)
**Remove META and generator tags
+
*Remove META and generator tags
**Use your own css/js and do not store those in a framework-specific folders
+
*Use your own css/js and do not store those in a framework-specific folders
**Make sure you're not using default scripts on the page; if using them is needed, obfuscate them.
+
*Make sure you're not using default scripts on the page; if using them is needed, obfuscate them.
  
*Specific files and folders
+
==== Specific files and folders ====
**Remove any unnecessary/unused files on the server. This implies text files disclosing information about versions and installation too.
+
*Remove any unnecessary/unused files on the server. This implies text files disclosing information about versions and installation too.
**Restrict access to other files in order to achieve 404-response when accessing them from outside. This can be done, for example, by modifying htaccess file and adding RewriteCond / RewriteRule there. Example of such restriction for two common WordPress folders is presented below.
+
*Restrict access to other files in order to achieve 404-response when accessing them from outside. This can be done, for example, by modifying htaccess file and adding RewriteCond / RewriteRule there. Example of such restriction for two common WordPress folders is presented below.
 
<pre>
 
<pre>
 
RewriteCond %{REQUEST_URI} /wp-login\.php$ [OR]
 
RewriteCond %{REQUEST_URI} /wp-login\.php$ [OR]
Line 302: Line 320:
 
RewriteRule $ /http://your_website [R=404,L]
 
RewriteRule $ /http://your_website [R=404,L]
 
</pre>
 
</pre>
However, this is not the only way to restrict access. In order to automate this process, certain framework-specific plugins exist. One example for WordPress is StealthLogin (http://wordpress.org/plugins/stealth-login-page)
+
However, these are not the only ways to restrict access. In order to automate this process, certain framework-specific plugins exist. One example for WordPress is StealthLogin (http://wordpress.org/plugins/stealth-login-page)
  
*Additional approaches
+
==== Additional approaches ====
**Checksum management -
+
*Checksum management  
Purpose of this approach is to beat checksum-based scanners and don't let them to disclose files by their hashes. Generally, there are two approaches in checksum management:
+
*:Purpose of this approach is to beat checksum-based scanners and don't let them to disclose files by their hashes. Generally, there are two approaches in checksum management:
***Change the location of where those files are placed (i.e. move them to another folder, or rename existing)
+
*:*Change the location of where those files are placed (i.e. move them to another folder, or rename existing)
***Modify their contents - even slight modification results in a completely different hash sum, so adding a single byte in the end of the file should not be a big problem.
+
*:*Modify their contents - even slight modification results in a completely different hash sum, so adding a single byte in the end of the file should not be a big problem.
***Controlled chaos
+
*Controlled chaos
A funny and effective method which essense is adding bogus files and folders from other frameworks in order to fool scanners and confuse an attacker. But be careful not to overwrite exisiting files and folders and to break the current framework!
+
*:A funny and effective method which essense is adding bogus files and folders from other frameworks in order to fool scanners and confuse an attacker. But be careful not to overwrite exisiting files and folders and to break the current framework!

Revision as of 20:32, 10 September 2013

This article is part of the new OWASP Testing Guide v4.
Back to the OWASP Testing Guide v4 ToC: https://www.owasp.org/index.php/OWASP_Testing_Guide_v4_Table_of_Contents Back to the OWASP Testing Guide Project: https://www.owasp.org/index.php/OWASP_Testing_Project

Summary

Web framework[*] fingerprinting is an important subtask of information gathering. Knowing type of framework can automatically give such a great advantage if such a framework has already been met by a penetration tester. It is not only known vulnerabilities in unpatched versions but specific misconfigurations and known file structure which makes it so important.

Several different vendors and versions of web frameworks are widely used. Information about it significantly helps in the testing process, and will also change the course of the test. Such information can be derived by careful analysis of certain common locations. Most of web frameworks have several markers in those locations, which help an attacker to spot them. This is basically what all automatic tools do - looking for a marker from a predefined location and then comparing it to the database of known signatures. For better accuracy several markers are usually used.

[*] Please note that in this article we make no difference between Web Application Frameworks (WAF) and Content Management Systems (CMS). This implying is made intentionally due to convenience from the point of fingerprinting of describing both of them in one chapter. Also, borders between WAFs and CMSes sometimes can be quite fuzzy (e.g. for Drupal, Joomla, SilverStripe and others) Further we reference both of the categories as web frameworks.

Test Objectives

To define type of used web framework so to have a better understanding of how to plan future attack.

How to Test

Black Box testing

There are several most common locations to look in in order to define the current framework:

  • HTTP headers
  • Cookies
  • HTML source code
  • Specific files and folders

Let's look closer at those approaches.

HTTP headers

The most basic form of identifying a web framework is to look at the X-Powered-By field in the HTTP response header. Many tools can be used to fingerprint a target. The simplest one is netcat utility. Consider the following HTTP Request-Response:

$ nc 127.0.0.1 80
HEAD / HTTP/1.0

HTTP/1.1 200 OK
Server: nginx/1.0.14
Date: Sat, 07 Sep 2013 08:19:15 GMT
Content-Type: text/html;charset=ISO-8859-1
Connection: close
Vary: Accept-Encoding
X-Powered-By: Mono

From the X-Powered-By field, we understand that the web application framework is likely to be Mono.

However, although simplicity and quickness of such an approach, this methodology doesn't work in 100% of cases. It is possible to easily disable X-Powered-By header by a proper configuration. There are also several techniques that allow a web site to obfuscate HTTP headers (see an example in Remediation chapter) So in the same example we could either miss the X-Powered-By header or obtain an answer like the following:

HTTP/1.1 200 OK
Server: nginx/1.0.14
Date: Sat, 07 Sep 2013 08:19:15 GMT
Content-Type: text/html;charset=ISO-8859-1
Connection: close
Vary: Accept-Encoding
X-Powered-By: Blood, sweat and tears

Sometimes there are more HTTP-headers which point at the certain web framework. In the following example according to the information from HTTP-request one can see that X-Powered-By header contains PHP version. However, X-Generator header points out the used framework is actually Swiftlet, which helps a penetration tester to expand his attack vectors. When performing fingerprinting, always carefully inspect every HTTP-header for such leaks.

HTTP/1.1 200 OK
Server: nginx/1.4.1
Date: Sat, 07 Sep 2013 09:22:52 GMT
Content-Type: text/html
Connection: keep-alive
Vary: Accept-Encoding
X-Powered-By: PHP/5.4.16-1~dotdeb.1
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
X-Generator: Swiftlet

Cookies

Another similar and somehow more reliable way to determine the current web framework, are framework-specific cookies. Consider the following HTTP-request:

Cakephp cookie.png


As we can see, cookie CAKEPHP has automatically been set, which gives us information about what framework is used. List of common cookies names is presented in chapter #Cookies_2. Limitations are the same - it is possible to change the name of the cookie. For example, for the selected CakePHP framework this could be done by the following configuration (excerpt from core.php):

/**
* The name of CakePHP's session cookie.
*
* Note the guidelines for Session names states: "The session name references
* the session id in cookies and URLs. It should contain only alphanumeric
* characters."
* @link http://php.net/session_name
*/
Configure::write('Session.cookie', 'CAKEPHP');

However from the experience, these changes are less likely to be made than, for example, X-Powered-By header so this approach can be considered as more reliable one.

HTML source code

This technique is based on finding certain patterns in the HTML page source code. Often one can find much information which helps a tester to recognize specific web framework. Ones of the common markers are HTML comments which directly lead to a framework disclosure. More often certain framework-specific paths can be found, i.e. links to framework-specific css and/or js folders. Finally, specific script variables might also point on a certain framework. From the screenshot below one can easily learn the used framework and its version by the mentioned markers: comment, specific paths and script variables can all help an attacker to quickly determine an instance of ZK framework.

Zk html source.png


The most frequently such information is placed either between <head></head> and in <meta> tags or in the end of the page. Nevertheless, it is recommended to check the whole document - it can be useful for other purposes (such as inspection of other useful comments and hidden fields) Sometimes, however, web developers don't care much about hiding tracks of a framework. It's still possible to stumble upon something like that at the bottom of the page:

Banshee bottom page.png


Specific files and folders

Apart from information, gathered from HTML sources, there is another approach which greatly helps an attacker to determine the framework with high accuracy. Every framework has its own specific file and folder structure on the server. We pointed out that one can see the specific path from the HTML page source but sometimes they are not explicitly presented there and still reside on the server. In order to uncover them such technique as dirbusting is used. Dirbusting essense is fuzzing target with predictable folder- and filenames and monitoring HTTP-responses thus enumerating server contents. This information can be used both for finding default files and attacking them in next stages and for fingerprinting the web framework. Dirbusting can be done in several ways, example below shows successful dirbusting attack against a WordPress-powered target with the help of defined list and Intruder functionality of Burp Suite.

Wordpress dirbusting.png


We can see that for some WordPress-specific folders (i.e. /wp-admin, /wp-content and /wp-includes) HTTP-reponse is 403 (Forbidden), whereas for other predictable names it's 404. This is a good indicator that the target is WordPress-powered. The same way it is possible to dirbust different framework plugin folders and their versions. On a screenshot below one can see a typical CHANGELOG file of a Drupal plugin, which both points out on the used framework and discloses vulnerable plugin version.

Drupal botcha disclosure.png


Tip: before starting dirbusting (which is a useful operation anyway), it is recommended to check robots.txt file first. Sometimes framework specific folders and other sensitive information can be found there as well! Example of such robots file is presented on a screenshot below.

Robots-info-disclosure.png


Gray Box testing

Please address yourself to watching Monty Python's Flying Circus, I'm sure you'll like it!


Common frameworks

Cookies

Framework Cookie name
Zope zope3
CakePHP cakephp
Kohana kohanasession
Laravel laravel_session
1C-Bitrix BITRIX_
AMPcms AMP
Django CMS django
DotNetNuke DotNetNukeAnonymous
e107 e107_tz
EPiServer EPiTrace, EPiServer
Graffiti CMS graffitibot
Hotaru CMS hotaru_mobile
ImpressCMS ICMSession
Indico MAKACSESSION
InstantCMS InstantCMS[logdate]
Kentico CMS CMSPreferredCulture
MODx SN4[12symb]
TYPO3 fe_typo_user
Dynamicweb Dynamicweb
LEPTON lep[some_numeric_value]+sessionid
Wix Domain=.wix.com
VIVVO VivvoSessionId


HTML source code

General markers:

 %framework_name%
powered by
built upon
running

Specific markers:

Framework Keyword
Adobe ColdFusion <!-- START headerTags.cfm
Microsoft ASP.NET __VIEWSTATE
ZK <!-- ZK
Business Catalyst <!-- BC_OBNW -->
Indexhibit ndxz-studio

Specific files and folders

Different for each specific framework. It is recommended to install the corresponding framework during penetration tests in order to have better understanding of what infrastructure is presented and which files might be left on the server. However, several good pre-made lists already exist, one good example of them - RAFT Wordlists of predictable files/folders (http://code.google.com/p/raft/)


Tools

A list of general and well-known tools is presented below. There are also a lot of other utilities, as well as framework-based fingerprinting tools.

WhatWeb

Website: http://www.morningstarsecurity.com/research/whatweb
Currently one of the best fingerprinting tools on the market. Included in a default Linux Kali build. Language: Ruby Matches for fingerprinting are made with:

  • Text strings (case sensitive)
  • Regular expressions
  • Google Hack Database queries (limited set of keywords)
  • MD5 hashes
  • URL recognition
  • HTML tag patterns
  • Custom ruby code for passive and aggressive operations

Sample output is presented on a screenshot below:

Whatweb-sample.png


BlindElephant

Website: https://community.qualys.com/community/blindelephant
This great tool works on the principle of static file checksum based version difference thus providing a very high quality of fingerprinting. Language: Python

Sample output of a successful fingerprint:

pentester$ python BlindElephant.py http://my_target drupal
Loaded /Library/Python/2.7/site-packages/blindelephant/dbs/drupal.pkl with 145 versions, 478 differentiating paths, and 434 version groups.
Starting BlindElephant fingerprint for version of drupal at http://my_target 

Hit http://my_target/CHANGELOG.txt
File produced no match. Error: Retrieved file doesn't match known fingerprint. 527b085a3717bd691d47713dff74acf4 

Hit http://my_target/INSTALL.txt
File produced no match. Error: Retrieved file doesn't match known fingerprint. 14dfc133e4101be6f0ef5c64566da4a4 

Hit http://my_target/misc/drupal.js
Possible versions based on result: 7.12, 7.13, 7.14

Hit http://my_target/MAINTAINERS.txt
File produced no match. Error: Retrieved file doesn't match known fingerprint. 36b740941a19912f3fdbfcca7caa08ca 

Hit http://my_target/themes/garland/style.css
Possible versions based on result: 7.2, 7.3, 7.4, 7.5, 7.6, 7.7, 7.8, 7.9, 7.10, 7.11, 7.12, 7.13, 7.14

...

Fingerprinting resulted in:
7.14


Best Guess: 7.14


Wappalyzer

Website: http://wappalyzer.com
Wapplyzer is a Firefox/Chrome plug-in. It works on only regular expression matching and doesn't need anything other than the page to be loaded on browser. It works completely at the browser level and give results in form of icons. Although sometimes it has false positives, this is very handy to have notion of what technologies were used to construct a target website immediately after browsing a page. Sample output of a plug-in is presented on a screenshot below.

Owasp-wappalyzer.png


Vulnerability References

Whitepapers


Remediation

General advice: use several tools described above and check scan logs in order to better understand what exactly helps an attacker to disclose your web framework. By performing multiple scans after changes you've done to hide framework tracks, it's possible to achieve better security level and to make sure of undetectability by automatic scans. Below you may find specific recommendations by framework marker location and some additional interesting approaches.

HTTP headers

Check your configuration and disable/obfuscate all HTTP-headers which disclose information about used technologies. An interesting article about HTTP-headers obfuscation using Netscaler: http://grahamhosking.blogspot.ru/2013/07/obfuscating-http-header-using-netscaler.html

Cookies

It is recommended to change cookie names by making proper changes in corresponding config files.

HTML source code

Check manually the contents of your HTML code and remove everything what explicitly points to the framework. General guidelines:

  • Make sure you didn't leave any visual markers disclosing used framework
  • Remove any unnecessary comments (copyrights, bug information, specific framework comments)
  • Remove META and generator tags
  • Use your own css/js and do not store those in a framework-specific folders
  • Make sure you're not using default scripts on the page; if using them is needed, obfuscate them.

Specific files and folders

  • Remove any unnecessary/unused files on the server. This implies text files disclosing information about versions and installation too.
  • Restrict access to other files in order to achieve 404-response when accessing them from outside. This can be done, for example, by modifying htaccess file and adding RewriteCond / RewriteRule there. Example of such restriction for two common WordPress folders is presented below.
RewriteCond %{REQUEST_URI} /wp-login\.php$ [OR]
RewriteCond %{REQUEST_URI} /wp-admin/$
RewriteRule $ /http://your_website [R=404,L]

However, these are not the only ways to restrict access. In order to automate this process, certain framework-specific plugins exist. One example for WordPress is StealthLogin (http://wordpress.org/plugins/stealth-login-page)

Additional approaches

  • Checksum management
    Purpose of this approach is to beat checksum-based scanners and don't let them to disclose files by their hashes. Generally, there are two approaches in checksum management:
    • Change the location of where those files are placed (i.e. move them to another folder, or rename existing)
    • Modify their contents - even slight modification results in a completely different hash sum, so adding a single byte in the end of the file should not be a big problem.
  • Controlled chaos
    A funny and effective method which essense is adding bogus files and folders from other frameworks in order to fool scanners and confuse an attacker. But be careful not to overwrite exisiting files and folders and to break the current framework!