[Xfce4-commits] [www/forum.xfce.org] 04/79: Add bad behaviour mod version 1.1.1.
noreply at xfce.org
noreply at xfce.org
Tue May 21 14:47:59 CEST 2019
This is an automated email from the git hooks/post-receive script.
s k u n n y k p u s h e d a c o m m i t t o b r a n c h o l d f o r u m
in repository www/forum.xfce.org.
commit 7b6e16e8b2b0bf2f5be52e0053c71a222484e499
Author: Nick Schermer <nick at xfce.org>
Date: Fri Nov 12 17:13:33 2010 +0100
Add bad behaviour mod version 1.1.1.
http://fluxbb.org/resources/mods/bad-behavior-integration-for-fluxbb/
---
include/bad-behavior-fluxbb.php | 173 ++++++++++++++++++++++++++++++
include/bad-behavior-mysql.php | 46 ++++++++
include/bad-behavior/banned.inc.php | 50 +++++++++
include/bad-behavior/blackhole.inc.php | 69 ++++++++++++
include/bad-behavior/blacklist.inc.php | 127 ++++++++++++++++++++++
include/bad-behavior/common_tests.inc.php | 143 ++++++++++++++++++++++++
include/bad-behavior/core.inc.php | 154 ++++++++++++++++++++++++++
include/bad-behavior/functions.inc.php | 70 ++++++++++++
include/bad-behavior/google.inc.php | 13 +++
include/bad-behavior/housekeeping.inc.php | 16 +++
include/bad-behavior/index.html | 1 +
include/bad-behavior/konqueror.inc.php | 17 +++
include/bad-behavior/lynx.inc.php | 13 +++
include/bad-behavior/movabletype.inc.php | 14 +++
include/bad-behavior/mozilla.inc.php | 19 ++++
include/bad-behavior/msie.inc.php | 26 +++++
include/bad-behavior/msnbot.inc.php | 13 +++
include/bad-behavior/opera.inc.php | 13 +++
include/bad-behavior/post.inc.php | 80 ++++++++++++++
include/bad-behavior/responses.inc.php | 49 +++++++++
include/bad-behavior/safari.inc.php | 13 +++
include/bad-behavior/screener.inc.php | 63 +++++++++++
include/bad-behavior/trackback.inc.php | 28 +++++
include/bad-behavior/version.inc.php | 3 +
include/bad-behavior/whitelist.inc.php | 30 ++++++
include/common.php | 3 +
plugins/AP_Bad_Behavior.php | 110 +++++++++++++++++++
27 files changed, 1356 insertions(+)
diff --git a/include/bad-behavior-fluxbb.php b/include/bad-behavior-fluxbb.php
new file mode 100644
index 0000000..5eb5dbf
--- /dev/null
+++ b/include/bad-behavior-fluxbb.php
@@ -0,0 +1,173 @@
+<?php
+/*
+http://www.bad-behavior.ioerror.us/
+
+Bad Behavior - detects and blocks unwanted Web accesses
+Copyright (C) 2005 Michael Hampton
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+// This file is the entry point for Bad Behavior.
+
+if (!defined('PUN_ROOT')) exit;
+
+define('BB2_CWD', dirname(__FILE__));
+
+// Settings you can adjust for Bad Behavior.
+// Most of these are unused in non-database mode.
+$bb2_settings_defaults = array(
+ 'log_table' => $db->prefix.'bad_behavior',
+ 'display_stats' => true,
+ 'strict' => false,
+ 'verbose' => false,
+ 'logging' => true,
+ 'httpbl_key' => '',
+ 'httpbl_threat' => '25',
+ 'httpbl_maxage' => '30',
+ 'offsite_forms' => false,
+);
+
+// Bad Behavior callback functions.
+require_once(BB2_CWD . "/bad-behavior-mysql.php");
+
+// Return current time in the format preferred by your database.
+function bb2_db_date() {
+ return gmdate('Y-m-d H:i:s'); // Example is MySQL format
+}
+
+// Return affected rows from most recent query.
+function bb2_db_affected_rows($result) {
+ global $db;
+ return $db->affected_rows();
+}
+
+// Escape a string for database usage
+function bb2_db_escape($string) {
+ global $db;
+ return $db->escape($string);
+}
+
+// Return the number of rows in a particular query.
+function bb2_db_num_rows($result) {
+ global $db;
+ return $db->num_rows($result);
+}
+
+// Run a query and return the results, if any.
+// Should return FALSE if an error occurred.
+// Bad Behavior will use the return value here in other callbacks.
+function bb2_db_query($query) {
+ global $db;
+ return $db->query($query);
+}
+
+// Return all rows in a particular query.
+// Should contain an array of all rows generated by calling mysql_fetch_assoc()
+// or equivalent and appending the result of each call to an array.
+function bb2_db_rows($result) {
+ global $db;
+ $return = array();
+ while ($data = $db->fetch_assoc($result))
+ $return[] = $data;
+
+ return $return;
+}
+
+// Return emergency contact email address.
+function bb2_email() {
+ global $pun_config;
+ return $pun_config['o_webmaster_email'];
+}
+
+// retrieve settings from database
+// Settings are hard-coded for non-database use
+function bb2_read_settings() {
+ global $bb2_settings_defaults, $pun_config, $db;
+
+ // It's installed
+ if (isset($pun_config['o_badbehavior_display_stats']))
+ {
+ return array_merge($bb2_settings_defaults, array(
+ 'log_table' => $db->prefix.'bad_behavior',
+ 'display_stats' => (bool)$pun_config['o_badbehavior_display_stats'],
+ 'verbose' => (bool)$pun_config['o_badbehavior_verbose'],
+ 'strict' => (bool)$pun_config['o_badbehavior_strict'],
+ 'is_installed' => true,
+ ));
+ }
+ else
+ return $bb2_settings_defaults;
+}
+
+// write settings to database
+function bb2_write_settings($settings, $install = false) {
+ global $db;
+
+ while (list($key, $input) = @each($settings))
+ {
+ if ($key == 'log_table')
+ continue;
+
+ $input = intval($input);
+
+ if ($install)
+ $db->query('INSERT INTO '.$db->prefix.'config (conf_name, conf_value) VALUES (\'o_badbehavior_'.$db->escape($key).'\', '.$input.')') or error('Unable to update board config', __FILE__, __LINE__, $db->error());
+ else
+ $db->query('UPDATE '.$db->prefix.'config SET conf_value='.$input.' WHERE conf_name=\'o_badbehavior_'.$db->escape($key).'\'') or error('Unable to update board config', __FILE__, __LINE__, $db->error());
+ }
+
+ // Regenerate the config cache
+ require_once PUN_ROOT.'include/cache.php';
+ generate_config_cache();
+}
+
+// installation
+function bb2_install() {
+ $settings = bb2_read_settings();
+ if (!isset($settings['is_installed']))
+ {
+ bb2_db_query(bb2_table_structure($settings['log_table']));
+ bb2_write_settings($settings, true);
+ }
+}
+
+// Display stats?
+function bb2_insert_stats($force = false) {
+ global $bb2_stats;
+
+ $settings = bb2_read_settings();
+
+ if ($force || $settings['display_stats']) {
+ $blocked = bb2_db_rows(bb2_db_query("SELECT COUNT(*) FROM " . $settings['log_table'] . " WHERE `key` NOT LIKE '00000000'"));
+ if ($blocked !== FALSE) {
+ echo sprintf('<p><a href="http://www.bad-behavior.ioerror.us/">%1$s</a> %2$s <strong>%3$s</strong> %4$s</p>', 'Bad Behavior', 'has blocked', $blocked[0]["COUNT(*)"], 'access attempt(s) in the last 7 days.');
+ }
+ }
+}
+
+// Return the top-level relative path of wherever we are (for cookies)
+// You should provide in $url the top-level URL for your site.
+function bb2_relative_path() {
+ global $cookie_path;
+ return $cookie_path;
+}
+
+// Calls inward to Bad Behavor itself.
+require_once(BB2_CWD . "/bad-behavior/version.inc.php");
+require_once(BB2_CWD . "/bad-behavior/core.inc.php");
+bb2_install();
+
+bb2_start(bb2_read_settings());
diff --git a/include/bad-behavior-mysql.php b/include/bad-behavior-mysql.php
new file mode 100644
index 0000000..936ecf5
--- /dev/null
+++ b/include/bad-behavior-mysql.php
@@ -0,0 +1,46 @@
+<?php
+
+// Our log table structure
+function bb2_table_structure($name)
+{
+ // It's not paranoia if they really are out to get you.
+ $name_escaped = bb2_db_escape($name);
+ return "CREATE TABLE IF NOT EXISTS `$name_escaped` (
+ `id` INT(11) NOT NULL auto_increment,
+ `ip` TEXT NOT NULL,
+ `date` DATETIME NOT NULL default '0000-00-00 00:00:00',
+ `request_method` TEXT NOT NULL,
+ `request_uri` TEXT NOT NULL,
+ `server_protocol` TEXT NOT NULL,
+ `http_headers` TEXT NOT NULL,
+ `user_agent` TEXT NOT NULL,
+ `request_entity` TEXT NOT NULL,
+ `key` TEXT NOT NULL,
+ INDEX (`ip`(15)),
+ INDEX (`user_agent`(10)),
+ PRIMARY KEY (`id`) );"; // TODO: INDEX might need tuning
+}
+
+// Insert a new record
+function bb2_insert($settings, $package, $key)
+{
+ $ip = bb2_db_escape($package['ip']);
+ $date = bb2_db_date();
+ $request_method = bb2_db_escape($package['request_method']);
+ $request_uri = bb2_db_escape($package['request_uri']);
+ $server_protocol = bb2_db_escape($package['server_protocol']);
+ $user_agent = bb2_db_escape($package['user_agent']);
+ $headers = "$request_method $request_uri $server_protocol\n";
+ foreach ($package['headers'] as $h => $v) {
+ $headers .= bb2_db_escape("$h: $v\n");
+ }
+ $request_entity = "";
+ if (!strcasecmp($request_method, "POST")) {
+ foreach ($package['request_entity'] as $h => $v) {
+ $request_entity .= bb2_db_escape("$h: $v\n");
+ }
+ }
+ return "INSERT INTO `" . bb2_db_escape($settings['log_table']) . "`
+ (`ip`, `date`, `request_method`, `request_uri`, `server_protocol`, `http_headers`, `user_agent`, `request_entity`, `key`) VALUES
+ ('$ip', '$date', '$request_method', '$request_uri', '$server_protocol', '$headers', '$user_agent', '$request_entity', '$key')";
+}
diff --git a/include/bad-behavior/banned.inc.php b/include/bad-behavior/banned.inc.php
new file mode 100644
index 0000000..85a58f2
--- /dev/null
+++ b/include/bad-behavior/banned.inc.php
@@ -0,0 +1,50 @@
+<?php if (!defined('BB2_CORE')) die('I said no cheating!');
+
+// Functions called when a request has been denied
+// This part can be gawd-awful slow, doesn't matter :)
+
+require_once(BB2_CORE . "/responses.inc.php");
+
+function bb2_display_denial($settings, $key, $previous_key = false)
+{
+ define('DONOTCACHEPAGE', true); // WP Super Cache
+ if (!$previous_key) $previous_key = $key;
+ if ($key == "e87553e1") {
+ // FIXME: lookup the real key
+ }
+ // Create support key
+ $ip = explode(".", $_SERVER['REMOTE_ADDR']);
+ $ip_hex = "";
+ foreach ($ip as $octet) {
+ $ip_hex .= str_pad(dechex($octet), 2, 0, STR_PAD_LEFT);
+ }
+ $support_key = implode("-", str_split("$ip_hex$key", 4));
+
+ // Get response data
+ $response = bb2_get_response($previous_key);
+ header("HTTP/1.1 " . $response['response'] . " Bad Behavior");
+ header("Status: " . $response['response'] . " Bad Behavior");
+?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<!--< html xmlns="http://www.w3.org/1999/xhtml">-->
+<head>
+<title>HTTP Error <?php echo $response['response']; ?></title>
+</head>
+<body>
+<h1>Error <?php echo $response['response']; ?></h1>
+<p>We're sorry, but we could not fulfill your request for
+<?php echo htmlspecialchars($_SERVER['REQUEST_URI']) ?> on this server.</p>
+<p><?php echo $response['explanation']; ?></p>
+<p>Your technical support key is: <strong><?php echo $support_key; ?></strong></p>
+<p>You can use this key to <a href="http://www.ioerror.us/bb2-support-key?key=<?php echo $support_key; ?>">fix this problem yourself</a>.</p>
+<p>If you are unable to fix the problem yourself, please contact <a href="mailto:<?php echo htmlspecialchars(str_replace("@", "+nospam at nospam.", bb2_email())); ?>"><?php echo htmlspecialchars(str_replace("@", " at ", bb2_email())); ?></a> and be sure to provide the technical support key shown above.</p>
+<?php
+}
+
+function bb2_log_denial($settings, $package, $key, $previous_key=false)
+{
+ if (!$settings['logging']) return;
+ bb2_db_query(bb2_insert($settings, $package, $key));
+}
+
+?>
diff --git a/include/bad-behavior/blackhole.inc.php b/include/bad-behavior/blackhole.inc.php
new file mode 100644
index 0000000..63829a6
--- /dev/null
+++ b/include/bad-behavior/blackhole.inc.php
@@ -0,0 +1,69 @@
+<?php if (!defined('BB2_CORE')) die('I said no cheating!');
+
+// Quick and dirty check for an IPv6 address
+function is_ipv6($address) {
+ return (strpos($address, ":")) ? TRUE : FALSE;
+}
+
+// Look up address on various blackhole lists.
+// These should not be used for GET requests under any circumstances!
+// FIXME: Note that this code is no longer in use
+function bb2_blackhole($package) {
+ // Can't use IPv6 addresses yet
+ if (@is_ipv6($package['ip'])) return false;
+
+ // Workaround for "MySQL server has gone away"
+ bb2_db_query("SET @@session.wait_timeout = 90");
+
+ // Only conservative lists
+ $bb2_blackhole_lists = array(
+ "sbl-xbl.spamhaus.org", // All around nasties
+// "dnsbl.sorbs.net", // Old useless data.
+// "list.dsbl.org", // Old useless data.
+// "dnsbl.ioerror.us", // Bad Behavior Blackhole
+ );
+
+ // Things that shouldn't be blocked, from aggregate lists
+ $bb2_blackhole_exceptions = array(
+ "sbl-xbl.spamhaus.org" => array("127.0.0.4"), // CBL is problematic
+ "dnsbl.sorbs.net" => array("127.0.0.10",), // Dynamic IPs only
+ "list.dsbl.org" => array(),
+ "dnsbl.ioerror.us" => array(),
+ );
+
+ // Check the blackhole lists
+ $ip = $package['ip'];
+ $find = implode('.', array_reverse(explode('.', $ip)));
+ foreach ($bb2_blackhole_lists as $dnsbl) {
+ $result = gethostbynamel($find . "." . $dnsbl . ".");
+ if (!empty($result)) {
+ // Got a match and it isn't on the exception list
+ $result = @array_diff($result, $bb2_blackhole_exceptions[$dnsbl]);
+ if (!empty($result)) {
+ return '136673cd';
+ }
+ }
+ }
+ return false;
+}
+
+function bb2_httpbl($settings, $package) {
+ // Can't use IPv6 addresses yet
+ if (@is_ipv6($package['ip'])) return false;
+
+ if (@!$settings['httpbl_key']) return false;
+
+ // Workaround for "MySQL server has gone away"
+ bb2_db_query("SET @@session.wait_timeout = 90");
+
+ $find = implode('.', array_reverse(explode('.', $package['ip'])));
+ $result = gethostbynamel($settings['httpbl_key'].".${find}.dnsbl.httpbl.org.");
+ if (!empty($result)) {
+ $ip = explode('.', $result[0]);
+ if ($ip[0] == 127 && ($ip[3] & 7) && $ip[2] >= $settings['httpbl_threat'] && $ip[1] <= $settings['httpbl_maxage']) {
+ return '2b021b1f';
+ }
+ }
+ return false;
+}
+?>
diff --git a/include/bad-behavior/blacklist.inc.php b/include/bad-behavior/blacklist.inc.php
new file mode 100644
index 0000000..e9ca62a
--- /dev/null
+++ b/include/bad-behavior/blacklist.inc.php
@@ -0,0 +1,127 @@
+<?php if (!defined('BB2_CORE')) die('I said no cheating!');
+
+function bb2_blacklist($package) {
+
+ // Blacklisted user agents
+ // These user agent strings occur at the beginning of the line.
+ $bb2_spambots_0 = array(
+ "<sc", // XSS exploit attempts
+ "8484 Boston Project", // video poker/porn spam
+ "adwords", // referrer spam
+ "autoemailspider", // spam harvester
+ "blogsearchbot-martin", // from honeypot
+ "CherryPicker", // spam harvester
+ "core-project/", // FrontPage extension exploits
+ "Diamond", // delivers spyware/adware
+ "Digger", // spam harvester
+ "ecollector", // spam harvester
+ "EmailCollector", // spam harvester
+ "Email Siphon", // spam harvester
+ "EmailSiphon", // spam harvester
+ "grub crawler", // misc comment/email spam
+ "HttpProxy", // misc comment/email spam
+ "Internet Explorer", // XMLRPC exploits seen
+ "ISC Systems iRc", // spam harvester
+ "Jakarta Commons", // custommised spambots
+ "Java 1.", // definitely a spammer
+ "Java/1.", // definitely a spammer
+ "libwww-perl", // spambot scripts
+ "LWP", // spambot scripts
+ "Microsoft URL", // spam harvester
+ "Missigua", // spam harvester
+ "MJ12bot/v1.0.8", // malicious botnet
+ "Movable Type", // customised spambots
+ "Mozilla ", // malicious software
+ "Mozilla/2", // malicious software
+ "Mozilla/4.0(", // from honeypot
+ "Mozilla/4.0+(", // suspicious harvester
+ "MSIE", // malicious software
+ "NutchCVS", // unidentified robots
+ "Nutscrape/", // misc comment spam
+ "OmniExplorer", // spam harvester
+ "psycheclone", // spam harvester
+ "PussyCat ", // misc comment spam
+ "PycURL", // misc comment spam
+// "Shockwave Flash", // spam harvester
+// WP 2.5 now has Flash; FIXME
+ "Super Happy Fun ", // spam harvester
+ "TrackBack/", // trackback spam
+ "user", // suspicious harvester
+ "User Agent: ", // spam harvester
+ "User-Agent: ", // spam harvester
+ "WebSite-X Suite", // misc comment spam
+ "Winnie Poh", // Automated Coppermine hacks
+ "Wordpress", // malicious software
+ "\"", // malicious software
+ );
+
+ // These user agent strings occur anywhere within the line.
+ $bb2_spambots = array(
+ "\r", // A really dumb bot
+ "; Widows ", // misc comment/email spam
+ "a href=", // referrer spam
+ "Bad Behavior Test", // Add this to your user-agent to test BB
+ "compatible ; MSIE", // misc comment/email spam
+ "compatible-", // misc comment/email spam
+ "DTS Agent", // misc comment/email spam
+ "Email Extractor", // spam harvester
+ "Gecko/25", // revisit this in 500 years
+ "grub-client", // search engine ignores robots.txt
+ "hanzoweb", // very badly behaved crawler
+ "Indy Library", // misc comment/email spam
+ "MSIE 7.0; Windows NT 5.2", // Cyveillance
+ "Murzillo compatible", // comment spam bot
+ ".NET CLR 1)", // free poker, etc.
+ "POE-Component-Client", // free poker, etc.
+ "Turing Machine", // www.anonymizer.com abuse
+ "unspecified.mail", // stealth harvesters
+ "User-agent: ", // spam harvester/splogger
+ "WebaltBot", // spam harvester
+ "WISEbot", // spam harvester
+ "WISEnutbot", // spam harvester
+ "Windows NT 4.0;)", // wikispam bot
+ "Windows NT 5.0;)", // wikispam bot
+ "Windows NT 5.1;)", // wikispam bot
+ "Windows XP 5", // spam harvester
+ "WordPress/4.01", // pingback spam
+ "Xedant Human Emulator",// spammer script engine
+ "\\\\)", // spam harvester
+ );
+
+ // These are regular expression matches.
+ $bb2_spambots_regex = array(
+ "/^[A-Z]{10}$/", // misc email spam
+// msnbot is using this fake user agent string now
+// "/^Mozilla...[05]$/i", // fake user agent/email spam
+ "/[bcdfghjklmnpqrstvwxz ]{8,}/",
+// "/(;\){1,2}$/", // misc spammers/harvesters
+// "/MSIE.*Windows XP/", // misc comment spam
+ );
+
+ // Do not edit below this line.
+
+ @$ua = $package['headers_mixed']['User-Agent'];
+
+ foreach ($bb2_spambots_0 as $spambot) {
+ $pos = strpos($ua, $spambot);
+ if ($pos !== FALSE && $pos == 0) {
+ return "17f4e8c8";
+ }
+ }
+
+ foreach ($bb2_spambots as $spambot) {
+ if (strpos($ua, $spambot) !== FALSE) {
+ return "17f4e8c8";
+ }
+ }
+
+ foreach ($bb2_spambots_regex as $spambot) {
+ if (preg_match($spambot, $ua)) {
+ return "17f4e8c8";
+ }
+ }
+
+ return FALSE;
+}
+
+?>
diff --git a/include/bad-behavior/common_tests.inc.php b/include/bad-behavior/common_tests.inc.php
new file mode 100644
index 0000000..e4d88f0
--- /dev/null
+++ b/include/bad-behavior/common_tests.inc.php
@@ -0,0 +1,143 @@
+<?php if (!defined('BB2_CORE')) die('I said no cheating!');
+
+// Enforce adherence to protocol version claimed by user-agent.
+
+function bb2_protocol($settings, $package)
+{
+ // Is it claiming to be HTTP/1.0? Then it shouldn't do HTTP/1.1 things
+ // Always run this test; we should never see Expect:
+ if (array_key_exists('Expect', $package['headers_mixed']) && stripos($package['headers_mixed']['Expect'], "100-continue") !== FALSE) {
+ return "a0105122";
+ }
+
+ // Is it claiming to be HTTP/1.1? Then it shouldn't do HTTP/1.0 things
+ // Blocks some common corporate proxy servers in strict mode
+ if ($settings['strict'] && !strcmp($package['server_protocol'], "HTTP/1.1")) {
+ if (array_key_exists('Pragma', $package['headers_mixed']) && strpos($package['headers_mixed']['Pragma'], "no-cache") !== FALSE && !array_key_exists('Cache-Control', $package['headers_mixed'])) {
+ return "41feed15";
+ }
+ }
+ return false;
+}
+
+function bb2_cookies($settings, $package)
+{
+ // Enforce RFC 2965 sec 3.3.5 and 9.1
+ // Bots wanting new-style cookies should send Cookie2
+ // FIXME: Amazon Kindle is broken; Amazon has been notified 9/24/08
+ if (@strpos($package['headers_mixed']['Cookie'], '$Version=0') !== FALSE && !array_key_exists('Cookie2', $package['headers_mixed']) && strpos($package['headers_mixed']['User-Agent'], "Kindle/") === FALSE) {
+ return '6c502ff1';
+ }
+ return false;
+}
+
+function bb2_misc_headers($settings, $package)
+{
+ @$ua = $package['headers_mixed']['User-Agent'];
+
+ if (!strcmp($package['request_method'], "POST") && empty($ua)) {
+ return "f9f2b8b9";
+ }
+
+ // Broken spambots send URLs with various invalid characters
+ // Some broken browsers send the #vector in the referer field :(
+ // if (strpos($package['request_uri'], "#") !== FALSE || strpos($package['headers_mixed']['Referer'], "#") !== FALSE) {
+ if (strpos($package['request_uri'], "#") !== FALSE) {
+ return "dfd9b1ad";
+ }
+ // A pretty nasty SQL injection attack on IIS servers
+ if (strpos($package['request_uri'], ";DECLARE%20@") !== FALSE) {
+ return "dfd9b1ad";
+ }
+
+ // Range: field exists and begins with 0
+ // Real user-agents do not start ranges at 0
+ // NOTE: this blocks the whois.sc bot. No big loss.
+ // Exceptions: MT (not fixable); LJ (refuses to fix; may be
+ // blocked again in the future)
+ if ($settings['strict'] && array_key_exists('Range', $package['headers_mixed']) && strpos($package['headers_mixed']['Range'], "=0-") !== FALSE) {
+ if (strncmp($ua, "MovableType", 11) && strncmp($ua, "URI::Fetch", 10) && strncmp($ua, "php-openid/", 11)) {
+ return "7ad04a8a";
+ }
+ }
+
+ // Content-Range is a response header, not a request header
+ if (array_key_exists('Content-Range', $package['headers_mixed'])) {
+ return '7d12528e';
+ }
+
+ // Lowercase via is used by open proxies/referrer spammers
+ // Exceptions: Clearswift uses lowercase via (refuses to fix;
+ // may be blocked again in the future)
+ if (array_key_exists('via', $package['headers']) &&
+ strpos($package['headers']['via'],'Clearswift') === FALSE &&
+ strpos($ua,'CoralWebPrx') === FALSE) {
+ return "9c9e4979";
+ }
+
+ // pinappleproxy is used by referrer spammers
+ if (array_key_exists('Via', $package['headers_mixed'])) {
+ if (stripos($package['headers_mixed']['Via'], "pinappleproxy") !== FALSE || stripos($package['headers_mixed']['Via'], "PCNETSERVER") !== FALSE || stripos($package['headers_mixed']['Via'], "Invisiware") !== FALSE) {
+ return "939a6fbb";
+ }
+ }
+
+ // TE: if present must have Connection: TE
+ // RFC 2616 14.39
+ // Blocks Microsoft ISA Server 2004 in strict mode. Contact Microsoft
+ // to obtain a hotfix.
+ if ($settings['strict'] && array_key_exists('Te', $package['headers_mixed'])) {
+ if (!preg_match('/\bTE\b/', $package['headers_mixed']['Connection'])) {
+ return "582ec5e4";
+ }
+ }
+
+ if (array_key_exists('Connection', $package['headers_mixed'])) {
+ // Connection: keep-alive and close are mutually exclusive
+ if (preg_match('/\bKeep-Alive\b/i', $package['headers_mixed']['Connection']) && preg_match('/\bClose\b/i', $package['headers_mixed']['Connection'])) {
+ return "a52f0448";
+ }
+ // Close shouldn't appear twice
+ if (preg_match('/\bclose,\s?close\b/i', $package['headers_mixed']['Connection'])) {
+ return "a52f0448";
+ }
+ // Keey-Alive shouldn't appear twice either
+ if (preg_match('/\bkeep-alive,\s?keep-alive\b/i', $package['headers_mixed']['Connection'])) {
+ return "a52f0448";
+ }
+ }
+
+
+ // Headers which are not seen from normal user agents; only malicious bots
+ if (array_key_exists('X-Aaaaaaaaaaaa', $package['headers_mixed']) || array_key_exists('X-Aaaaaaaaaa', $package['headers_mixed'])) {
+ return "b9cc1d86";
+ }
+ // Proxy-Connection does not exist and should never be seen in the wild
+ if (array_key_exists('Proxy-Connection', $package['headers_mixed'])) {
+ return "b7830251";
+ }
+
+ if (array_key_exists('Referer', $package['headers_mixed'])) {
+ // Referer, if it exists, must not be blank
+ if (empty($package['headers_mixed']['Referer'])) {
+ return "69920ee5";
+ }
+
+ // Referer, if it exists, must contain a :
+ // While a relative URL is technically valid in Referer, all known
+ // legit user-agents send an absolute URL
+ if (strpos($package['headers_mixed']['Referer'], ":") === FALSE) {
+ return "45b35e30";
+ }
+ }
+
+ // "uk" is not a language (ISO 639) nor a country (ISO 3166)
+ // oops, yes it is :( Please shoot any Ukrainian spammers you see.
+# if (preg_match('/\buk\b/', $package['headers_mixed']['Accept-Language'])) {
+# return "35ea7ffa";
+# }
+
+ return false;
+}
+
+?>
diff --git a/include/bad-behavior/core.inc.php b/include/bad-behavior/core.inc.php
new file mode 100644
index 0000000..0b09fb5
--- /dev/null
+++ b/include/bad-behavior/core.inc.php
@@ -0,0 +1,154 @@
+<?php if (!defined('BB2_CWD')) die("I said no cheating!");
+
+// Bad Behavior entry point is bb2_start()
+// If you're reading this, you are probably lost.
+// Go read the bad-behavior-generic.php file.
+
+define('BB2_CORE', dirname(__FILE__));
+define('BB2_COOKIE', 'bb2_screener_');
+
+require_once(BB2_CORE . "/functions.inc.php");
+
+// Kill 'em all!
+function bb2_banned($settings, $package, $key, $previous_key=false)
+{
+ // Some spambots hit too hard. Slow them down a bit.
+ sleep(2);
+
+ require_once(BB2_CORE . "/banned.inc.php");
+ bb2_display_denial($settings, $key, $previous_key);
+ bb2_log_denial($settings, $package, $key, $previous_key);
+ if (is_callable('bb2_banned_callback')) {
+ bb2_banned_callback($settings, $package, $key);
+ }
+ // Penalize the spammers some more
+ require_once(BB2_CORE . "/housekeeping.inc.php");
+ bb2_housekeeping($settings, $package);
+ die();
+}
+
+function bb2_approved($settings, $package)
+{
+ // Dirk wanted this
+ if (is_callable('bb2_approved_callback')) {
+ bb2_approved_callback($settings, $package);
+ }
+
+ // Decide what to log on approved requests.
+ if (($settings['verbose'] && $settings['logging']) || empty($package['user_agent'])) {
+ bb2_db_query(bb2_insert($settings, $package, "00000000"));
+ }
+}
+
+
+// Let God sort 'em out!
+function bb2_start($settings)
+{
+ // Gather up all the information we need, first of all.
+ $headers = bb2_load_headers();
+ // Postprocess the headers to mixed-case
+ // TODO: get the world to stop using PHP as CGI
+ $headers_mixed = array();
+ foreach ($headers as $h => $v) {
+ $headers_mixed[uc_all($h)] = $v;
+ }
+
+ // IPv6 - IPv4 compatibility mode hack
+ $_SERVER['REMOTE_ADDR'] = preg_replace("/^::ffff:/", "", $_SERVER['REMOTE_ADDR']);
+
+ // Reconstruct the HTTP entity, if present.
+ $request_entity = array();
+ if (!strcasecmp($_SERVER['REQUEST_METHOD'], "POST") || !strcasecmp($_SERVER['REQUEST_METHOD'], "PUT")) {
+ foreach ($_POST as $h => $v) {
+ $request_entity[$h] = $v;
+ }
+ }
+
+ @$package = array('ip' => $_SERVER['REMOTE_ADDR'], 'headers' => $headers, 'headers_mixed' => $headers_mixed, 'request_method' => $_SERVER['REQUEST_METHOD'], 'request_uri' => $_SERVER['REQUEST_URI'], 'server_protocol' => $_SERVER['SERVER_PROTOCOL'], 'request_entity' => $request_entity, 'user_agent' => $_SERVER['HTTP_USER_AGENT'], 'is_browser' => false);
+
+ $result = bb2_screen($settings, $package);
+ if ($result && !defined('BB2_TEST')) bb2_banned($settings, $package, $result);
+ return $result;
+}
+
+function bb2_screen($settings, $package)
+{
+ // Please proceed to the security checkpoint and have your
+ // identification and boarding pass ready.
+
+ // First check the whitelist
+ require_once(BB2_CORE . "/whitelist.inc.php");
+ if (!bb2_whitelist($package)) {
+ // Now check the blacklist
+ require_once(BB2_CORE . "/blacklist.inc.php");
+ if ($r = bb2_blacklist($package)) return $r;
+
+ // Check the http:BL
+ require_once(BB2_CORE . "/blackhole.inc.php");
+ if ($r = bb2_httpbl($settings, $package)) return $r;
+
+ // Check for common stuff
+ require_once(BB2_CORE . "/common_tests.inc.php");
+ if ($r = bb2_protocol($settings, $package)) return $r;
+ if ($r = bb2_cookies($settings, $package)) return $r;
+ if ($r = bb2_misc_headers($settings, $package)) return $r;
+
+ // Specific checks
+ @$ua = $package['user_agent'];
+ // MSIE checks
+ if (stripos($ua, "; MSIE") !== FALSE) {
+ $package['is_browser'] = true;
+ if (stripos($ua, "Opera") !== FALSE) {
+ require_once(BB2_CORE . "/opera.inc.php");
+ if ($r = bb2_opera($package)) return $r;
+ } else {
+ require_once(BB2_CORE . "/msie.inc.php");
+ if ($r = bb2_msie($package)) return $r;
+ }
+ } elseif (stripos($ua, "Konqueror") !== FALSE) {
+ $package['is_browser'] = true;
+ require_once(BB2_CORE . "/konqueror.inc.php");
+ if ($r = bb2_konqueror($package)) return $r;
+ } elseif (stripos($ua, "Opera") !== FALSE) {
+ $package['is_browser'] = true;
+ require_once(BB2_CORE . "/opera.inc.php");
+ if ($r = bb2_opera($package)) return $r;
+ } elseif (stripos($ua, "Safari") !== FALSE) {
+ $package['is_browser'] = true;
+ require_once(BB2_CORE . "/safari.inc.php");
+ if ($r = bb2_safari($package)) return $r;
+ } elseif (stripos($ua, "Lynx") !== FALSE) {
+ $package['is_browser'] = true;
+ require_once(BB2_CORE . "/lynx.inc.php");
+ if ($r = bb2_lynx($package)) return $r;
+ } elseif (stripos($ua, "MovableType") !== FALSE) {
+ require_once(BB2_CORE . "/movabletype.inc.php");
+ if ($r = bb2_movabletype($package)) return $r;
+ } elseif (stripos($ua, "msnbot") !== FALSE || stripos($ua, "MS Search") !== FALSE) {
+ require_once(BB2_CORE . "/msnbot.inc.php");
+ if ($r = bb2_msnbot($package)) return $r;
+ } elseif (stripos($ua, "Googlebot") !== FALSE || stripos($ua, "Mediapartners-Google") !== FALSE || stripos($ua, "Google Wireless") !== FALSE) {
+ require_once(BB2_CORE . "/google.inc.php");
+ if ($r = bb2_google($package)) return $r;
+ } elseif (stripos($ua, "Mozilla") !== FALSE && stripos($ua, "Mozilla") == 0) {
+ $package['is_browser'] = true;
+ require_once(BB2_CORE . "/mozilla.inc.php");
+ if ($r = bb2_mozilla($package)) return $r;
+ }
+
+ // More intensive screening applies to POST requests
+ if (!strcasecmp('POST', $package['request_method'])) {
+ require_once(BB2_CORE . "/post.inc.php");
+ if ($r = bb2_post($settings, $package)) return $r;
+ }
+ }
+
+ // Last chance screening.
+ require_once(BB2_CORE . "/screener.inc.php");
+ bb2_screener($settings, $package);
+
+ // And that's about it.
+ bb2_approved($settings, $package);
+ return false;
+}
+?>
diff --git a/include/bad-behavior/functions.inc.php b/include/bad-behavior/functions.inc.php
new file mode 100644
index 0000000..22e8882
--- /dev/null
+++ b/include/bad-behavior/functions.inc.php
@@ -0,0 +1,70 @@
+<?php if (!defined('BB2_CORE')) die("I said no cheating!");
+
+// Miscellaneous helper functions.
+
+// stripos() needed because stripos is only present on PHP 5
+if (!function_exists('stripos')) {
+ function stripos($haystack,$needle,$offset = 0) {
+ return(strpos(strtolower($haystack),strtolower($needle),$offset));
+ }
+}
+
+// str_split() needed because str_split is only present on PHP 5
+if (!function_exists('str_split')) {
+ function str_split($string, $split_length=1)
+ {
+ if ($split_length < 1) {
+ return false;
+ }
+
+ for ($pos=0, $chunks = array(); $pos < strlen($string); $pos+=$split_length) {
+ $chunks[] = substr($string, $pos, $split_length);
+ }
+ return $chunks;
+ }
+}
+
+// Convert a string to mixed-case on word boundaries.
+function uc_all($string) {
+ $temp = preg_split('/(\W)/', str_replace("_", "-", $string), -1, PREG_SPLIT_DELIM_CAPTURE);
+ foreach ($temp as $key=>$word) {
+ $temp[$key] = ucfirst(strtolower($word));
+ }
+ return join ('', $temp);
+}
+
+// Determine if an IP address resides in a CIDR netblock or netblocks.
+function match_cidr($addr, $cidr) {
+ $output = false;
+
+ if (is_array($cidr)) {
+ foreach ($cidr as $cidrlet) {
+ if (match_cidr($addr, $cidrlet)) {
+ $output = true;
+ }
+ }
+ } else {
+ @list($ip, $mask) = explode('/', $cidr);
+ if (!$mask) $mask = 32;
+ $mask = pow(2,32) - pow(2, (32 - $mask));
+ $output = ((ip2long($addr) & $mask) == (ip2long($ip) & $mask));
+ }
+ return $output;
+}
+
+// Obtain all the HTTP headers.
+// NB: on PHP-CGI we have to fake it out a bit, since we can't get the REAL
+// headers. Run PHP as Apache 2.0 module if possible for best results.
+function bb2_load_headers() {
+ if (!is_callable('getallheaders')) {
+ $headers = array();
+ foreach ($_SERVER as $h => $v)
+ if (ereg('HTTP_(.+)', $h, $hp))
+ $headers[str_replace("_", "-", uc_all($hp[1]))] = $v;
+ } else {
+ $headers = getallheaders();
+ }
+ return $headers;
+}
+
+?>
diff --git a/include/bad-behavior/google.inc.php b/include/bad-behavior/google.inc.php
new file mode 100644
index 0000000..956bdb4
--- /dev/null
+++ b/include/bad-behavior/google.inc.php
@@ -0,0 +1,13 @@
+<?php if (!defined('BB2_CORE')) die('I said no cheating!');
+
+// Analyze user agents claiming to be Googlebot
+
+function bb2_google($package)
+{
+ if (match_cidr($package['ip'], "66.249.64.0/19") === FALSE && match_cidr($package['ip'], "64.233.160.0/19") === FALSE && match_cidr($package['ip'], "72.14.192.0/18") === FALSE) {
+ return "f1182195";
+ }
+ return false;
+}
+
+?>
diff --git a/include/bad-behavior/housekeeping.inc.php b/include/bad-behavior/housekeeping.inc.php
new file mode 100644
index 0000000..b837ee0
--- /dev/null
+++ b/include/bad-behavior/housekeeping.inc.php
@@ -0,0 +1,16 @@
+<?php if (!defined('BB2_CORE')) die('I said no cheating!');
+
+function bb2_housekeeping($settings, $package)
+{
+ // FIXME Yes, the interval's hard coded (again) for now.
+ $query = "DELETE FROM `" . $settings['log_table'] . "` WHERE `date` < DATE_SUB('" . bb2_db_date() . "', INTERVAL 7 DAY)";
+ bb2_db_query($query);
+
+ // Waste a bunch more of the spammer's time, sometimes.
+ if (rand(1,1000) == 1) {
+ $query = "OPTIMIZE TABLE `" . $settings['log_table'] . "`";
+ bb2_db_query($query);
+ }
+}
+
+?>
diff --git a/include/bad-behavior/index.html b/include/bad-behavior/index.html
new file mode 100644
index 0000000..508b3dd
--- /dev/null
+++ b/include/bad-behavior/index.html
@@ -0,0 +1 @@
+Viewing directory contents is not permitted.
diff --git a/include/bad-behavior/konqueror.inc.php b/include/bad-behavior/konqueror.inc.php
new file mode 100644
index 0000000..3a84dba
--- /dev/null
+++ b/include/bad-behavior/konqueror.inc.php
@@ -0,0 +1,17 @@
+<?php if (!defined('BB2_CORE')) die('I said no cheating!');
+
+// Analyze user agents claiming to be Konqueror
+
+function bb2_konqueror($package)
+{
+ // CafeKelsa is a dev project at Yahoo which indexes job listings for
+ // Yahoo! HotJobs. It identifies as Konqueror so we skip these checks.
+ if (stripos($package['headers_mixed']['User-Agent'], "YahooSeeker/CafeKelsa") === FALSE || match_cidr($package['ip'], "209.73.160.0/19") === FALSE) {
+ if (!array_key_exists('Accept', $package['headers_mixed'])) {
+ return "17566707";
+ }
+ }
+ return false;
+}
+
+?>
diff --git a/include/bad-behavior/lynx.inc.php b/include/bad-behavior/lynx.inc.php
new file mode 100644
index 0000000..a59ba10
--- /dev/null
+++ b/include/bad-behavior/lynx.inc.php
@@ -0,0 +1,13 @@
+<?php if (!defined('BB2_CORE')) die('I said no cheating!');
+
+// Analyze user agents claiming to be Lynx
+
+function bb2_lynx($package)
+{
+ if (!array_key_exists('Accept', $package['headers_mixed'])) {
+ return "17566707";
+ }
+ return false;
+}
+
+?>
diff --git a/include/bad-behavior/movabletype.inc.php b/include/bad-behavior/movabletype.inc.php
new file mode 100644
index 0000000..b15fe9c
--- /dev/null
+++ b/include/bad-behavior/movabletype.inc.php
@@ -0,0 +1,14 @@
+<?php if (!defined('BB2_CORE')) die('I said no cheating!');
+
+function bb2_movabletype($package)
+{
+ // Is it a trackback?
+ if (strcasecmp($package['request_method'], "POST")) {
+ if (strcmp($package['headers_mixed']['Range'], "bytes=0-99999")) {
+ return "7d12528e";
+ }
+ }
+ return false;
+}
+
+?>
diff --git a/include/bad-behavior/mozilla.inc.php b/include/bad-behavior/mozilla.inc.php
new file mode 100644
index 0000000..a1cac82
--- /dev/null
+++ b/include/bad-behavior/mozilla.inc.php
@@ -0,0 +1,19 @@
+<?php if (!defined('BB2_CORE')) die('I said no cheating!');
+
+// Analyze user agents claiming to be Mozilla
+
+function bb2_mozilla($package)
+{
+ // First off, workaround for Google Desktop, until they fix it FIXME
+ // Google Desktop fixed it, but apparently some old versions are
+ // still out there. :(
+ // Always check accept header for Mozilla user agents
+ if (strpos($package['headers_mixed']['User-Agent'], "Google Desktop") === FALSE && strpos($package['headers_mixed']['User-Agent'], "PLAYSTATION 3") === FALSE) {
+ if (!array_key_exists('Accept', $package['headers_mixed'])) {
+ return "17566707";
+ }
+ }
+ return false;
+}
+
+?>
diff --git a/include/bad-behavior/msie.inc.php b/include/bad-behavior/msie.inc.php
new file mode 100644
index 0000000..3c49f26
--- /dev/null
+++ b/include/bad-behavior/msie.inc.php
@@ -0,0 +1,26 @@
+<?php if (!defined('BB2_CORE')) die('I said no cheating!');
+
+// Analyze user agents claiming to be MSIE
+
+function bb2_msie($package)
+{
+ if (!array_key_exists('Accept', $package['headers_mixed'])) {
+ return "17566707";
+ }
+
+ // MSIE does NOT send "Windows ME" or "Windows XP" in the user agent
+ if (strpos($package['headers_mixed']['User-Agent'], "Windows ME") !== FALSE || strpos($package['headers_mixed']['User-Agent'], "Windows XP") !== FALSE || strpos($package['headers_mixed']['User-Agent'], "Windows 2000") !== FALSE || strpos($package['headers_mixed']['User-Agent'], "Win32") !== FALSE) {
+ return "a1084bad";
+ }
+
+ // MSIE does NOT send Connection: TE but Akamai does
+ // Bypass this test when Akamai detected
+ // The latest version of IE for Windows CE also uses Connection: TE
+ if (!array_key_exists('Akamai-Origin-Hop', $package['headers_mixed']) && strpos($package['headers_mixed']['User-Agent'], "IEMobile") === FALSE && @preg_match('/\bTE\b/i', $package['headers_mixed']['Connection'])) {
+ return "2b90f772";
+ }
+
+ return false;
+}
+
+?>
diff --git a/include/bad-behavior/msnbot.inc.php b/include/bad-behavior/msnbot.inc.php
new file mode 100644
index 0000000..0341da1
--- /dev/null
+++ b/include/bad-behavior/msnbot.inc.php
@@ -0,0 +1,13 @@
+<?php if (!defined('BB2_CORE')) die('I said no cheating!');
+
+// Analyze user agents claiming to be msnbot
+
+function bb2_msnbot($package)
+{
+ if (match_cidr($package['ip'], "207.46.0.0/16") === FALSE && match_cidr($package['ip'], "65.52.0.0/14") === FALSE && match_cidr($package['ip'], "207.68.128.0/18") === FALSE && match_cidr($package['ip'], "207.68.192.0/20") === FALSE && match_cidr($package['ip'], "64.4.0.0/18") === FALSE) {
+ return "e4de0453";
+ }
+ return false;
+}
+
+?>
diff --git a/include/bad-behavior/opera.inc.php b/include/bad-behavior/opera.inc.php
new file mode 100644
index 0000000..e29a8c7
--- /dev/null
+++ b/include/bad-behavior/opera.inc.php
@@ -0,0 +1,13 @@
+<?php if (!defined('BB2_CORE')) die('I said no cheating!');
+
+// Analyze user agents claiming to be Opera
+
+function bb2_opera($package)
+{
+ if (!array_key_exists('Accept', $package['headers_mixed'])) {
+ return "17566707";
+ }
+ return false;
+}
+
+?>
diff --git a/include/bad-behavior/post.inc.php b/include/bad-behavior/post.inc.php
new file mode 100644
index 0000000..5857f1a
--- /dev/null
+++ b/include/bad-behavior/post.inc.php
@@ -0,0 +1,80 @@
+<?php if (!defined('BB2_CORE')) die('I said no cheating!');
+
+// All tests which apply specifically to POST requests
+function bb2_post($settings, $package)
+{
+ // Check blackhole lists for known spam/malicious activity
+ // require_once(BB2_CORE . "/blackhole.inc.php");
+ // if ($r = bb2_blackhole($package)) return $r;
+
+ // MovableType needs specialized screening
+ if (stripos($package['headers_mixed']['User-Agent'], "MovableType") !== FALSE) {
+ if (strcmp($package['headers_mixed']['Range'], "bytes=0-99999")) {
+ return "7d12528e";
+ }
+ }
+
+ // Trackbacks need special screening
+ $request_entity = $package['request_entity'];
+ if (isset($request_entity['title']) && isset($request_entity['url']) && isset($request_entity['blog_name'])) {
+ require_once(BB2_CORE . "/trackback.inc.php");
+ return bb2_trackback($package);
+ }
+
+ // Catch a few completely broken spambots
+ foreach ($request_entity as $key => $value) {
+ $pos = strpos($key, " document.write");
+ if ($pos !== FALSE) {
+ return "dfd9b1ad";
+ }
+ }
+
+ // If Referer exists, it should refer to a page on our site
+ if ($settings['offsite_forms'] && array_key_exists('Referer', $package['headers_mixed']) && stripos($package['headers_mixed']['Referer'], $package['headers_mixed']['Host']) === FALSE) {
+ return "cd361abb";
+ }
+
+ // Screen by cookie/JavaScript form add
+ if (isset($_COOKIE[BB2_COOKIE])) {
+ $screener1 = explode(" ", $_COOKIE[BB2_COOKIE]);
+ } else {
+ $screener1 = array(0);
+ }
+ if (isset($_POST[BB2_COOKIE])) {
+ $screener2 = explode(" ", $_POST[BB2_COOKIE]);
+ } else {
+ $screener2 = array(0);
+ }
+ $screener = max($screener1[0], $screener2[0]);
+
+ if ($screener > 0) {
+ // Posting too fast? 5 sec
+ // FIXME: even 5 sec is too intrusive
+ // if ($screener + 5 > time())
+ // return "408d7e72";
+ // Posting too slow? 48 hr
+ if ($screener + 172800 < time())
+ return "b40c8ddc";
+
+ // Screen by IP address
+ $ip = ip2long($package['ip']);
+ $ip_screener = ip2long($screener[1]);
+// FIXME: This is b0rked, but why?
+// if ($ip && $ip_screener && abs($ip_screener - $ip) > 256)
+// return "c1fa729b";
+
+ if (!empty($package['headers_mixed']['X-Forwarded-For'])) {
+ $ip = $package['headers_mixed']['X-Forwarded-For'];
+ }
+ // Screen for user agent changes
+ // User connected previously with blank user agent
+// $q = bb2_db_query("SELECT `ip` FROM " . $settings['log_table'] . " WHERE (`ip` = '" . $package['ip'] . "' OR `ip` = '" . $screener[1] . "') AND `user_agent` != '" . $package['user_agent'] . "' AND `date` > DATE_SUB('" . bb2_db_date() . "', INTERVAL 5 MINUTE)");
+ // Damnit, too many ways for this to fail :(
+// if ($q !== FALSE && $q != NULL && bb2_db_num_rows($q) > 0)
+// return "799165c2";
+ }
+
+ return false;
+}
+
+?>
diff --git a/include/bad-behavior/responses.inc.php b/include/bad-behavior/responses.inc.php
new file mode 100644
index 0000000..89c995c
--- /dev/null
+++ b/include/bad-behavior/responses.inc.php
@@ -0,0 +1,49 @@
+<?php if (!defined('BB2_CORE')) die('I said no cheating!');
+
+// Defines the responses which Bad Behavior might return.
+
+function bb2_get_response($key) {
+ $bb2_responses = array(
+ '00000000' => array('response' => 200, 'explanation' => '', 'log' => 'Permitted'),
+ '136673cd' => array('response' => 403, 'explanation' => 'Your Internet Protocol address is listed on a blacklist of addresses involved in malicious or illegal activity. See the listing below for more details on specific blacklists and removal procedures.', 'log' => 'IP address found on external blacklist'),
+ '17566707' => array('response' => 403, 'explanation' => 'An invalid request was received from your browser. This may be caused by a malfunctioning proxy server or browser privacy software.', 'log' => 'Required header \'Accept\' missing'),
+ '17f4e8c8' => array('response' => 403, 'explanation' => 'You do not have permission to access this server.', 'log' => 'User-Agent was found on blacklist'),
+ '21f11d3f' => array('response' => 403, 'explanation' => 'An invalid request was received. You claimed to be a mobile Web device, but you do not actually appear to be a mobile Web device.', 'log' => 'User-Agent claimed to be AvantGo, claim appears false'),
+ '2b021b1f' => array('response' => 403, 'explanation' => 'You do not have permission to access this server. Before trying again, run anti-virus and anti-spyware software and remove any viruses and spyware from your computer.', 'log' => 'IP address found on http:BL blacklist'),
+ '2b90f772' => array('response' => 403, 'explanation' => 'You do not have permission to access this server. If you are using the Opera browser, then Opera must appear in your user agent.', 'log' => 'Connection: TE present, not supported by MSIE'),
+ '35ea7ffa' => array('response' => 403, 'explanation' => 'You do not have permission to access this server. Check your browser\'s language and locale settings.', 'log' => 'Invalid language specified'),
+ '408d7e72' => array('response' => 403, 'explanation' => 'You do not have permission to access this server. Before trying again, run anti-virus and anti-spyware software and remove any viruses and spyware from your computer.', 'log' => 'POST comes too quickly after GET'),
+ '41feed15' => array('response' => 400, 'explanation' => 'An invalid request was received. This may be caused by a malfunctioning proxy server. Bypass the proxy server and connect directly, or contact your proxy server administrator.', 'log' => 'Header \'Pragma\' without \'Cache-Control\' prohibited for HTTP/1.1 requests'),
+ '45b35e30' => array('response' => 400, 'explanation' => 'An invalid request was received from your browser. This may be caused by a malfunctioning proxy server or browser privacy software.', 'log' => 'Header \'Referer\' is corrupt'),
+ '57796684' => array('response' => 403, 'explanation' => 'You do not have permission to access this server. Before trying again, run anti-virus and anti-spyware software and remove any viruses and spyware from your computer.', 'log' => 'Prohibited header \'X-Aaaaaaaaaa\' or \'X-Aaaaaaaaaaaa\' present'),
+ '582ec5e4' => array('response' => 400, 'explanation' => 'An invalid request was received. If you are using a proxy server, bypass the proxy server or contact your proxy server administrator. This may also be caused by a bug in the Opera web browser.', 'log' => '"Header \'TE\' present but TE not specified in \'Connection\' header'),
+ '69920ee5' => array('response' => 400, 'explanation' => 'An invalid request was received from your browser. This may be caused by a malfunctioning proxy server or browser privacy software.', 'log' => 'Header \'Referer\' present but blank'),
+ '6c502ff1' => array('response' => 403, 'explanation' => 'You do not have permission to access this server.', 'log' => 'Bot not fully compliant with RFC 2965'),
+ '799165c2' => array('response' => 403, 'explanation' => 'You do not have permission to access this server.', 'log' => 'Rotating user-agents detected'),
+ '7a06532b' => array('response' => 400, 'explanation' => 'An invalid request was received from your browser. This may be caused by a malfunctioning proxy server or browser privacy software.', 'log' => 'Required header \'Accept-Encoding\' missing'),
+ '7ad04a8a' => array('response' => 400, 'explanation' => 'The automated program you are using is not permitted to access this server. Please use a different program or a standard Web browser.', 'log' => 'Prohibited header \'Range\' present'),
+ '7d12528e' => array('response' => 403, 'explanation' => 'You do not have permission to access this server.', 'log' => 'Prohibited header \'Range\' or \'Content-Range\' in POST request'),
+ '939a6fbb' => array('response' => 403, 'explanation' => 'The proxy server you are using is not permitted to access this server. Please bypass the proxy server, or contact your proxy server administrator.', 'log' => 'Banned proxy server in use'),
+ '9c9e4979' => array('response' => 403, 'explanation' => 'The proxy server you are using is not permitted to access this server. Please bypass the proxy server, or contact your proxy server administrator.', 'log' => 'Prohibited header \'via\' present'),
+ 'a0105122' => array('response' => 417, 'explanation' => 'Expectation failed. Please retry your request.', 'log' => 'Header \'Expect\' prohibited; resend without Expect'),
+ 'a1084bad' => array('response' => 403, 'explanation' => 'You do not have permission to access this server.', 'log' => 'User-Agent claimed to be MSIE, with invalid Windows version'),
+ 'a52f0448' => array('response' => 400, 'explanation' => 'An invalid request was received. This may be caused by a malfunctioning proxy server or browser privacy software. If you are using a proxy server, bypass the proxy server or contact your proxy server administrator.', 'log' => 'Header \'Connection\' contains invalid values'),
+ 'b40c8ddc' => array('response' => 403, 'explanation' => 'You do not have permission to access this server. Before trying again, close your browser, run anti-virus and anti-spyware software and remove any viruses and spyware from your computer.', 'log' => 'POST more than two days after GET'),
+ 'b7830251' => array('response' => 400, 'explanation' => 'Your proxy server sent an invalid request. Please contact the proxy server administrator to have this problem fixed.', 'log' => 'Prohibited header \'Proxy-Connection\' present'),
+ 'b9cc1d86' => array('response' => 403, 'explanation' => 'The proxy server you are using is not permitted to access this server. Please bypass the proxy server, or contact your proxy server administrator.', 'log' => 'Prohibited header \'X-Aaaaaaaaaa\' or \'X-Aaaaaaaaaaaa\' present'),
+ 'c1fa729b' => array('response' => 403, 'explanation' => 'You do not have permission to access this server. Before trying again, run anti-virus and anti-spyware software and remove any viruses and spyware from your computer.', 'log' => 'Use of rotating proxy servers detected'),
+ 'cd361abb' => array('response' => 403, 'explanation' => 'You do not have permission to access this server. Data may not be posted from offsite forms.', 'log' => 'Referer did not point to a form on this site'),
+ 'd60b87c7' => array('response' => 403, 'explanation' => 'You do not have permission to access this server. Before trying again, please remove any viruses or spyware from your computer.', 'log' => 'Trackback received via proxy server'),
+ 'e3990b47' => array('response' => 403, 'explanation' => 'You do not have permission to access this server. Before trying again, please remove any viruses or spyware from your computer.', 'log' => 'Obviously fake trackback received'),
+ 'dfd9b1ad' => array('response' => 403, 'explanation' => 'You do not have permission to access this server.', 'log' => 'Request contained a malicious JavaScript or SQL injection attack'),
+ 'e4de0453' => array('response' => 403, 'explanation' => 'An invalid request was received. You claimed to be a major search engine, but you do not appear to actually be a major search engine.', 'log' => 'User-Agent claimed to be msnbot, claim appears to be false'),
+ 'e87553e1' => array('response' => 403, 'explanation' => 'You do not have permission to access this server.', 'log' => 'I know you and I don\'t like you, dirty spammer.'),
+ 'f0dcb3fd' => array('response' => 403, 'explanation' => 'You do not have permission to access this server. Before trying again, run anti-virus and anti-spyware software and remove any viruses and spyware from your computer.', 'log' => 'Web browser attempted to send a trackback'),
+ 'f1182195' => array('response' => 403, 'explanation' => 'An invalid request was received. You claimed to be a major search engine, but you do not appear to actually be a major search engine.', 'log' => 'User-Agent claimed to be Googlebot, claim appears to be false.'),
+ 'f9f2b8b9' => array('response' => 403, 'explanation' => 'You do not have permission to access this server. This may be caused by a malfunctioning proxy server or browser privacy software.', 'log' => 'A User-Agent is required but none was provided.'),
+ );
+
+ if (array_key_exists($key, $bb2_responses)) return $bb2_responses[$key];
+ return array('00000000');
+}
+?>
diff --git a/include/bad-behavior/safari.inc.php b/include/bad-behavior/safari.inc.php
new file mode 100644
index 0000000..523bdd5
--- /dev/null
+++ b/include/bad-behavior/safari.inc.php
@@ -0,0 +1,13 @@
+<?php if (!defined('BB2_CORE')) die('I said no cheating!');
+
+// Analyze user agents claiming to be Safari
+
+function bb2_safari($package)
+{
+ if (!array_key_exists('Accept', $package['headers_mixed'])) {
+ return "17566707";
+ }
+ return false;
+}
+
+?>
diff --git a/include/bad-behavior/screener.inc.php b/include/bad-behavior/screener.inc.php
new file mode 100644
index 0000000..55da198
--- /dev/null
+++ b/include/bad-behavior/screener.inc.php
@@ -0,0 +1,63 @@
+<?php if (!defined('BB2_CWD')) die("I said no cheating!");
+
+// Bad Behavior browser screener
+
+function bb2_screener_cookie($settings, $package, $cookie_name, $cookie_value)
+{
+ // FIXME: Set the real cookie
+ setcookie($cookie_name, $cookie_value, 0, bb2_relative_path());
+}
+
+function bb2_screener_javascript($settings, $package, $cookie_name, $cookie_value)
+{
+ global $bb2_javascript;
+
+ // FIXME: do something
+ $bb2_javascript = "<script type=\"text/javascript\">
+<!--
+function bb2_addLoadEvent(func) {
+ var oldonload = window.onload;
+ if (typeof window.onload != 'function') {
+ window.onload = func;
+ } else {
+ window.onload = function() {
+ oldonload();
+ func();
+ }
+ }
+}
+
+bb2_addLoadEvent(function() {
+ for ( i=0; i < document.forms.length; i++ ) {
+ if (document.forms[i].method == 'post') {
+ var myElement = document.createElement('input');
+ myElement.setAttribute('type', 'hidden');
+ myElement.name = '$cookie_name';
+ myElement.value = '$cookie_value';
+ document.forms[i].appendChild(myElement);
+ }
+ }
+});
+// --></script>
+ ";
+}
+
+function bb2_screener($settings, $package)
+{
+ $cookie_name = BB2_COOKIE;
+
+ // Set up a simple cookie
+ $screener = array(time(), $package['ip']);
+ if (isset($package['headers_mixed']['X-Forwarded-For'])) {
+ array_push($screener, $package['headers_mixed']['X-Forwarded-For']);
+ }
+ if (isset($package['headers_mixed']['Client-Ip'])) {
+ array_push($screener, $package['headers_mixed']['Client-Ip']);
+ }
+
+ $cookie_value = implode(" ", $screener);
+
+ bb2_screener_cookie($settings, $package, BB2_COOKIE, $cookie_value);
+ bb2_screener_javascript($settings, $package, BB2_COOKIE, $cookie_value);
+}
+?>
diff --git a/include/bad-behavior/trackback.inc.php b/include/bad-behavior/trackback.inc.php
new file mode 100644
index 0000000..b284f67
--- /dev/null
+++ b/include/bad-behavior/trackback.inc.php
@@ -0,0 +1,28 @@
+<?php if (!defined('BB2_CORE')) die('I said no cheating!');
+
+// Specialized screening for trackbacks
+function bb2_trackback($package)
+{
+ // Web browsers don't send trackbacks
+ if ($package['is_browser']) {
+ return 'f0dcb3fd';
+ }
+
+ // Proxy servers don't send trackbacks either
+ if (array_key_exists('Via', $package['headers_mixed']) || array_key_exists('Max-Forwards', $package['headers_mixed']) || array_key_exists('X-Forwarded-For', $package['headers_mixed']) || array_key_exists('Client-Ip', $package['headers_mixed'])) {
+ return 'd60b87c7';
+ }
+
+ // Fake WordPress trackbacks
+ // Real ones do not contain Accept:, and have a charset defined
+ // Real WP trackbacks may contain Accept: depending on the HTTP
+ // transport being used by the sending host
+ if (strpos($package['headers_mixed']['User-Agent'], "WordPress/") !== FALSE) {
+ if (strpos($package['headers_mixed']['Content-Type'], "charset=") === FALSE) {
+ return 'e3990b47';
+ }
+ }
+ return false;
+}
+
+?>
diff --git a/include/bad-behavior/version.inc.php b/include/bad-behavior/version.inc.php
new file mode 100644
index 0000000..f615eae
--- /dev/null
+++ b/include/bad-behavior/version.inc.php
@@ -0,0 +1,3 @@
+<?php if (!defined('BB2_CWD')) die("I said no cheating!");
+define('BB2_VERSION', "2.1.2");
+?>
diff --git a/include/bad-behavior/whitelist.inc.php b/include/bad-behavior/whitelist.inc.php
new file mode 100644
index 0000000..6fa023f
--- /dev/null
+++ b/include/bad-behavior/whitelist.inc.php
@@ -0,0 +1,30 @@
+<?php if (!defined('BB2_CORE')) die('I said no cheating!');
+
+function bb2_whitelist($package)
+{
+ $whitelists = @parse_ini_file(dirname(BB2_CORE) . "/whitelist.ini");
+
+ if (@!empty($whitelists['ip'])) {
+ foreach ($whitelists['ip'] as $range) {
+ if (match_cidr($package['ip'], $range)) return true;
+ }
+ }
+ if (@!empty($whitelists['useragent'])) {
+ foreach ($whitelists['useragent'] as $user_agent) {
+ if (!strcmp($package['headers_mixed']['User-Agent'], $user_agent)) return true;
+ }
+ }
+ if (@!empty($whitelists['url'])) {
+ if (strpos($package['request_uri'], "?") === FALSE) {
+ $request_uri = $package['request_uri'];
+ } else {
+ $request_uri = substr($package['request_uri'], 0, strpos($package['request_uri'], "?"));
+ }
+ foreach ($whitelists['url'] as $url) {
+ if (!strcmp($request_uri, $url)) return true;
+ }
+ }
+ return false;
+}
+
+?>
diff --git a/include/common.php b/include/common.php
index dc5ae08..6d5f8c7 100644
--- a/include/common.php
+++ b/include/common.php
@@ -135,6 +135,9 @@ if (!defined('PUN_DISABLE_BUFFERING'))
// Define standard date/time formats
$forum_time_formats = array($pun_config['o_time_format'], 'H:i:s', 'H:i', 'g:i:s a', 'g:i a');
$forum_date_formats = array($pun_config['o_date_format'], 'Y-m-d', 'Y-d-m', 'd-m-Y', 'm-d-Y', 'M j Y', 'jS M Y');
+
+// BadBehavior will stop the spammers!
+require PUN_ROOT.'include/bad-behavior-fluxbb.php';
// Check/update/set cookie and fetch user info
$pun_user = array();
diff --git a/plugins/AP_Bad_Behavior.php b/plugins/AP_Bad_Behavior.php
new file mode 100644
index 0000000..188807c
--- /dev/null
+++ b/plugins/AP_Bad_Behavior.php
@@ -0,0 +1,110 @@
+<?php
+/***********************************************************************
+
+ Copyright (C) 2002-2005 Smartys (smartys at punbb-hosting.com)
+
+ This file is part of PunBB.
+
+ PunBB is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2 of the License,
+ or (at your option) any later version.
+
+ PunBB is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ MA 02111-1307 USA
+
+************************************************************************/
+
+// Make sure no one attempts to run this script "directly"
+if (!defined('PUN'))
+ exit;
+
+// Tell admin_loader.php that this is indeed a plugin and that it is loaded
+define('PUN_PLUGIN_LOADED', 1);
+
+// If the "Save" button was clicked
+if (isset($_POST['save']))
+{
+ $form = array_map("intval", $_POST['form']);
+ while (list($key, $input) = @each($form))
+ {
+ $db->query('UPDATE '.$db->prefix.'config SET conf_value='.$input.' WHERE conf_name=\'o_badbehavior_'.$db->escape($key).'\'') or error('Unable to update board config', __FILE__, __LINE__, $db->error());
+ }
+
+ // Regenerate the config cache
+ require_once PUN_ROOT.'include/cache.php';
+ generate_config_cache();
+
+ redirect($_SERVER['REQUEST_URI'], 'Options updated. Redirecting...');
+}
+else
+{
+ // Display the admin navigation menu
+ generate_admin_menu($plugin);
+
+?>
+ <div id="badbehaviorplugin" class="blockform">
+ <h2><span>Bad Behavior Plugin</span></h2>
+ <div class="box">
+ <div class="inbox">
+ <p>The Bad Behavior system helps protect your site from malicious bots (spammers, email harvesters, etc).</p>
+ <p>For more information please visit the <a href="http://www.bad-behavior.ioerror.us/">Bad Behavior</a> homepage.</p>
+ <p>If you find Bad Behavior valuable, please consider making a <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=error%40ioerror%2eus&item_name=Bad%20Behavior%20<?php echo BB2_VERSION; ?>%20%28From%20Admin%29&no_shipping=1&cn=Comments%20about%20Bad%20Behavior&tax=0¤cy_code=USD&bn=PP%2dDonationsBF&charset=UTF%2d8">financial contribution</a> to further development of Bad Behavior.</p>
+ </div>
+ </div>
+ <h2 class="block2"><span>Statistics:</span></h2>
+ <div class="box">
+ <div class="inbox">
+ <p><?php echo bb2_insert_stats(true) ?></p>
+ </div>
+ </div>
+ <h2 class="block2"><span>Settings</span></h2>
+ <div class="box">
+ <form id="example" method="post" action="<?php echo $_SERVER['REQUEST_URI'] ?>">
+ <p class="submittop"><input type="submit" name="save" value="Save changes" /></p>
+ <div class="inform">
+ <fieldset>
+ <legend>Change your settings and submit!</legend>
+ <div class="infldset">
+ <table class="aligntop" cellspacing="0">
+ <tr>
+ <th scope="row">Display Statistics</th>
+ <td>
+ <input type="radio" name="form[display_stats]" value="1"<?php if ($pun_config['o_badbehavior_display_stats'] == '1') echo ' checked="checked"' ?> /> <strong>Yes</strong> <input type="radio" name="form[display_stats]" value="0"<?php if ($pun_config['o_badbehavior_display_stats'] == '0') echo ' checked="checked"' ?> /> <strong>No</strong>
+ <span>Allows you to decide if statistics should be displayed publicly or not (you will also need to edit the code to include a call to bb2_insert_stats()). This setting does not affect the statistics seen above.</span>
+ </td>
+ </tr>
+ <tr>
+ <th scope="row">Verbose Logging</th>
+ <td>
+ <input type="radio" name="form[verbose]" value="1"<?php if ($pun_config['o_badbehavior_verbose'] == '1') echo ' checked="checked"' ?> /> <strong>Yes</strong> <input type="radio" name="form[verbose]" value="0"<?php if ($pun_config['o_badbehavior_verbose'] == '0') echo ' checked="checked"' ?> /> <strong>No</strong>
+ <span>More verbose logging (logs data from all requests made).</span>
+ </td>
+ </tr>
+ <tr>
+ <th scope="row">Strict Mode</th>
+ <td>
+ <input type="radio" name="form[strict]" value="1"<?php if ($pun_config['o_badbehavior_strict'] == '1') echo ' checked="checked"' ?> /> <strong>Yes</strong> <input type="radio" name="form[strict]" value="0"<?php if ($pun_config['o_badbehavior_strict'] == '0') echo ' checked="checked"' ?> /> <strong>No</strong>
+ <span>Strict checking (blocks more spam but may block some people)</span>
+ </td>
+ </tr>
+ </table>
+ </div>
+ </fieldset>
+ </div>
+ <p class="submitend"><input type="submit" name="save" value="Save changes" /></p>
+ </form>
+ </div>
+ </div>
+<?php
+
+}
+
+// Note that the script just ends here. The footer will be included by admin_loader.php.
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the Xfce4-commits
mailing list