3
\$\begingroup\$

I am recently making a CMS and I need a secure login system, so this is my code. How is it?

First: the HTMLcode for signup and login:

<div id="login" style="display: none">
    <input type="text" name="email" id="login-email" placeholder=""><br><br>
    <input type="password" name="password" id="login-password" placeholder=""><br><br>
    <button type="button" id="submit-lodin"></button>
</div>
<div id="signup" style="display: none">
    <input type="text" name="firstname" id="firstname" placeholder=""><br><br>
    <input type="text" name="lastname" id="lastname" placeholder=""><br><br>
    <input type="text" name="email" id="email" placeholder=""><br><br>
    <input type="password" name="password" id="password" placeholder=""><br><br>
    <input type="password" name="re_password" id="re_password" placeholder=""><br><br>
    <button type="button" id="submit-signup"></button>
</div>

Second, the code for jQuery Ajax request for signup:

$(function(){
    $("#submit-signup").click(function(){

    var firstname   = $("#firstname").val();
    var lastname    = $("#lastname").val();
    var email       = $("#email").val();
    var password    = $("#password").val();
    var re_password = $("#re_password").val();


    if(password === re_password){
        if(validateEmail(email)){

            if(firstname == "" || lastname == "" || email == "" || password == ""|| re_password == ""){
                alert("");
            }else{
                $.ajax({
                    url : "resourcs/check_email.php",
                    type: "POST",
                    data : "firstname="+firstname+"&lastname="+lastname+"&email="+email+"&password="+password+"&re_password="+re_password  ,
                    success : function(d)
                    {
                        if(d === "ok"){
                            $.ajax({
                                url : "resourcs/register.php",
                                type: "POST",
                                data : "firstname="+firstname+"&lastname="+lastname+"&email="+email+"&password="+password+"&re_password="+re_password  ,
                                success : function(d2)
                                {
                                    if(d2 === "ok"){
                                                                                    location.reload(true);
                                    }else{
                                    alert(d2);
                                    }
                                }
                            });                          
                        }else{
                            switch(d){
                                case "error1":
                                    alert("");
                                break;                                    
                                case "error2":
                                    alert("");
                                break;                                    
                                case "error3":
                                    alert("");
                                break;                                    
                                case "error4":
                                    alert("");
                                break;    
                            };

                        }
                    }
                });     



            }
        }else{
        alert("");
        }
    }else{
    alert("");
    }

});

});
function validateEmail(email) { 
    var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
    return re.test(email);
}

My jQuery Ajax code for login:

$(function(){
 $("#submit-lodin").click(function(){
    var email = $("#login-email").val();
    var password = $("#login-password").val();
    if(email != "" && password != ""){
        $.ajax("resourcs/login.php",{
            type : "POST",
            data : "email="+email+"&password="+password,
            success : function(data){
                if(data === "ok"){
                                        location.reload(true);
                }else{
                    alert(data);
                }
            }
        });
    }
 });
});

My php code for login:

session_start();
include_once '../includes/config.php';


if(isset($_POST['email']) && isset($_POST['password'])&& $_POST['password'] != ""){
    $email = mysql_real_escape_string(strip_tags($_POST['email']),$connect);
    $password = mysql_real_escape_string(strip_tags($_POST['password']),$connect);
    $sql   = "select * from users where u_email = '$email'";
    $query = mysql_query($sql) or die(mysql_error());
    if(mysql_num_rows($query) > 0){
        while ($row  = mysql_fetch_object($query)) {
            $salt    = $row->u_salt;
            $grade = $row->u_grade;
            $id = $row->u_id;
        }

        $n_password  = md5(md5($password).$salt);
        $sql2 = "SELECT *
                FROM users
                WHERE u_email = '$email'
                AND u_password = '$n_password'";
        $query2=  mysql_query($sql2)  or die(mysql_error());
        if (mysql_num_rows($query2) == 1){
                $_SESSION ['login'] = "login";
                $_SESSION ['user_id'] = $id;
                $_SESSION ['email'] = $email;
                $_SESSION ['grade'] = $grade;
                echo"ok";

        }else{
            echo '';
        }

    }  else {
        echo '';
    }

}

My php code for signup is:

session_start();
include_once '../includes/config.php';
    $salt = '';
    for ($i = 0; $i < 3; $i++)
    {
        $salt .= chr(rand(33, 126));
    }
    $email       =  mysql_real_escape_string(strip_tags($_POST["email"]),$connect);
    $first_name  =  mysql_real_escape_string(strip_tags($_POST["firstname"]),$connect);
    $last_name   =  mysql_real_escape_string(strip_tags($_POST["lastname"]),$connect);
    $password    =  mysql_real_escape_string(strip_tags($_POST["password"]),$connect);
    $re_password =  mysql_real_escape_string(strip_tags($_POST["re_password"]),$connect);

    $password_e    =  md5(md5($password).$salt);
    $sql="INSERT INTO `users` (
            `u_firstname` ,
            `u_lastname` ,
            `u_password` ,
            `u_email` ,
            `u_salt`
            )
            VALUES (
            '".$first_name."',"
            . " '".$last_name."',"
            . "'".$password_e."', "
            . "'".$email."',"
            . " '".$salt."'
            )";
    $query=mysql_query($sql) or die(mysql_error());
    if ($query){
        $sql2 ="select * from users where u_email = '$email'";
        $query2=  mysql_query($sql2);
        while ($row = mysql_fetch_object($query2)) {
            $id=$row->u_id;
        }
        $_SESSION['login']="login";
        $_SESSION['user_id']=$id;
        $_SESSION['email']=$email;
        $_SESSION['isadmin']=2;
        echo 'ok';

    }

Finally, my database structure is:

CREATE TABLE IF NOT EXISTS `users` (
`u_id` int(11) NOT NULL,
  `u_firstname` varchar(255) CHARACTER SET utf8 NOT NULL,
  `u_lastname` varchar(255) CHARACTER SET utf8 NOT NULL,
  `u_password` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `u_email` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `u_grade` int(1) NOT NULL DEFAULT '1',
  `u_salt` varchar(255) COLLATE utf8_unicode_ci NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

Are there any security flaws in this code?

\$\endgroup\$
2
\$\begingroup\$

Flow Security

  • You should repeat the email validation in Server side too (js validation could be bypassed)
  • You don't check if the user is already inserted during sign up. There is no unique key in your users table. So I can signup with your admin email and (according with your code) I'm in. If somewhere in your code you don't check the users.id but email only, then you have a problem.
  • You should not login the client after the sign up, expecially if you don't force an email check (validation link). Generally this is a possible backdoor if you have some other bug somewhere (as first point, for example). Another point is to allow bots to entry in restricted area. That's not a great idea.

Structure security

  • use unique key on fields that must be unique (email in this case)

Language security

--

data : "email="+email+"&password="+password,

With a real data will be:

data : "email=my@email.it&password=my&!verystrong!!_#@[**password,

So my very strong password will be truncated at 2nd char. Both login and signup have the same issue. So my password will be valid and never I can suspect this issue. But a bruteforce attack will be more effective (my password will be simply "my")

\$\endgroup\$
  • \$\begingroup\$ " you don't check the users.id but email only" what do you mean \$\endgroup\$ – tom fox Feb 7 '15 at 17:16
  • \$\begingroup\$ If somewhere in your code you trust only the email stored in the session, then this is a possible backdoor. (I'm logged in with an email never checked) \$\endgroup\$ – Luca Rainone Feb 7 '15 at 17:19
  • \$\begingroup\$ so now what i need to secure my code is generate an access token during the login process and save it in session then hash it and save it in database and when login i check if this token after hash it match that in the database 2- is to make unique email and modify the JavaScript code to be use json instead of this method the change all the requests to the database from MySQL to PDO so after all these change my login now is secure 3-send validation messages to validate the email during register \$\endgroup\$ – tom fox Feb 7 '15 at 17:26
  • \$\begingroup\$ @tomfox "secure my code" is too generic :-). There are several levels of "security". I have just report what is not secure in your code already written (as suggested by bob hound). There are other things that could have sense to insert in your script. It depends what level of security do you need. (links of bob's answer are a point to start) \$\endgroup\$ – Luca Rainone Feb 8 '15 at 19:09
2
\$\begingroup\$

To answer your question, no, your login system isn't secure. chumkiu's answer just covers the obvious issues. It'll take more effort than it is worth to actually secure it. You are better off using a pre-built login system that has been hardened against multiple attack vectors. Here are a couple to choose from:

Rolls-Royce: http://barebonescms.com/documentation/sso/

Pinto: http://www.php-login.net/

The former has everything you will ever need in a login system. The latter is bizarrely split off into multiple projects, which makes maintenance for the project maintainers a lot harder, but their software at least aims to be secure and is backed with experience.

\$\endgroup\$
  • \$\begingroup\$ i can't configure the php-login in localhost to send validation messages to the registered email \$\endgroup\$ – tom fox Feb 8 '15 at 19:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.