Author |
Message |
NoFantasy
Worker


Joined: Apr 26, 2005
Posts: 114
|
Posted:
Fri Nov 24, 2006 7:00 am |
|
I made this quite simple, but working, captcha for BBtoNuke which hopefully should prevent many of the bot spammers from posting new topics and replies as guests. Logged in users is not affected.
In modules/Forums/posting.php
Find
Code:include("includes/functions_post.php");
|
After, add
Code:// MOD Captcha start
mt_srand ((double)microtime()*1000000);
$maxran = 1000000;
$captcha_num = mt_rand(0, $maxran);
// MOD Captcha end
|
Find
Code: switch ( $mode )
{
case 'editpost':
case 'newtopic':
case 'reply':
$username = ( !empty($HTTP_POST_VARS['username']) ) ? $HTTP_POST_VARS['username'] : '';
$subject = ( !empty($HTTP_POST_VARS['subject']) ) ? trim($HTTP_POST_VARS['subject']) : '';
$message = ( !empty($HTTP_POST_VARS['message']) ) ? $HTTP_POST_VARS['message'] : '';
$poll_title = ( isset($HTTP_POST_VARS['poll_title']) && $is_auth['auth_pollcreate'] ) ? $HTTP_POST_VARS['poll_title'] : '';
$poll_options = ( isset($HTTP_POST_VARS['poll_option_text']) && $is_auth['auth_pollcreate'] ) ? $HTTP_POST_VARS['poll_option_text'] : '';
$poll_length = ( isset($HTTP_POST_VARS['poll_length']) && $is_auth['auth_pollcreate'] ) ? $HTTP_POST_VARS['poll_length'] : '';
$bbcode_uid = '';
prepare_post($mode, $post_data, $bbcode_on, $html_on, $smilies_on, $error_msg, $username, $bbcode_uid, $subject, $message, $poll_title, $poll_options, $poll_length);
|
Change to
Code: switch ( $mode )
{
case 'editpost':
case 'newtopic':
case 'reply':
$username = ( !empty($HTTP_POST_VARS['username']) ) ? $HTTP_POST_VARS['username'] : '';
$subject = ( !empty($HTTP_POST_VARS['subject']) ) ? trim($HTTP_POST_VARS['subject']) : '';
$message = ( !empty($HTTP_POST_VARS['message']) ) ? $HTTP_POST_VARS['message'] : '';
$poll_title = ( isset($HTTP_POST_VARS['poll_title']) && $is_auth['auth_pollcreate'] ) ? $HTTP_POST_VARS['poll_title'] : '';
$poll_options = ( isset($HTTP_POST_VARS['poll_option_text']) && $is_auth['auth_pollcreate'] ) ? $HTTP_POST_VARS['poll_option_text'] : '';
$poll_length = ( isset($HTTP_POST_VARS['poll_length']) && $is_auth['auth_pollcreate'] ) ? $HTTP_POST_VARS['poll_length'] : '';
// MOD Captcha
if ( !$userdata['session_logged_in'] ) {
$captcha_check = ($HTTP_POST_VARS['captcha_check'] ) ? $HTTP_POST_VARS['captcha_check'] : '';
}
// MOD Captcha
$bbcode_uid = '';
prepare_post($mode, $post_data, $bbcode_on, $html_on, $smilies_on, $error_msg, $username, $bbcode_uid, $subject, $message, $poll_title, $poll_options, $poll_length, $captcha_check);
|
Find
Code:switch( $mode )
{
case 'newtopic':
$page_title = $lang['Post_a_new_topic'];
$hidden_form_fields .= '<input type="hidden" name="' . POST_FORUM_URL . '" value="' . $forum_id . '" />';
break;
case 'reply':
$page_title = $lang['Post_a_reply'];
$hidden_form_fields .= '<input type="hidden" name="' . POST_TOPIC_URL . '" value="' . $topic_id . '" />';
break;
case 'editpost':
$page_title = $lang['Edit_Post'];
$hidden_form_fields .= '<input type="hidden" name="' . POST_POST_URL . '" value="' . $post_id . '" />';
break;
}
// Generate smilies listing for page output]
|
Change to:
Code:switch( $mode )
{
case 'newtopic':
$page_title = $lang['Post_a_new_topic'];
$hidden_form_fields .= '<input type="hidden" name="' . POST_FORUM_URL . '" value="' . $forum_id . '" />';
// MOD Captcha start
if ( !$userdata['session_logged_in'] )
{
$hidden_form_fields .= '<img src="modules.php?gfx=gfx&random_num=' . $captcha_num . '" border="1" alt="Securitycode" title="Securitycode" /><br>
Type securitycode:<br>
<input type="text" name="captcha_check" size="7" maxlenght="6" />
<input type="hidden" name="captcha_num" value="' . $captcha_num . '" /><br>';
}
// MOD Captcha end
break;
case 'reply':
$page_title = $lang['Post_a_reply'];
$hidden_form_fields .= '<input type="hidden" name="' . POST_TOPIC_URL . '" value="' . $topic_id . '" />';
// MOD Captcha start
if ( !$userdata['session_logged_in'] )
{
$hidden_form_fields .= '<img src="modules.php?gfx=gfx&random_num=' . $captcha_num . '" border="1" alt="Securitycode" title="Securitycode" /><br>
Type securitycode:<br>
<input type="text" name="captcha_check" size="7" maxlenght="6" />
<input type="hidden" name="captcha_num" value="' . $captcha_num . '" /><br>';
}
// MOD Captcha end
break;
case 'editpost':
$page_title = $lang['Edit_Post'];
$hidden_form_fields .= '<input type="hidden" name="' . POST_POST_URL . '" value="' . $post_id . '" />';
break;
}
// Generate smilies listing for page output
|
In includes/functions_post.php
Find
Code:function prepare_post(&$mode, &$post_data, &$bbcode_on, &$html_on, &$smilies_on, &$error_msg, &$username, &$bbcode_uid, &$subject, &$message, &$poll_title, &$poll_options, &$poll_length)
{
global $board_config, $userdata, $lang, $phpEx, $phpbb_root_path;
|
Change to
Code:function prepare_post(&$mode, &$post_data, &$bbcode_on, &$html_on, &$smilies_on, &$error_msg, &$username, &$bbcode_uid, &$subject, &$message, &$poll_title, &$poll_options, &$poll_length, &$captcha_check)
{
global $board_config, $userdata, $lang, $phpEx, $phpbb_root_path, $sitekey;
|
Find
Code: return;
}
//
// Post a new topic/reply/poll or edit existing post/poll
//
|
Change to
Code:// MOD Captcha start
if (!empty($captcha_check))
{
if ( !$userdata['session_logged_in'] && ($mode == 'newtopic' || $mode == 'reply') )
{
$datekey = date("F j");
$rcode = hexdec(md5($_SERVER['HTTP_USER_AGENT'] . $sitekey . $_POST['captcha_num'] . $datekey));
$code = substr($rcode, 2, 6);
if ($code != $captcha_check)
{
$error_msg .= (!empty($error_msg)) ? '<br />Wrong security code' : 'Wrong security code';
}
}
}
else if ($captcha_check == '')
{
if ( !$userdata['session_logged_in'] && ($mode == 'newtopic' || $mode == 'reply') )
{
$error_msg .= (!empty($error_msg)) ? '<br />You must enter the security code' : 'You must enter the security code';
}
}
// MOD Captcha end
return;
}
//
// Post a new topic/reply/poll or edit existing post/poll
//
|
Thats about it...
The apperance of the captcha is found in modules/Forums/templates/subSilver/posting_body.tpl
I made mine a bit different from the original, like
Code:<td class="areatitle" colspan="2" align="center" height="25">
<input type="submit" tabindex="5" name="preview" class="mainoption" value="{L_PREVIEW}" />
<hr />
{S_HIDDEN_FORM_FIELDS}
<br />
<input type="submit" accesskey="s" tabindex="6" name="post" class="mainoption" value="{L_SUBMIT}" /></td>
|
however, all the code is in the {S_HIDDEN_FORM_FIELDS} so if you want it quick'n-dirty, no edits are necesarry in this file.
Please enhance, im no coder so i might have missed something along the line. It works with me, using nuke 7.6, patched 3.3 and BBtoNuke .21
For the record, if no code is written or wrong code is written an error message is appearing just like it would when no subject is applied. |
Last edited by NoFantasy on Mon Nov 27, 2006 7:56 am; edited 1 time in total |
|
|
 |
montego
Site Admin

Joined: Aug 29, 2004
Posts: 9457
Location: Arizona
|
Posted:
Fri Nov 24, 2006 10:02 am |
|
Very cool! Thanks for sharing with the community. |
_________________ Only registered users can see links on this board! Get registered or login!
Only registered users can see links on this board! Get registered or login! |
|
|
 |
NoFantasy

|
Posted:
Fri Nov 24, 2006 10:54 am |
|
yah, felt i've been asking for help all the time, so guess it's time to give a bit back.
Please feel free to make it more "allround" and get rid of any bad/unecesarry coding, as i said it's not tested on other than one of my sites. |
|
|
|
 |
evaders99
Former Moderator in Good Standing

Joined: Apr 30, 2004
Posts: 3221
|
Posted:
Sat Nov 25, 2006 1:17 am |
|
Smart stuff! |
_________________ - Only registered users can see links on this board! Get registered or login! -
Need help? Only registered users can see links on this board! Get registered or login! |
|
|
 |
NoFantasy

|
Posted:
Mon Nov 27, 2006 8:00 am |
|
...even smarter when i give you all the code, heh... I forgot to paste the part about making a random number, sorry...
Also fixed a small typo, so code above is all good now. |
|
|
|
 |
technocrat
Life Cycles Becoming CPU Cycles

Joined: Jul 07, 2005
Posts: 511
|
Posted:
Mon Nov 27, 2006 10:36 am |
|
Ah, I am not trying to be mean, but this is a poor way to do it and you can thank FB for it. The problem is your passing the number in two places which makes it visible to bots. This means it is very easy to break.
The first thing you need to do is ditch using FB's design to make a captcha, because to make the image you have to include the numbers. So modules.php?gfx=gfx&random_num=12345 can be read by a bot/scanner. This makes it VERY simple. The other problem is the hidden field that contains the number. Again this is readable.
The easiest fix would be to use sessions to hold and display the number. It would only take a few minutes to recode everything to work correctly.
Again I am not trying to be mean, I am just pointing out the flaws in the system that FB laid out. A more advanced spam bot is going to blast right through this. |
_________________ Only registered users can see links on this board! Get registered or login!
Only registered users can see links on this board! Get registered or login! / Only registered users can see links on this board! Get registered or login! |
|
|
 |
evaders99

|
Posted:
Mon Nov 27, 2006 1:28 pm |
|
But the random number itself does not match the value of the image. Is there an easy way to figure that out without knowing the randomization key?
Granted the CAPCHTA in phpNuke default is weak, as it ties one random number to a code for 24 hours. You can read it once by eye, and then have the script input the correct number for those 24 hrs. |
|
|
|
 |
technocrat

|
Posted:
Mon Nov 27, 2006 2:58 pm |
|
For starters how many people do you think change the key? You can also post and get the code like you said.
Really the whole design is pretty messed up. It should be just rewritten using sessions and more proper random generator. It would not be too hard to do. In Evo and it will show up in the next release of RN, we are using an out side phpCATPCHA that already uses sessions, and I rewrote the default one to use sessions.
Here is the code from Evo, which would need some back porting to get working on standard nuke. It's a mix of the standard and the more advance phpCATPCHA.
GFX generator
Code:if (realpath(__FILE__) == realpath($_SERVER['SCRIPT_FILENAME'])) {
exit('Access Denied');
}
include_once(dirname(dirname((__FILE__))).'/mainfile.php');
global $random_num, $evoconfig;
function random_code($number) {
$out = '';
$letters = range('a', 'z');
for ($i=0; $i < $number; $i++) {
mt_srand(crc32(microtime()));
$num = mt_rand(0,1);
if ($num) {
//Number 1 - 9
$out .= mt_rand(1, 9);
} else {
$out .= $letters[mt_rand(0, 25)];
}
}
return $out;
}
if(GDSUPPORT) {
$useimage = intval($evoconfig['useimage']);
$fontsize = 5;
$ttf = false;
if ($evoconfig['codefont']) {
$codefont = stripslashes($evoconfig['codefont']);
$font = NUKE_INCLUDE_DIR.'fonts/'.$codefont.'.ttf';
$ttf = (function_exists('imagettftext') && file_exists($font));
$ttfsize = $fontsize*2;
}
$code = random_code($evoconfig['codesize']);
$ThemeSel = get_theme();
include_once(NUKE_THEMES_DIR.$ThemeSel.'/theme.php');
if ($ttf) {
$border = imagettfbbox($ttfsize, 0, $font, $code);
$width = $border[2]-$border[0];
} else {
$width = strlen($code)*(4+$fontsize);
}
if ($useimage) {
if (file_exists("themes/$ThemeSel/images/code_bg.jpg")) {
$image = ImageCreateFromJPEG("themes/$ThemeSel/images/code_bg.jpg");
} else if (file_exists("themes/$ThemeSel/images/code_bg.png")) {
$image = ImageCreateFromPNG("themes/$ThemeSel/images/code_bg.png");
} else {
$image = ImageCreateFromJPEG('images/code_bg.jpg');
}
if (!isset($gfxcolor)) {
$gfxcolor = '#505050';
}
} else {
if (!isset($gfxcolor)) {
$txtclr = $textcolor1;
}
$bgclr = $bgcolor1;
$bred = hexdec(substr($bgclr, 1, 2));
$bgreen = hexdec(substr($bgclr, 3, 2));
$bblue = hexdec(substr($bgclr, -2));
$image = ImageCreate($width+6,20);
$background_color = ImageColorAllocate($image, $bred, $bgreen, $bblue);
ImageFill($image, 0, 0, $background_color);
}
$tred = hexdec(substr($gfxcolor, 1, 2));
$tgreen = hexdec(substr($gfxcolor, 3, 2));
$tblue = hexdec(substr($gfxcolor, -2));
$left = (imagesx($image)-$width)/2;
if (function_exists('imagecolorallocatealpha')) {
$txt_color = imagecolorallocatealpha($image, $tred, $tgreen, $tblue, 50);
if ($ttf) {
imagettftext($image, $ttfsize, 0, $left+1, 16, $txt_color, $font, $code);
} else {
ImageString($image, $fontsize, $left+2, 3, $code, $txt_color);
}
}
if ($ttf) {
imagettftext($image, $ttfsize, 0, $left, 15, ImageColorAllocate($image, $tred, $tgreen, $tblue), $font, $code);
} else {
ImageString($image, $fontsize, $left, 2, $code, ImageColorAllocate($image, $tred, $tgreen, $tblue));
}
session_start();
if(isset($_SESSION['GFXCHECK'])) unset($_SESSION['GFXCHECK']);
$_SESSION['GFXCHECK'] = $code;
Header('Content-type: image/png');
ImagePNG($image);
ImageDestroy($image);
exit;
}
|
GFX code check:
Code:function security_code_check($gfx_code, $gfxchk) {
global $evoconfig;
if (!GDSUPPORT) {
return true;
}
session_start();
if ($gfxchk != 'force') {
if (!in_array($evoconfig['usegfxcheck'],$gfxchk)) {
if (isset($_SESSION['GFXCHECK'])) unset($_SESSION['GFXCHECK']);
return true;
}
}
if (defined('CAPTCHA')) {
require_once(NUKE_CLASSES_DIR.'class.php-captcha.php');
if (PhpCaptcha::Validate($gfx_code)) {
return true;
} else {
return false;
}
} else {
if(!isset($_SESSION['GFXCHECK'])) {
return false;
}
if ($gfx_code != $_SESSION['GFXCHECK']) {
unset($_SESSION['GFXCHECK']);
return false;
}
unset($_SESSION['GFXCHECK']);
return true;
}
}
|
|
|
|
|
 |
gregexp
The Mouse Is Extension Of Arm

Joined: Feb 21, 2006
Posts: 1497
Location: In front of a screen....HELP! lol
|
Posted:
Mon Nov 27, 2006 5:57 pm |
|
In Raven's words, the old code could be hijacked to give the output.
Now as for technocrats code, looks Great but really was all that necessary?
I mean all we really would need to do is send the $random_num through sessions and not $_post. and tell the existing check to look at sessions and not the post variable, Just my thought on the matter considering that the captcha system you speak of sends the actual code itself through sessions, so no decoding. |
_________________ For those who stand shall NEVER fall and those who fall shall RISE once more!! |
|
 |
 |
technocrat

|
Posted:
Mon Nov 27, 2006 6:07 pm |
|
You have to some how get what the user entered, and it is always going to get posted (never get). |
|
|
|
 |
gregexp

|
Posted:
Mon Nov 27, 2006 7:11 pm |
|
sorry, I was reffering to the $random_num not what the user entered.
The check system in standard nuke, grabs 2 things, first the users input($_POST) and the random_num($_POST) but we could change the random number to be processed through sessions instead of post.
Thats all I meant by it. |
|
|
|
 |
NoFantasy

|
Posted:
Tue Nov 28, 2006 7:43 am |
|
technocrat wrote: | Ah, I am not trying to be mean, but this is a poor way to do it and you can thank FB for it. |
No offence taken, in any way As it says in the topic, it's a simple captcha, no more, no less. At least i got rid of a couple of spammers using this, it still remains to see if they come back with a more advanced user agent and continue their mission to inform my users of their adult sites (least they could do was to give us more interesting pictures to look on)...
Thanks for the sample code, i really hope someone make it work fully in BBtoNuke, easy to implement and also not only for the upcoming RN. |
|
|
|
 |
technocrat

|
Posted:
Tue Nov 28, 2006 10:05 am |
|
It should be easily backported from RN once it is released. With Evo we improved the base so much it can be hard to backport. |
|
|
|
 |
|