From dd0f421015059247464efd5f6d2735c5ee08a400 Mon Sep 17 00:00:00 2001 From: Michael Save Date: Thu, 12 Apr 2012 17:20:49 +1000 Subject: [PATCH] better anti-bot check --- inc/anti-bot.php | 236 ++++++++++++++++++ inc/functions.php | 161 +----------- inc/image.php | 1 - .../Twig/Extensions/Extension/Tinyboard.php | 3 +- templates/post_form.html | 51 ++-- 5 files changed, 274 insertions(+), 178 deletions(-) create mode 100644 inc/anti-bot.php diff --git a/inc/anti-bot.php b/inc/anti-bot.php new file mode 100644 index 00000000..e8c26113 --- /dev/null +++ b/inc/anti-bot.php @@ -0,0 +1,236 @@ +?=-` '; + + $chars = str_split($chars); + + $ch = array(); + + // fill up $ch until we reach $length + while(count($ch) < $length) { + $n = $length - count($ch); + $keys = array_rand($chars, $n > count($chars) ? count($chars) : $n); + if($n == 1) { + $ch[] = $chars[$keys]; + break; + } + shuffle($keys); + foreach($keys as $key) + $ch[] = $chars[$key]; + } + + $chars = $ch; + + return implode('', $chars); + } + + public static function make_confusing($string) { + $chars = str_split($string); + + foreach($chars as &$c) { + if(rand(0, 2) != 0) + continue; + $c = mb_encode_numericentity($c, array(0, 0xffff, 0, 0xffff), 'UTF-8'); + } + + return implode('', $chars); + } + + public function __construct(array $salt = array()) { + global $config; + + if(!empty($salt)) { + // create a salted hash of the "extra salt" + $this->salt = implode(':', $salt); + } else { + $this->salt = ''; + } + + shuffle($config['spam']['hidden_input_names']); + + $input_count = rand($config['spam']['hidden_inputs_min'], $config['spam']['hidden_inputs_max']); + $hidden_input_names_x = 0; + + for($x = 0; $x < $input_count ; $x++) { + if($hidden_input_names_x === false || rand(0, 2) == 0) { + // Use an obscure name + $name = $this->randomString(rand(10, 40)); + } else { + // Use a pre-defined confusing name + $name = $config['spam']['hidden_input_names'][$hidden_input_names_x++]; + if($hidden_input_names_x >= count($config['spam']['hidden_input_names'])) + $hidden_input_names_x = false; + } + + if(rand(0, 2) == 0) { + // Value must be null + $this->inputs[$name] = ''; + } elseif(rand(0, 4) == 0) { + // Numeric value + $this->inputs[$name] = (string)rand(0, 100); + } else { + // Obscure value + $this->inputs[$name] = $this->randomString(rand(5, 100)); + } + } + } + + public function html($count = false) { + $elements = array( + '', + '', + '', + '', + '', + '
', + '
', + '', + '' + ); + + $html = ''; + + if($count == 0) { + // all elements + $inputs = array_slice($this->inputs, $this->index); + } else { + $inputs = array_slice($this->inputs, $this->index, $count); + } + $this->index += count($inputs); + + foreach($inputs as $name => $value) { + $element = false; + while(!$element) { + $element = $elements[array_rand($elements)]; + if(strpos($element, 'textarea') !== false && $value == '') { + // There have been some issues with mobile web browsers and empty '; - else - $content .= ''; - break; - case 7: - if(!empty($value)) - $content .= ''; - else - $content .= ''; - break; - case 8: - $content .= '
'; - break; - } - } - - // Create a hash to validate it after - // This is the tricky part. - - // First, sort the keys in alphabetical order (A-Z) - ksort($inputs); - - $hash = ''; - - // Iterate through each input - foreach($inputs as $name => $value) { - $hash .= $name . '=' . $value; - } - - // Add a salt to the hash - $hash .= $config['cookies']['salt']; - - // Use SHA1 for the hash - $hash = sha1($hash . $extra_salt); - - // Append it to the HTML - $content .= ''; - - return $content; -} - -function checkSpam($extra_salt = array()) { - global $config; - - if(!isset($_POST['hash'])) - return true; - - $hash = $_POST['hash']; - - if(!empty($extra_salt)) { - // create a salted hash of the "extra salt" - $extra_salt = implode(':', $extra_salt); - } else { - $extra_salt = ''; - } - - // Reconsturct the $inputs array - $inputs = array(); - - foreach($_POST as $name => $value) { - if(in_array($name, $config['spam']['valid_inputs'])) - continue; - - $inputs[$name] = $value; - } - - // Sort the inputs in alphabetical order (A-Z) - ksort($inputs); - - $_hash = ''; - - // Iterate through each input - foreach($inputs as $name => $value) { - $_hash .= $name . '=' . $value; - } - - // Add a salt to the hash - $_hash .= $config['cookies']['salt']; - - // Use SHA1 for the hash - $_hash = sha1($_hash . $extra_salt); - - return $hash != $_hash; -} function buildIndex() { global $board, $config; diff --git a/inc/image.php b/inc/image.php index f6bc3e7c..d1c292dc 100644 --- a/inc/image.php +++ b/inc/image.php @@ -194,7 +194,6 @@ class ImageImagick extends ImageBase { foreach($this->original as $frame) { $delay += $frame->getImageDelay(); - //if($i < $config['thumb_keep_animation_frames']) { if(in_array($i, $keep_frames)) { // $frame->scaleImage($this->width, $this->height, false); $frame->sampleImage($this->width, $this->height); diff --git a/inc/lib/Twig/Extensions/Extension/Tinyboard.php b/inc/lib/Twig/Extensions/Extension/Tinyboard.php index 0cf7705a..7e2149e5 100644 --- a/inc/lib/Twig/Extensions/Extension/Tinyboard.php +++ b/inc/lib/Twig/Extensions/Extension/Tinyboard.php @@ -35,7 +35,8 @@ class Twig_Extensions_Extension_Tinyboard extends Twig_Extension return Array( 'time' => new Twig_Filter_Function('time', array('needs_environment' => false)), 'timezone' => new Twig_Filter_Function('twig_timezone_function', array('needs_environment' => false)), - 'createHiddenInputs' => new Twig_Filter_Function('createHiddenInputs', array('needs_environment' => false)) + 'hiddenInputs' => new Twig_Filter_Function('hiddenInputs', array('needs_environment' => false)), + 'hiddenInputsHash' => new Twig_Filter_Function('hiddenInputsHash', array('needs_environment' => false)) ); } diff --git a/templates/post_form.html b/templates/post_form.html index 1ac1dfcf..69b179fd 100644 --- a/templates/post_form.html +++ b/templates/post_form.html @@ -1,49 +1,60 @@
-{{ createHiddenInputs([board.uri, id]) }} -{% if id %}{% endif %} - -{% if mod %}{% endif %} +{{ hiddenInputs([board.uri, id]) }} +{% if id %}{% endif %} +{{ hiddenInputs([board.uri, id]) }} + +{{ hiddenInputs([board.uri, id]) }} +{% if mod %}{% endif %} {% if not config.field_disable_name or (mod and post.mod|hasPermission(config.mod.bypass_field_disable, board.uri)) %}{% endif %} {% if not config.field_disable_email or (mod and post.mod|hasPermission(config.mod.bypass_field_disable, board.uri)) %}{% endif %} {% if config.recaptcha %} {% endif %} @@ -52,16 +63,19 @@ {% trans %}File{% endtrans %} {% if config.enable_embedding %} {% endif %} @@ -73,15 +87,15 @@ @@ -89,13 +103,18 @@ {% if not config.field_disable_password or (mod and post.mod|hasPermission(config.mod.bypass_field_disable, board.uri)) %}{% endif %}
{% trans %}Name{% endtrans %} + {{ hiddenInputs([board.uri, id]) }} - + + {{ hiddenInputs([board.uri, id]) }}
{% trans %}Email{% endtrans %} + {{ hiddenInputs([board.uri, id]) }} - + + {{ hiddenInputs([board.uri, id]) }}
{% trans %}Subject{% endtrans %} + {{ hiddenInputs([board.uri, id]) }} - - {% if config.spoiler_images %} {% endif %} + + {% if config.spoiler_images %} {% endif %}
{% trans %}Comment{% endtrans %} + {{ hiddenInputs([board.uri, id]) }} + {{ hiddenInputs([board.uri, id]) }}
{% trans %}Verification{% endtrans %} + {{ hiddenInputs([board.uri, id]) }} + {{ hiddenInputs([board.uri, id]) }}
- + + {{ hiddenInputs([board.uri, id]) }}
{% trans %}Embed{% endtrans %} + {{ hiddenInputs([board.uri, id]) }} - + + {{ hiddenInputs([board.uri, id]) }}
{% if not id and post.mod|hasPermission(config.mod.sticky, board.uri) %}
-
+
{% endif %} {% if not id and post.mod|hasPermission(config.mod.lock, board.uri) %}
-
- +
+
{% endif %} {% if post.mod|hasPermission(config.mod.rawhtml, board.uri) %}
-
- +
+
{% endif %}
{% trans %}Password{% endtrans %} + {{ hiddenInputs([board.uri, id]) }} - + {% trans %}(For file deletion.){% endtrans %} + {{ hiddenInputs([board.uri, id]) }}
+{{ hiddenInputs([board.uri, id]) }} + +{{ hiddenInputs([board.uri, id], true) }}