Skip to content

Writing WhatWeb Plugins

yehgdotnet edited this page Oct 15, 2010 · 23 revisions

Note to New Contributors

Please read this before writing a plugin.

  1. Check your desired plugins in ./plugins/
  2. Check them on the Plugin-ToDo Page http://github.com/urbanadventurer/WhatWeb/wiki/Plugins-%5BTO-DO%5D and and pending page.
  3. If you don't find them, write them down on that page so that others can see what you'll be doing
  4. Start writing new plugins
  5. Update that page accordingly by removing what you've written
  6. Test your plugins well against a wide range of targets as many as possible
  7. Submit your new plugins via email or forking the project or via the Issues page.

Getting Started

To get started modify plugin-template.rb.txt in the my-plugins folder. Rename it to your desired one like my-first-plugin.rb which will be run by WhatWeb without your needing to put it into ./plugins/ folder.

Also read the tutorial on writing WhatWeb plugins at How to develop WhatWeb plugins.

Typical Plugin (Example)

A typical plugin looks like this:

	Plugin.define "Plone" do
	author "Andrew Horton"
	version "0.2"
	description "CMS http://plone.org"
	examples %w| www.norden.org www.trolltech.com www.plone.net www.smeal.psu.edu|

	matches [
	{:name=>"meta generator tag",
	:regexp=>/<meta name="generator" content="[^>]*http:\/\/plone.org" \/>/},

	{:name=>"plone css",
	:regexp=>/(@import url|text\/css)[^>]*portal_css\/.*plone.*css(\)|")/}, #"

	{:name=>"plone javascript",
	:regexp=>/src="[^"]*ploneScripts[0-9]+.js"/}, #"

	{:text=>'<div class="visualIcon contenttype-plone-site">'},

	{:name=>"div tag, visual-portal-wrapper",
	:certainty=>75,
	:text=>'<div id="visual-portal-wrapper">'},
	]

	def passive
		m=[]
		#X-Caching-Rule-Id: plone-content-types
		#X-Cache-Rule: plone-content-types
		m << {:name=>"X-Caching-Rule-Id: plone-content-types" } if @meta["x-caching-rule-id"] =~ /plone-content-types/i
		m << {:name=>"X-Cache-Rule: plone-content-types" } if @meta["x-cache-rule"] =~ /plone-content-types/i
		m
	end


	end

Matches

There are 3 levels to a plugin. Simple matches, passive and aggressive tests. You don’t need to know ruby to write plugins with simple matches. Passive and aggressive tests are written in ruby.

The matches [] array contains a set of ways to match a website to a system.

The methods are:

* :text			Matches text within the webpage
* :regexp		A regular expression. Append /i for case insensitive matches
* :ghdb			Like a google query
* :md5			MD5 hash of the HTML page
* :tagpattern		Pattern of HTML tags
* :name			This is the name of the match, and is optional.
* :url			The URL has to match this. Used for passive and agressive testing
* :certainty		Optional, defaults to 100. Values are maybe (25), probably (75) and certain (100).
* :version		As a string or number this is a version returned when other methods match
* :version		As a regular expression, this extracts the version information from the HTML. Also requires :version_regexp_offset=>1

If you port a GHDB match, use :ghdb. I usually rewrite the GHDB matches with regular expressions, especially if they require inurl:

Example:

# http://johnny.ihackstuff.com/ghdb?function=detail&id=1840

{ :ghdb=>'"Powered by Vsns Lemon" intitle:"Vsns Lemon"' }

Note the GHDB queries are case insensitive, as a Google query is.

Supported GHDB codes are:

* intitle:
* inurl:
* filetype:

Each plugin can access @body, @meta, @status, @base_uri, @md5, @ip and @tagpattern variables.

Passive tests add matches to the m array, each match is a hash containing the name of the match, probability and more. The entire hash is returned with Full output, Brief output returns just the match, :version and :string

To discover the regular expressions to match against, wget about 20-30 examples into the tests/ folder. Be aware that some software can have dramatic variations between versions.

Generating a signature with ease

//TODO

Clone this wiki locally