diff --git a/README.md b/README.md index 8051923..ed140c0 100644 --- a/README.md +++ b/README.md @@ -3,13 +3,13 @@ Antiscan Automatic block (ban) IP addresses used by bad crawlers or vulnerability scanners. -**Antiscan** is an add-on module that extends the [IP address blocking](https://backdropcms.org/project/ip_blocking) +**Antiscan** is an add-on module that extends the [IP Address Blocking](https://backdropcms.org/project/ip_blocking) module (version 1.x-1.0.5 or newest) to automatically block anyone who tries to access paths defined as restricted. Usually it is a bad crawler looking for known potentially vulnerable paths, such as "wp-admin.php", "xmlrpc.php" and so on. -Also, since version 1.x-1.0.5, you can block bad bots using their well-known User-Agent strings and spam referrer domains. +Also, since version 1.x-1.0.5, you can block bad robots using their well-known User-Agent strings and spam referrer domains. **New in version version 1.x-1.0.4:** option "Report to AbuseIPDB" can be enabled for automatic reporting to AbuseIPDB about blocked scanners activity. You need to install [AbuseIPDB report](https://backdropcms.org/project/abuseipdb_report) module to see and use this option. @@ -24,7 +24,7 @@ Administration page is available via menu *Administration > Configuration > User accounts > Antiscan* (admin/config/people/antiscan) and may be used for: -- add your patterns for paths to be restricted (some usefull patterns are already added out of the box); +- add your patterns for paths to be restricted (some usefully patterns are already added out of the box); - set paths or portions of paths that will NOT be restricted to avoid self-blocking; - set "User-Agent strings" to be blocked; - set "Referrer spam domains" to be blocked; diff --git a/antiscan.admin.inc b/antiscan.admin.inc index 270f5e9..8663839 100644 --- a/antiscan.admin.inc +++ b/antiscan.admin.inc @@ -4,6 +4,7 @@ * Admin form to manage module settings * */ + /** * Define the form for manage blocking restricted paths, User-Agents and referrers * @@ -59,7 +60,7 @@ function antiscan_form($form, &$form_state) { '#rows' => 5, '#columns' => 60, '#default_value' => $blocked_ua, - '#title' => t('Blocked User-Agent strings'), + '#title' => t('Blockable User-Agent strings'), '#description' => t('Enter User-Agent strings to block, one per line.') . '
' . t('The * character is a wildcard for end of the string, so pattern like') . ' python-requests/* ' . t('will block any User-Agent strings starting with "python-requests/", for example "python-requests/2.9.0".'), @@ -72,28 +73,12 @@ function antiscan_form($form, &$form_state) { '#rows' => 5, '#columns' => 60, '#default_value' => $blocked_referrer, - '#title' => t('Blocked Referrer spam domains'), + '#title' => t('Blockable referrer spam domains'), '#description' => t('Enter referrer spam domains to block, separating them with commas or new lines.') . '
' . t('Use domain name only, for example: "semalt.com" or "buttons-for-website.com" without quotes.'), '#element_validate' => array('_validate_self_referrer'), ); - if (module_exists('abuseipdb_report')) { - $form['abuseipdb_report'] = array( - '#type' => 'checkbox', - '#title' => t('Report to AbuseIPDB'), - '#default_value' => $config->get('abuseipdb_report'), - '#description' => t('Report to AbuseIPDB about blocked scanners activity.'), - ); - } - - $form['log_enabled'] = array( - '#type' => 'checkbox', - '#title' => t('Enable logging'), - '#default_value' => $config->get('log_enabled'), - '#description' => t('Enable logging for blocked access attempts.'), - ); - $form['unblock'] = array( '#type' => 'checkbox', '#title' => t('Unblock blocked IPs automatically after:') . ' ', @@ -117,6 +102,22 @@ function antiscan_form($form, &$form_state) { ), ); + $form['log_enabled'] = array( + '#type' => 'checkbox', + '#title' => t('Enable logging'), + '#default_value' => $config->get('log_enabled'), + '#description' => t('Enable logging of blocked access attempts.'), + ); + + if (module_exists('abuseipdb_report')) { + $form['abuseipdb_report'] = array( + '#type' => 'checkbox', + '#title' => t('Report to AbuseIPDB'), + '#default_value' => $config->get('abuseipdb_report'), + '#description' => t('Report to AbuseIPDB about blocked scanners activity.'), + ); + } + $form['test_mode'] = array( '#type' => 'checkbox', '#title' => t('Test mode'), diff --git a/antiscan.info b/antiscan.info index e4d0376..24a702c 100644 --- a/antiscan.info +++ b/antiscan.info @@ -4,8 +4,8 @@ package = Spam control backdrop = 1.x type = module -dependencies[] = ip_blocking (>=1.0.5) +dependencies[] = ip_blocking (>=1.x-1.0.5) configure = admin/config/people/antiscan -version = 1.0.8 +version = 1.0.9 diff --git a/antiscan.install b/antiscan.install index 69ed24d..f4c4029 100644 --- a/antiscan.install +++ b/antiscan.install @@ -1,10 +1,9 @@ $t('version'), - 'description' => $t('IP address blocking module must have version 1.x-1.0.5 or newest.'), + 'title' => $t('IP Address Blocking module version'), + 'description' => $t('IP Address Blocking module must have version 1.x-1.0.5 or newest.'), 'value' => check_plain($ip_blocking_info['version']), 'severity' => REQUIREMENT_ERROR, ); } } - + if ($phase == 'runtime') { if ($test_mode) { $url = url('admin/config/people/antiscan'); @@ -39,7 +38,7 @@ function antiscan_requirements($phase) { array('@url' => $url)), 'severity' => REQUIREMENT_WARNING, ); - } + } } return $requirements; @@ -53,7 +52,7 @@ function antiscan_update_1000() { $config = config('antiscan.settings'); $config->set('abuseipdb_report', 0); $config->save(); - + state_set('antiscan_abuseipdb_report_last_date', time()); } @@ -65,7 +64,7 @@ function antiscan_update_1001() { $config = config('antiscan.settings'); $config->set("blocked_ua", "drupalgeddon2\r\nGo-http-client/*\r\nlibwww-perl*\r\npython-requests/*"); $config->set('blocked_referrer', 'semalt.com,buttons-for-website.com,simple-share-buttons.com,simplesharebuttons.com'); - $config->save(); + $config->save(); } /** diff --git a/antiscan.module b/antiscan.module index a5cc3a9..59a2fae 100644 --- a/antiscan.module +++ b/antiscan.module @@ -3,7 +3,7 @@ * @file antiscan.module */ -define('MODULE_UID', 10001, false); // reasonable big uid for use in DB records +define('MODULE_UID', 10001); // reasonable big uid for use in DB records /** * Implements hook_config_info(). @@ -161,10 +161,10 @@ function antiscan_action($ip, $type, $subject) { } if (!antiscan_logged_in_ip($ip)) { - header($_SERVER['SERVER_PROTOCOL'] . ' 403 Forbidden'); print $ban_message; + $reason = 'Other'; switch ($type) { case 'path': if (strlen($subject) > 45) { @@ -182,7 +182,7 @@ function antiscan_action($ip, $type, $subject) { break; } - antiscan_block_ip($ip, $reason); + antiscan_block_ip($ip, $reason, $type); exit(); } } @@ -209,10 +209,11 @@ function antiscan_logged_in_ip($ip = '') { * * @param string $ip IP address to block. * @param string $reason Reason for blocking. + * @param string $type */ -function antiscan_block_ip($ip, $reason) { - $config = config('antiscan.settings'); - $log_enabled = $config->get('log_enabled'); +function antiscan_block_ip($ip, $reason, $type) { + $config = config('antiscan.settings'); + $log_enabled = $config->get('log_enabled'); if (mb_strlen($reason,'UTF-8') > 230) { $reason_dec = urldecode(substr($reason, 0, 230)) . ' ... '; @@ -221,9 +222,16 @@ function antiscan_block_ip($ip, $reason) { $reason_dec = urldecode($reason); } + if (db_field_exists('blocked_ips', 'type')) { + $fields = array('ip' => $ip, 'reason' => $reason_dec, 'time' => time(), 'uid' => MODULE_UID, 'type' => $type); + } + else { + $fields = array('ip' => $ip, 'reason' => $reason_dec, 'time' => time(), 'uid' => MODULE_UID,); + } + // Insert the record to DB. db_insert('blocked_ips') - ->fields(array('ip' => $ip, 'reason' => $reason_dec, 'time' => time(), 'uid' => MODULE_UID)) + ->fields($fields) ->execute(); if ($log_enabled) { @@ -253,9 +261,12 @@ function antiscan_check_ip($ip) { */ function antiscan_ip_blocked($ip) { $blocked = FALSE; - if (class_exists('Database', FALSE)) { - $blocked = (bool)db_query("SELECT 1 FROM {blocked_ips} WHERE ip = :ip", array(':ip' => $ip))->fetchField(); + $blocked = (bool) db_select('blocked_ips', 'bi') + ->fields('bi', array('ip')) + ->condition('ip', $ip) + ->execute() + ->fetchField(); } return $blocked; } @@ -302,7 +313,6 @@ function antiscan_fix_duplicated_ips() { * @param int $time_expired */ function antiscan_unblock($time_expired) { - $unblocked = db_delete('blocked_ips') ->condition('uid', MODULE_UID) ->condition('time', $time_expired,'<') @@ -324,12 +334,10 @@ function antiscan_abuseipdb_report() { if ($abuseipdb_report) { $last_report_date = state_get('antiscan_abuseipdb_report_last_date', 0); - + $with_type = db_field_exists('blocked_ips', 'type'); + $fields = $with_type ? array('ip', 'reason', 'type') : array('ip', 'reason'); $result = db_select('blocked_ips', 'bi') - ->fields('bi', array( - 'ip', 'reason', - ) - ) + ->fields('bi', $fields) ->condition('uid', MODULE_UID, '=') ->condition('time', $last_report_date, '>') ->execute() @@ -338,11 +346,25 @@ function antiscan_abuseipdb_report() { if ($result) { // Most relevant categories: Bad Web Bot, Web App Attack $categories = array(19, 21); - foreach ($result as $record => $value) { $ip = $value->ip; - $request = $value->reason; - abuseipdb_report_ip($ip, $request, '"Antiscan" module', $categories); + $request = $with_type ? $value->type : $value->reason; + // Replacing information that may be sensitive. + switch ($request) { + case 'path': + $message = 'scanning for vulnerable files'; + break; + case 'ua': + $message = 'forbidden user agent'; + break; + case 'referrer': + $message = 'forbidden referrer'; + break; + default: + $message = $request; + } + + abuseipdb_report_ip($ip, $message, '"Antiscan" module', $categories); sleep(1); }