Hack: Bad Behavior for WackoWiki

bugs: implemented as extension
Compatible with: R6.0
Current version: 0.7
Credits: Sergey Martynoff, WikiAdmin, RideSnowNow

It is not in Bad Behavior release yet, so you can download it here:

1. About

Bad Behavior is a spam protection system that detects and blocks unwanted Web accesses.

2. Download

1. Bad Behavior:

2. Bad-Behavior plugin for WackoWiki:

Put the files in the following folders:

file folder notes
1. Bad-Behavior
bad-behavior/ lib/bad_behavior/ move the entire bad-behavior/ folder here
bb_whitelist.conf config/ you must create this file, see bb_whitelist-sample.conf
2. Bad-Behavior plugin for WackoWiki
tool_badbehavior.php admin/module/ optional, allows you to check the logs, access via admin panel
bad-behavior-wackowiki.php lib/bad_behavior/ plugin for WackoWiki
bb_settings.conf config/ see Configuration

3. Installation

To activate the extension you have to set ext_bad_behavior to 1 in the the Secondary Config, you can do this via the Admin panel.

Admin panel: Extensions -> Bad Behavior -> Settings

That's all – now go to your site and check if it is still working.

3.1. Configuration

still uses the bb_settings.conf

; settings.ini

display_stats = true
strict = false
verbose = false
logging = true
httpbl_key = ""
httpbl_threat = 25
httpbl_maxage = 30
offsite_forms = false
reverse_proxy = false
reverse_proxy_header = "X-Forwarded-For"
;reverse_proxy_addresses[] = 
;reverse_proxy_addresses[] =

Just as a reminder, if you use CloudFlare, Incapsula, Amazon Elastic Load Balancer, Azure Load Balancer, Google Cloud Load Balancing, or similar services on your site, you may need to enable the Reverse Proxy option in Bad Behavior’s settings, or many of your visitors and search engines will be blocked.

3.2. Whitelist

still uses the bb_whitelist.conf

; whitelist.conf
; Inappropriate whitelisting WILL expose you to spam, or cause Bad Behavior
; to stop functioning entirely! DO NOT WHITELIST unless you are 100% CERTAIN
; that you should.

; IP address ranges use the CIDR format.

; Digg whitelisted as of 2.0.12
ip[] = ""
ip[] = ""
; RFC 1918 addresses
ip[] = ""
ip[] = ""
ip[] = ""

; User agents are matched by exact match only.

useragent[] = "Mozilla/4.0 (It's me, let me in)"

; URLs are matched from the first / after the server name up to, but not
; including, the ? (if any). The URL to be whitelisted is a URL on YOUR site.
; A partial URL match is permitted, so URL whitelist entries should be as
; specific as possible, but no more specific than necessary. For instance,
; "/example" would match "/example.php" and "/example/address".

url[] = "/example.php"
url[] = "/openid/server"

4. AdminPanel Module

5. Changelog

0.1 Intitial version
0.2 Ported to WackoWiki 5.1.0
0.3 Added module for Admin panel
0.4 Integrated in distribution as extension
0.5 Adapted for WackoWiki's new init system
0.6 Removed obsolete cookie related code
0.7 Localized all message sets

6. To Do

  • make use of secondary config
  • add notes for ideas, improvements


  1. optimize log_table for bad_behavior

    "CREATE TABLE IF NOT EXISTS `$name_escaped` (
    		`log_id` INT(11) NOT NULL auto_increment,
    		`ip` VARCHAR(45) NOT NULL,
    		`host` VARCHAR(255) NOT NULL,
    		`date` DATETIME NOT NULL default '0000-00-00 00:00:00',
    		`request_method` VARCHAR(8) NOT NULL,
    		`request_uri` VARCHAR(2083) NOT NULL,
    		`server_protocol` VARCHAR(12) NOT NULL,
    		`http_headers` TEXT NOT NULL,
    		`user_agent` TEXT NOT NULL,
    		`user_agent_hash` CHAR(40) NOT NULL,
    		`request_entity` TEXT NOT NULL,
    		`status_key` VARCHAR(10) NOT NULL,
    		PRIMARY KEY (`log_id`),
    		KEY `idx_staus_key` (`status_key`),
    		KEY `idx_user_agent_hash` (`user_agent_hash`),
    		KEY `idx_ip` (`ip`),
    		KEY `idx_request_method` (`request_method`)
    		);";	// TODO: INDEX might need tuning


    1. ip TEXT ->
      1. VARCHAR(45)
      2. http://stackoverflow.com/quest[...]n-of-an-ipv6-address
      3. add field host to avoid random lookups over and over again -> VARCHAR(255)
        1. http://stackoverflow.com/quest[...]onverted-domain-name
    2. request_method TEXT ->
      1. VARCHAR (8)
      2. 'GET', 'HEAD', 'POST', 'PUT'
    3. request_uri TEXT ->
      1. VARCHAR(2083)
      2. http://stackoverflow.com/quest[...]n-different-browsers -> de facto limit of 2000 characters
      3. http://stackoverflow.com/quest[...]field-type-for-a-url#
    4. server_protocol TEXT ->
      1. VARCHAR (10)
      2. 'HTTP/1.0', 'HTTP/1.1'
    5. http_headers TEXT ->
    6. user_agent TEXT ->
      1. http://stackoverflow.com/quest[...]ser-agent-string-get
      2. Have another UNIQUE BINARY(32) (or 64, or 128 depending on your hash length) and hash the UserAgent
      3. user_agent_hash -> CHAR(40)
    7. request_entity TEXT ->
    8. key TEXT ->
      1. VARCHAR (8)
      2. 'key' is reserved word -> rename to 'status_key'
    • WikiAdmin
    • 22.04.2015 10:16 edited
  2. HTTP request

    $request = '';
    $request .= "{$_SERVER['REQUEST_METHOD']} ";
    $request .= "{$_SERVER['REQUEST_URI']} ";
    $request .= "{$_SERVER['SERVER_PROTOCOL']}\r\n";
    $request .= "Host: {$_SERVER['HTTP_HOST']}\r\n";
    $request .= "User-Agent: {$_SERVER['HTTP_USER_AGENT']}\r\n";
    $request .= "Accept: {$_SERVER['HTTP_ACCEPT']}\r\n\r\n";