-
Martin7483
Crossfire CMS
-
Posts: 373
Threads: 14
Joined: Sep 2015
Reputation:
20
09-30-2015, 03:28 AM
(This post was last modified: 06-20-2017, 05:01 AM by Martin7483.)
Hi,
I was searching on Google and in the CI forum but I could not find any recent topics on the use of a honey pot.
So I added it. If anyone is interested here are the steps and code required.
Any feedback is welcome
- Martin
Step 1: Edit config.php
Edit your application config.php file, located at ./application/config.php. Add the following lines to it
PHP Code: /* |-------------------------------------------------------------------------- | ANTI SPAM HONEY POT |-------------------------------------------------------------------------- | Enables the use of a invisible honey pot field. | | 'spam_protection' = TRUE => Use honey pot, FALSE => don't use honey pot | 'spam_protection_name' = The name of the honey pot cookie | 'honey_pot_expire' = The maximum time the token is valid for */ $config['spam_protection'] = TRUE; $config['spam_protection_name'] = 'ci_honey_pot'; $config['honey_pot_expire'] = 3600;
Step 2: Create MY_Input.php
Create MY_Input.php in your ./application/core directory and place the following code in it:
PHP Code: <?php if (! defined('BASEPATH')) exit('No direct script access allowed');
/** * My Input * * Extends CodeIgniters core Input with a honey pot anti-spam protection * Added config items for use. * * @author Martin Langenberg */
class MY_Input extends CI_Input { /** * Enable Honey pot flag * * Enables a honey pot token name to be set. * Set automatically based on config setting. * * @var bool */ protected $_enable_honey_pot = FALSE; public function __construct() { log_message('debug', "Class ".get_class($this)." Initialized."); parent::__construct(); $this->_enable_honey_pot = (config_item('spam_protection') === TRUE); $this->_resanitize_globals(); } // -------------------------------------------------------------------- /** * Resanitize Globals * * Internal method serving for the following purposes: * * - Sets the honey pot and validates on POST request * * @return void */ protected function _resanitize_globals() { // Honey pot protection check if ($this->_enable_honey_pot === TRUE && ! is_cli()) { $this->security->honey_pot_verify(); } log_message('debug', 'Honey pot set and verified'); } // -------------------------------------------------------------------- }
Step 3: Create MY_Security.php
Create MY_Security.php in your ./application/core directory and place the following code in it:
PHP Code: <?php if (! defined('BASEPATH')) exit('No direct script access allowed');
/** * My Security * * Extends CodeIgniters core Security with a honey pot anti-spam protection * * @author Martin Langenberg */
class MY_Security extends CI_Security { protected $_honey_pot_name; // The honey pot cookie name protected $_honey_pot_token_name; // The hashed honey pot field name protected $_honey_pot_expire; // The time the token remains valid for. Default is 1 hour public function __construct() { log_message('debug', "Class ".get_class($this)." Initialized."); parent::__construct(); $this->_honey_pot_name = config_item('spam_protection_name'); $this->_honey_pot_expire = config_item('honey_pot_expire'); } // -------------------------------------------------------------------- /** * Honey pot Verify * * @return MY_Security */ public function honey_pot_verify() { // If it's not a POST request, set the honey pot and return if (strtoupper($_SERVER['REQUEST_METHOD']) !== 'POST') { return $this->_spam_protection_set_honey_pot(); } // It's a post, get the stored token name to use with the available $_POST data $this->_honey_pot_token_name = $_COOKIE[$this->_honey_pot_name]; // Do the tokens exist in the _POST if ( ! isset( $_POST[$this->_honey_pot_token_name] ) OR strlen($_POST[$this->_honey_pot_token_name]) > 0 ) // Is the honey pot empty? { // Log a clear error, but don't print clear honey pot errors to screen log_message('error', 'The honey pot was invalid OR not empty!'); $this->csrf_show_error(); } // We kill this since we're done and we don't want to polute the _POST array unset($_POST[$this->_honey_pot_token_name]); // Nothing should last forever unset($_COOKIE[$this->_honey_pot_name]); $this->_honey_pot_token_name = NULL; $this->_spam_protection_set_honey_pot(); log_message('info', 'Honey pot verified'); return $this; } // -------------------------------------------------------------------- /** * Set Honey pot name and value * * @return string */ protected function _spam_protection_set_honey_pot() { if ($this->_honey_pot_token_name === NULL) { // If the cookie exists we will use its value. // We don't necessarily want to regenerate it with // each page load since a page could contain embedded // sub-pages causing this feature to fail if (isset($_COOKIE[$this->_honey_pot_name]) && is_string($_COOKIE[$this->_honey_pot_name]) && preg_match('#^[0-9a-f]{32}$#iS', $_COOKIE[$this->_honey_pot_name]) === 1) { return $this->_honey_pot_token_name = $_COOKIE[$this->_honey_pot_name]; } $rand = $this->get_random_bytes(16); $this->_honey_pot_token_name = ($rand === FALSE) ? md5(uniqid(mt_rand(), TRUE)) : bin2hex($rand); } $this->honey_pot_set_cookie(); return $this->_honey_pot_token_name; } // -------------------------------------------------------------------- /** * Honey pot Set Cookie * * @return CI_Security */ public function honey_pot_set_cookie() { $expire = time() + $this->_honey_pot_expire; $secure_cookie = (bool) config_item('cookie_secure'); setcookie( $this->_honey_pot_name, $this->_honey_pot_token_name, $expire, config_item('cookie_path'), config_item('cookie_domain'), $secure_cookie, config_item('cookie_httponly') ); log_message('info', 'Honey Pot cookie sent'); return $this; } // -------------------------------------------------------------------- /** * return the set honey pot token name * @return string */ public function get_honey_pot_token_name() { return $this->_honey_pot_token_name; } // -------------------------------------------------------------------- }
Step 4: Create MY_form_helper.php
Create MY_form_helper.php in your ./application/helpers directory and place the following code in it:
PHP Code: <?php /** * Crossfire CMS * * @package Crossfire CMS * @author Martin Langenberg * @copyright Copyright (c) 2011 - 2015, Martin Langenberg * @since Version 2.0 * @filesource */
/** * * This class replaces the CodeIgniter form_helper method form_open(). * It adds the use of a invisible honey pot field if required by the config. * The hidden and invisible fields are wrapped in a invisible container. */
defined('BASEPATH') OR exit('No direct script access allowed');
/** * CodeIgniter Form Helpers * * @package CodeIgniter * @subpackage Helpers * @category Helpers * @author EllisLab Dev Team * @link http://codeigniter.com/user_guide/helpers/form_helper.html */
// ------------------------------------------------------------------------
if ( ! function_exists('form_open')) { /** * Form Declaration * * Creates the opening portion of the form. * * @param string the URI segments of the form destination * @param array a key/value pair of attributes * @param array a key/value pair hidden data * @return string */ function form_open($action = '', $attributes = array(), $hidden = array()) { $CI =& get_instance();
// If no action is provided then set to the current url if ( ! $action) { $action = $CI->config->site_url($CI->uri->uri_string()); } // If an action is not a full URL then turn it into one elseif (strpos($action, '://') === FALSE) { $action = $CI->config->site_url($action); }
$attributes = _attributes_to_string($attributes);
if (stripos($attributes, 'method=') === FALSE) { $attributes .= ' method="post"'; }
if (stripos($attributes, 'accept-charset=') === FALSE) { $attributes .= ' accept-charset="'.strtolower(config_item('charset')).'"'; }
$form = '<form action="'.$action.'"'.$attributes.">\n";
// Add CSRF field if enabled, but leave it out for GET requests and requests to external websites if ($CI->config->item('csrf_protection') === TRUE && strpos($action, $CI->config->base_url()) !== FALSE && ! stripos($form, 'method="get"')) { $hidden[$CI->security->get_csrf_token_name()] = $CI->security->get_csrf_hash(); } // Add honey pot field if enabled, but leave it out for GET requests and requests to external websites if ($CI->config->item('spam_protection') === TRUE && strpos($action, $CI->config->base_url()) !== FALSE && ! stripos($form, 'method="get"')) { $hidden[$CI->security->get_honey_pot_token_name()] = NULL; }
// Make all hidden fields invisible $form .= '<div class="hidden" style="display: none;">'; if (is_array($hidden)) { foreach ($hidden as $name => $value) { $form .= '<input type="hidden" name="'.$name.'" value="'.html_escape($value).'" style="display:none;" />'."\n"; } } $form .= '</div>';
return $form; } }
And that is that. You can now have a honey pot field automatically added to a form
-
ardavan
Member
-
Posts: 114
Threads: 32
Joined: Jan 2015
Reputation:
0
Hey Martin,
thanks for sharing the codes.
I'm wonder you never mentioned about calling the helper anywhere. i didn't find any line of the code to call the helper as well !
Also im eager to know how am i able to test this functionality?
Please advice me.
Thanks
-
includebeer
CodeIgniter Team
-
Posts: 1,018
Threads: 18
Joined: Oct 2014
Reputation:
40
Interesting stuff. But why does it need a unique token? Am I wrong or is the same token used for all visitors?
-
ardavan
Member
-
Posts: 114
Threads: 32
Joined: Jan 2015
Reputation:
0
Hey @ Martin7483,
i copy and paste your honey pot code to my project.
Now How can i test whether its working on my project or not?
Thanks in advance
|