Sinisterly
A different way of keeping spammers away from registering - Printable Version

+- Sinisterly (https://sinister.ly)
+-- Forum: Coding (https://sinister.ly/Forum-Coding)
+--- Forum: PHP (https://sinister.ly/Forum-PHP)
+--- Thread: A different way of keeping spammers away from registering (/Thread-A-different-way-of-keeping-spammers-away-from-registering)



A different way of keeping spammers away from registering - zomgwtfbbq - 04-06-2013

Creating an advanced secure login script with php,json,jquery,html and css3

[Image: rFiK0Ec.jpg]

====INTRO=====

So what? Another login? Yes sir, but don't be afraid, this login is different. The problem with most designers/programmers is that they copy other ideas instead of being a little bit more inventive. A good example is using captchas and other far from
user friendly interfaces to prevent bots from spamming and ruining your community. A few years ago I came with my own solution to battle xRumer and other bots from registering.

Personally I'm a big fan of jQuery,CSS3 and PHP, so decided to let jQuery create the login/registration process instead of using static html, in this tutorial I will show you how.
You can even secure this more by letting jquery create the input fields, but as I don't have loads of time, I'll do it the easy way. Also I left out several other parts, I just want to show you how to secure your login system from bots in a different way.

As inspiration I used the login on my hackchallenge site, this login is a less advanced one though, otherwise the tutorial would get a bit too big.

If necessary I can upload the script on my server, just ask me.

====PREPARATION====

Let's see what we need:
- editor (eg Dreamweaver,Notepad,Vi)
- php (I assume you have access to a webserver with this installed)
- latest/recent version of jQuery

That's all.

====THE CODE====

I always start with the clientside(HTML,jQuery and CSS) then afterwards create the PHP (and SQL code).

The HTML is very straightforward so I won't explain what every tag does:
Code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Advanced Login</title> <style type="text/css"> <!-- body { background:#000000;font-family:Verdana,Helvetica;font-size:12px;color:#ffffff; } .container { display:block;margin:0 auto;width:800px;overflow:auto;border: 1px solid rgba(0,0,0,0.5); border-radius: 10px 10px 2px 2px; background: rgba(0,0,0,0.25); box-shadow: 0 2px 6px rgba(0,0,0,0.5), inset 0 1px rgba(255,255,255,0.3), inset 0 10px rgba(255,255,255,0.2), inset 0 10px 20px rgba(255,255,255,0.25), inset 0 -15px 30px rgba(0,0,0,0.3); -o-box-shadow: 0 2px 6px rgba(0,0,0,0.5), inset 0 1px rgba(255,255,255,0.3), inset 0 10px rgba(255,255,255,0.2), inset 0 10px 20px rgba(255,255,255,0.25), inset 0 -15px 30px rgba(0,0,0,0.3); -webkit-box-shadow: 0 2px 6px rgba(0,0,0,0.5), inset 0 1px rgba(255,255,255,0.3), inset 0 10px rgba(255,255,255,0.2), inset 0 10px 20px rgba(255,255,255,0.25), inset 0 -15px 30px rgba(0,0,0,0.3); -moz-box-shadow: 0 2px 6px rgba(0,0,0,0.5), inset 0 1px rgba(255,255,255,0.3), inset 0 10px rgba(255,255,255,0.2), inset 0 10px 20px rgba(255,255,255,0.25), inset 0 -15px 30px rgba(0,0,0,0.3); } .container .cleft { margin:10px 0 20px 10px;float:left;width:250px; } .container .cleft .login { display:block; } .sub { display:block; } .sub .username,.sub .usernamef,.sub .password,.sub .passwordf,.sub .submit,.sub .submit .registerlink,.sub .submit .loginlink { float:left; } .sub .username,.sub .password { width:80px; } .sub .submit { padding-top:5px; } .sub .submit .registerlink:hover,.sub .submit .loginlink:hover { text-decoration:underline;color:#ff0000;cursor:pointer; } .container .cright { float:left;margin:10px 0 0 10px; } .clear { clear:both; } --> </style> </head> <body> <div class="container"> <div class="cleft"> <div class="login"> <div class="sub"> <div class="username">username</div><div class="usernamef"><input type="text" name="sUser" id="field" class="fielda" value="" /></div> </div> <div class="clear"></div> <div class="sub"> <div class="password">password</div><div class="passwordf"><input type="password" name="sPass" id="field" class="fieldb" value="" /></div> </div> <div class="clear"></div> <div class="sub"> <div class="submit"><div class="registerlink" id="action" alt="Register">[ register ]</div> <div class="loginlink" id="action" alt="Login">[ login ]</div></div> </div> </div> </div> <div class="cright"> <div class="placeholder">You don't have access to our site, please register or login(user:demo, pass:demo).</div> </div> </div> </body> </html>
You can see there's no form tag, it's what spambots are looking for.
The jQuery will create extra fields dynamically. Biggrin

Now that we have the layout completed let's move on to the jQuery part.

What will the jQuery part do?
- create and send the form
- add extra fields
- modify fields depending on register or login(default) selection
- submit button will appear if both fields are filled in
- submit button will disappear if a request is sent
- send ajax request and parses the json response from the php script
- change the placeholder in case of a login or registration otherwise alert an error
- successful login makes the form dissapear

We can create all this with way less than a 100 lines of code:
Code:
$(document).ready(function(){ // first of all we're going to append the submit button, it will stay hidden until both fields are filled out $('.sub .submit').append('<input type="submit" name="submit" class="hideme" value="Login" />'); $('input#field').keypress(function(){ if($('input.fielda').val()!='' && $('input.fieldb').val()!=''){ $('.hideme').show('fast'); } }); }); // switch between login and registration forms $(document).on("click","div#action",function(){ if($(this).attr('alt')=='Register'){ // change the text and inputfield values $('input.fieldb').get(0).type='text'; $('input.hideme').get(0).value='Register'; $('.sub .password').html('email'); } else if($(this).attr('alt')=='Login'){ $('input.fieldb').get(0).type='password'; $('input.hideme').get(0).value='Login'; $('.sub .password').html('password'); } }); // if user submits the form $(document).on("click","input.hideme",function(){ var query = ""; // create query string if($(this).attr('value')=='Register'){ query = "sUserName="+$('input.fielda').val()+"&sEmail="+$('input.fieldb').val(); } else if($(this).attr('value')=='Login'){ query = "sUserName="+$('input.fielda').val()+"&sPassWord="+$('input.fieldb').val(); } else{ alert('Unknown action, you can only register or login'); return false; } $('input.hideme').hide('fast'); // send json request $.ajax({ type: "POST", url: "handler.php", data: query, dataType: "json", beforeSend: function(){ // hide submit button to prevent duplicate requests $('input.hideme').hide('fast'); }, error: function(){ // error occured, show submission button again, plus a message alert('Connection failure.'); $('input.hideme').show('fast'); }, success: function(json){ if(json.jresult==true){ // successful login or registration, remove login and show success messages $('.cleft .login').after(json.jmessage); $('.cright .placeholder').html(json.jplaceholder); $('.cleft .login').hide('fast'); } else{ // failure $('input.hideme').show('fast'); alert(json.jmessage); } } }); });
We can put this altogether in the index.php file like this:
Code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Advanced Login</title> <style type="text/css"> <!-- body { background:#000000;font-family:Verdana,Helvetica;font-size:12px;color:#ffffff; } .container { display:block;margin:0 auto;width:800px;overflow:auto;border: 1px solid rgba(0,0,0,0.5); border-radius: 10px 10px 2px 2px; background: rgba(0,0,0,0.25); box-shadow: 0 2px 6px rgba(0,0,0,0.5), inset 0 1px rgba(255,255,255,0.3), inset 0 10px rgba(255,255,255,0.2), inset 0 10px 20px rgba(255,255,255,0.25), inset 0 -15px 30px rgba(0,0,0,0.3); -o-box-shadow: 0 2px 6px rgba(0,0,0,0.5), inset 0 1px rgba(255,255,255,0.3), inset 0 10px rgba(255,255,255,0.2), inset 0 10px 20px rgba(255,255,255,0.25), inset 0 -15px 30px rgba(0,0,0,0.3); -webkit-box-shadow: 0 2px 6px rgba(0,0,0,0.5), inset 0 1px rgba(255,255,255,0.3), inset 0 10px rgba(255,255,255,0.2), inset 0 10px 20px rgba(255,255,255,0.25), inset 0 -15px 30px rgba(0,0,0,0.3); -moz-box-shadow: 0 2px 6px rgba(0,0,0,0.5), inset 0 1px rgba(255,255,255,0.3), inset 0 10px rgba(255,255,255,0.2), inset 0 10px 20px rgba(255,255,255,0.25), inset 0 -15px 30px rgba(0,0,0,0.3); } .container .cleft { margin:10px 0 20px 10px;float:left;width:250px; } .container .cleft .login { display:block; } .sub { display:block; } .sub .username,.sub .usernamef,.sub .password,.sub .passwordf,.sub .submit,.sub .submit .registerlink,.sub .submit .loginlink { float:left; } .sub .username,.sub .password { width:80px; } .sub .submit { padding-top:5px; } .sub .submit .registerlink,.sub .submit .loginlink { padding-top:5px; } .sub .submit .registerlink:hover,.sub .submit .loginlink:hover { text-decoration:underline;color:#ff0000;cursor:pointer; } .container .cright { float:left;margin:10px 0 0 10px; } .clear { clear:both; } .hideme { display:none; } --> </style> <!-- for better performance put it in your own directory --> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script> </head> <body> <script type="text/javascript"> <!-- $(document).ready(function(){ // first of all we're going to append the submit button, it will stay hidden until both fields are filled out $('.sub .submit').append('<input type="submit" name="submit" class="hideme" value="Login" />'); $('input#field').keypress(function(){ if($('input.fielda').val()!='' && $('input.fieldb').val()!=''){ $('.hideme').show('fast'); } }); }); // switch between login and registration forms $(document).on("click","div#action",function(){ if($(this).attr('alt')=='Register'){ // change the text and inputfield values $('input.fieldb').get(0).type='text'; $('input.hideme').get(0).value='Register'; $('.sub .password').html('email'); } else if($(this).attr('alt')=='Login'){ $('input.fieldb').get(0).type='password'; $('input.hideme').get(0).value='Login'; $('.sub .password').html('password'); } }); // if user submits the form $(document).on("click","input.hideme",function(){ var query = ""; // create query string if($(this).attr('value')=='Register'){ query = "sUserName="+$('input.fielda').val()+"&sEmail="+$('input.fieldb').val(); } else if($(this).attr('value')=='Login'){ query = "sUserName="+$('input.fielda').val()+"&sPassWord="+$('input.fieldb').val(); } else{ alert('Unknown action, you can only register or login'); return false; } $('input.hideme').hide('fast'); // send json request $.ajax({ type: "POST", url: "handler.php", data: query, dataType: "json", beforeSend: function(){ // hide submit button to prevent duplicate requests $('input.hideme').hide('fast'); }, error: function(){ // error occured, show submission button again, plus a message alert('Connection failure.'); $('input.hideme').show('fast'); }, success: function(json){ if(json.jresult==true){ // successful login or registration, remove login and show success messages $('.cleft .login').after(json.jmessage); $('.cright .placeholder').html(json.jplaceholder); $('.cleft .login').hide('fast'); } else{ // failure $('input.hideme').show('fast'); alert(json.jmessage); } } }); }); //--> </script> <div class="container"> <div class="cleft"> <div class="login"> <div class="sub"> <div class="username">username</div><div class="usernamef"><input type="text" name="sUser" id="field" class="fielda" value="" /></div> </div> <div class="clear"></div> <div class="sub"> <div class="password">password</div><div class="passwordf"><input type="password" name="sPass" id="field" class="fieldb" value="" /></div> </div> <div class="clear"></div> <div class="sub"> <div class="submit"><div class="registerlink" id="action" alt="Register">[ register ]</div> <div class="loginlink" id="action" alt="Login">[ login ]</div></div> </div> </div> </div> <div class="cright"> <div class="placeholder">You don't have access to our site, please register or login(user:demo, pass:demo).</div> </div> </div> </body> </html>

This still won't work because we will need to create the file that spits out the json request so that we know whether we logged in or registered successfully.
PHP Code:
<?php /* Handler of registation, note that the login is hardcoded and you have to add a registration handler. Don't worry I've commented a lot in case you like the login and want to integrate it into your site. :) */ // setting headers session_cache_limiter('nocache'); header('Expires: '.gmdate('r',0)); header('Content-type: application/json'); // hold the result text $aDataR = array(); $aDataR['jresult'] = false; /* you can put your configuration data here for setting up a database communication or include files that will add functionality to your environment */ if(isset($_POST['sUserName']) && isset($_POST['sEmail'])){ /* registration poc - you can see if the user and email already exists - send the email with instructions to activate the account(you can use the php mail() function) */ if(!filter_var($_POST['sEmail'],FILTER_VALIDATE_EMAIL)){ $aDataR['jmessage'] = "Invalid email address"; } else{ $aDataR['jresult'] = true; $aDataR['jmessage'] = "Check your email"; $aDataR['jplaceholder'] = "Activation email sent to: ".strip_tags($_POST['sEmail']); } } elseif(isset($_POST['sUserName']) && isset($_POST['sPassWord'])){ /* login poc - here you would query the database to see whether the posted password(usually encrypted) and user matches a record */ // just a poc if($_POST['sUserName']=="demo" && $_POST['sPassWord']=="demo"){ $aDataR['jresult'] = true; $aDataR['jmessage'] = "Welcome back demo!"; $aDataR['jplaceholder'] = "You're logged in as user demo"; } else{ // prevent bruteforcing by delaying response of the server $aDataR['jmessage'] = "Invalid login"; sleep(3); /* you can log the failed logins of oourse using a file or database backend, allowing you eg to ban ip addresses */ } } else{ $aDataR['jmessage'] = "Not a valid request for this document"; } // you need to encode the response with the json_encode() function, because jQuery expects it to be in that particular format echo json_encode($aDataR); ?>
Save this file as handler.php and put it in the same folder as your index.php script that we created earlier.

Feel free to ask me questions about this login.
Cheers!


RE: A different way of keeping spammers away from registering - The Alchemist - 04-06-2013

now thats a cool way of stopping spam bots.


RE: A different way of keeping spammers away from registering - zomgwtfbbq - 04-06-2013

(04-06-2013, 01:08 PM)The Alchemist Wrote: now thats a cool way of stopping spam bots.
Thanks. Sadly webdevelopers still rely on non user friendly captchas when there are easier solutions.


RE: A different way of keeping spammers away from registering - The Alchemist - 04-06-2013

(04-06-2013, 01:24 PM)zomgwtfbbq Wrote:
(04-06-2013, 01:08 PM)The Alchemist Wrote: now thats a cool way of stopping spam bots.
Thanks. Sadly webdevelopers still rely on non user friendly captchas when there are easier solutions.
Well. I dont know jQuery and all. But, when the login screen is diaplayed, isn't the jQuery code displayed too when we try getting the contents of the index.php? It'll be difficult for spam bots to use those, but they can still get the names of the fields and send http post requests to the login.php file.
I may be wrong though.


RE: A different way of keeping spammers away from registering - zomgwtfbbq - 04-06-2013

(04-06-2013, 03:28 PM)The Alchemist Wrote:
(04-06-2013, 01:24 PM)zomgwtfbbq Wrote:
(04-06-2013, 01:08 PM)The Alchemist Wrote: now thats a cool way of stopping spam bots.
Thanks. Sadly webdevelopers still rely on non user friendly captchas when there are easier solutions.
Well. I dont know jQuery and all. But, when the login screen is diaplayed, isn't the jQuery code displayed too when we try getting the contents of the index.php? It'll be difficult for spam bots to use those, but they can still get the names of the fields and send http post requests to the login.php file.
I may be wrong though.
Some spambots can indeed read js/jquery, but the first part they will search for is the form. There isn't one, even if they manage to understand how the app works they will be mislead by the variable names. The inputfield variable names are different from the variables actually being send with ajax to the login or registration handler. Also the submission button is created dynamically.

I've tried breaking it with Xrumer 7.5 which is considered as the creme de la creme of the spambots.


RE: A different way of keeping spammers away from registering - The Alchemist - 04-06-2013

Spoiler:
(04-06-2013, 03:46 PM)zomgwtfbbq Wrote:
(04-06-2013, 03:28 PM)The Alchemist Wrote:
(04-06-2013, 01:24 PM)zomgwtfbbq Wrote:
(04-06-2013, 01:08 PM)The Alchemist Wrote: now thats a cool way of stopping spam bots.
Thanks. Sadly webdevelopers still rely on non user friendly captchas when there are easier solutions.
Well. I dont know jQuery and all. But, when the login screen is diaplayed, isn't the jQuery code displayed too when we try getting the contents of the index.php? It'll be difficult for spam bots to use those, but they can still get the names of the fields and send http post requests to the login.php file.
I may be wrong though.
Some spambots can indeed read js/jquery, but the first part they will search for is the form. There isn't one, even if they manage to understand how the app works they will be mislead by the variable names. The inputfield variable names are different from the variables actually being send with ajax to the login or registration handler. Also the submission button is created dynamically.

I've tried breaking it with Xrumer 7.5 which is considered as the creme de la creme of the spambots.

Ok. So its time for us to feel sorry for spam bots. Smile
Anyways, I'll try implementing this later on when I make login pages and stuff. You're right, it seems quite easy and better than captchas.


RE: A different way of keeping spammers away from registering - zomgwtfbbq - 04-06-2013

(04-06-2013, 03:55 PM)The Alchemist Wrote:
Spoiler:
(04-06-2013, 03:46 PM)zomgwtfbbq Wrote:
(04-06-2013, 03:28 PM)The Alchemist Wrote:
(04-06-2013, 01:24 PM)zomgwtfbbq Wrote:
(04-06-2013, 01:08 PM)The Alchemist Wrote: now thats a cool way of stopping spam bots.
Thanks. Sadly webdevelopers still rely on non user friendly captchas when there are easier solutions.
Well. I dont know jQuery and all. But, when the login screen is diaplayed, isn't the jQuery code displayed too when we try getting the contents of the index.php? It'll be difficult for spam bots to use those, but they can still get the names of the fields and send http post requests to the login.php file.
I may be wrong though.
Some spambots can indeed read js/jquery, but the first part they will search for is the form. There isn't one, even if they manage to understand how the app works they will be mislead by the variable names. The inputfield variable names are different from the variables actually being send with ajax to the login or registration handler. Also the submission button is created dynamically.

I've tried breaking it with Xrumer 7.5 which is considered as the creme de la creme of the spambots.

Ok. So its time for us to feel sorry for spam bots. Smile
Anyways, I'll try implementing this later on when I make login pages and stuff. You're right, it seems quite easy and better than captchas.
Feel free to drop a message here and I'll help you out.


RE: A different way of keeping spammers away from registering - hackarchives - 04-22-2013

If someone has JS disabled then what will happen?


RE: A different way of keeping spammers away from registering - zomgwtfbbq - 05-17-2013

(04-22-2013, 03:01 PM)hackarchives Wrote: If someone has JS disabled then what will happen?
Then they won't be able to register of course.


RE: A different way of keeping spammers away from registering - zomgwtfbbq - 05-17-2013

(04-22-2013, 03:01 PM)hackarchives Wrote: If someone has JS disabled then what will happen?
Then they won't be able to register of course.