Castle == Introduction == Castle is a tool used to help protect web forms from being automatically filled in by bots. It is designed to be lightweight, and to not require complex methods. Because of these design desisions, it is not a proper captcha system. It does not prevent the same response from being submitted multiple times (though it does have a timeout option, which will prevent the response from being valid after a certain amount of time). == How it works == When used, an additional visible (by default) form field is included in your form. The user will be expected to submit the correct answer to the question or problem presented. Because a spambot will (hopefully) not have encountered the type of question or problem before, it will not be able to provide the correct answer. The answer, a timestamp (and optionally, the IP address of the user) are hashed together with two different salt values, and included (along with, in clear text, the same timestamp) in a hidden field in the form as well. After the form has been submitted, the current time is checked against the timestamp in the submitted answer, if too much time has elapsed, a "timeout" is returend. Otherwise, the provided answer is hashed with the timestamp and the two salts (and, optionally, the IP address of the user). If the resultant hash is different to the one given in the form, an error will result (otherwise, no problem). == To use == Step 1, change the two salt constants, to prevent the use of Rainbow tables, and any other options as desired (see below). Step 2, include this file in the file where you want the captcha thingy. Then, where you want the captcha, call the function nncc_displayictc() (with the paramaters as desired, see below). Step 3, include this file in the file which processes the form input, and where appropriate, call the second function nncc_compareictc() (with the correct paramaters, see below) which will compare the answer given with the correct answer. Step 4, If the result given by the comareictc() function is false, the answer was incorrect. If the result is "timeout" then the answer was not checked, as the time expired for that problem. If the result is true, then the answer was correct, and within the allowed time. == function paramaters == nncc_displayictc() === description === This function displays the 'captcha' === usage === === Parameters == $captcha int/mixed, which captcha to use, see [[#avaliable "catchas"]] below. $optparam1 mixed can be used to add variablness. $optparam2 mixed can be used to add variablness. $htmlattributes string used to add extra attributes to the label and input field. Can be used to set them both to hidden, in a honeypot situation. $idaddition string used to make the ids unique, used with the constants above, so that you can have multiple castle on one page. $xhtmlcompliant boolean, whether to add extra / to the tags, defaults to false $sleepfortime boolean, can slow down the processing by having the script sleep (currently three seconds) before returning result (if you have bots attacking your site, this slows down the number of times they can submit the form). compareictc * Compares the answer given with the correct answer and returns a result. * * @param $answergiven string the answer given to the question * @param $answerc string the hash of the answer from the hidden field. * @return on success, 'true'; on timeout, 'timeout'; on failure to get correct answer, 'fail' or boolean false. Because this function can return a non-Boolean responce, please use exact equivilent === rather than ==. == Avaliable "catchas" == There are only two built in by default. The first (1) uses the two optparam paramaters. The first is the question/problem to be displayed, and the second the expected answer. The second built in is the default, and is a simple maths problem. It will display two numbers and the answer expected is the sum of the two (the answer won't be more than 99). However, you can easily extend the function, see [[#extending]] below. == Extending == The function nncc_displayictc() has a switch statement which forms the core of that function. You can add extra cases to that switch, and then when you call the function, just give the case number, and the optional paramaters if required. Each case has to define an expected $answer, and the problem/question ($label), to be displayed. You can also define a $size for the text box where the answer will go (by default 6). For example: case 99: $size=6;//the size of the answer text box. $answer="three";//the actual answer $label='Please enter the string '.$answer.' in the text box';// the instructions provided break; If you are including tags (such as an image tag, it should use the provided $xhtmltag variable, which is either " /" or "" depending on the sixth param. Other examples: case 2:/* Case two. Selects a number at a particular position in a string, expects that number. */ $size=2; $randomnum_asstring = (string)mt_rand(1,9999999); $random_position = mt_rand(1,strlen($randomnum_asstring)); $answer=substr($randomnum_asstring,$random_position-1,1); $label='Please enter the character at position '.$random_position.', in the string '.$randomnum_asstring.':'; break; case 3:/* Case three. Selects a word from the sentence, and expects that word. */ $size=10; $randnum = mt_rand(5,11); $label = 'Please enter the '.$randnum.'th word from the start of this sentence. '; $array = explode(" ",$label); $answer= $array[$randnum-1]; break; case 4:/* Same as default case, but makes use of two optional parameters */ $size=2; $aaa = mt_rand(0,(int)$optparm1); $bbb = mt_rand(0,(int)$optparm2); $answer = $aaa + $bbb; $label='Please add together the following two numbers: '.$aaa.' and '.$bbb.': '; break; case 5:/* Multiple, uses two optional parameters */ $size=2; $answer = mt_rand(1,(int)$optparm1); $bbb = mt_rand(1,(int)$optparm2); $aaa = $answer*$bbb; $label='Given '.$aaa.' is equal to x times '.$bbb.', provide x: '; break; case 6:/* x to the power of 2. */ $size=2; $answer = mt_rand(0,10); $bbb = 2; $aaa = pow($answer,$bbb); $label='Given '.$aaa.' is equal to x to the power of '.$bbb.', provide x: '; break; case 7:/* Highlights a number in a string, expects that number. */ $size = 2; $answer=mt_rand(0,9); $label='Please enter the strong number in the box, '; for ($aaa=0;$aaa<7;$aaa++) { if (!$switc) { $abc=mt_rand(0,2); // echo '=-'.$abc.'=-'; if ($abc==2) {$switc=true; $label=$label.''.$answer.'';} else{$label=$label.mt_rand(0,9);} } else {$label=$label.mt_rand(0,9);} } if (!$switc){$label=$label.''.$answer.'';} break; case 9:// Read the text on the image... Use GD to generate an image, and then temp save it. // If you wish to implement text to speech, have a look at Festival or Flite and the many ways to use PHP and festival. $tempfilename = $optparm2; $size=4; $rannum1 = mt_rand(0,9); if ($optparm1==''){$optparm1=(string)mt_rand(1,9999999);} $answer = $optparm1.$rannum1; //create image here. $width = strlen($answer)*10; $height = 20; $image = imagecreate ($width,$height);//size of image is 12 high, and as wide as the text. $bg = imagecolorallocate($image, 255, 255, 255);// white background $txtcol = imagecolorallocate($image,0,0,0);//black text. $reccol = imagecolorallocate($image,0,00,255);//blue rectangles imagestring($image,5,2,2,$answer,$txtcol);//put the text on the image. imagerectangle($image,mt_rand(0,$width),mt_rand(0,$height),mt_rand(0,$width),mt_rand(0,$height),$reccol);//draw a rectangle over the text. imagerectangle($image,mt_rand(0,$width),mt_rand(0,$height),mt_rand(0,$width),mt_rand(0,$height),$reccol);//draw a rectangle over the text. echo "--
\n"; ob_start(); if (!imagepng($image,$tempfilename,9,null)){die ('Image png failed.');}//save to disk. ob_end_clean(); echo "\n
-/-"; imagedestroy($image); $label='What does the text on the image '.$answer.' say?: '; break; // */ == licence == Copyright 2008 - 2011 by Michael Harris, http://next-nexus.info/harrismw This program is free software. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. == not secure! == This is *not* a secure implementation of a CAPTCHA. It does not prevent multiple attempts at the same question (though it makes it hard if you are on a different IP and that option is enabled). What it does do is introduce another element to a form that will hopefully throw most bots off. How hard would it be to write a bot to pass this? Not hard at all. A correctly designed CAPTCHA does not allow multiple solution attempts at one CAPTCHA. This prevents the reuse of a correct CAPTCHA solution or making a second guess after an incorrect OCR attempt. A quote from Wikipedia. QUOTE A CAPTCHA system is a means of automatically generating new challenges which: * Current computers are unable to solve accurately. * Most humans can solve. * Does not rely on the type of CAPTCHA being new to the attacker. Although a checkbox "check here if you are not a bot" might serve to distinguish between humans and computers, it is not a CAPTCHA because it relies on the fact that an attacker has not spent effort to break that specific form. UNQUOTE So, yeah... don't use this on a large scale website unless you are willing to take the risk. == changelog and todo == Changelog and TODO list .8 After a long break, I'm back. - I deleted most of the options. - Deleted many params from the functions = This assumes that a the time stamp, the number of seconds since the epoch is always 10 chars, e.g. 1310426499 + Now proper time limited. You can specify how long + Can have more than one capcha field on a page, if you set the fourth param of the display function. + Can now have an optional attribute param on the nncc_displayictc function. Can be used to set the class, or style (or both) attribute of the input field. Could be used to set the field to be invisible (((style="display:none;"') so that this can be used as a honeypot. + Added option to include the IP address of the user in the hash, so that only the original requestor can post the form. Off by default because I'm not sure of the possible consequences. = not compatible with previous versions! Into the future: Use the user agent and put that into the hash as well, the same idea as the IP address (other headers, like the request headers, could also be used) For other ideas, please look at and .