Jump to content

[SOLVED] really secure login


Recommended Posts

Im building a site for someone who wants it to be really secure and is the only one who is going to be logging into this site. so they dont want a regular login.

 

I'll admit im not a security expert but i wrote a script that ive never been seen used before, and its seems pretty secure to me.

 

First the client requests a login, then the script creates a 16 character random string, and creates a hash of it. The hash is inserted into a mysql Database along with a timestamp. the 16 character string is e-mailed to the client. the client then logs in with e-mailed 16 character pw, the entered pw is hashed and rechecked, if its correct and it has been less then 15 minutes then the user is logged in, else they get an error.

 

I just wanted to get some experts opinions on weather or not this is secure, maybe there is a simple exploit im not seeing? the code is pretty long but i will post it if you want to look at it.

Link to comment
Share on other sites

Here is the actuall generation file

 

<?php
    require_once($_SERVER['DOCUMENT_ROOT']."/framework/config.php");

        $con=frame_mysql_connect($db, $host, $sql_user, $sql_pass);
        $sql="SELECT * FROM `passgen`";
        $q=mysql_query($sql);
        $num= mysql_affected_rows();


    	if($num < 0)
    {
        $sql = "CREATE TABLE `passgen`
    		(`id` INT NOT NULL AUTO_INCREMENT,
    		`password` TINYTEXT NOT NULL,
    	`ipaddress` TINYTEXT NOT NULL,
	    `time` TINYTEXT NOT NULL,
            PRIMARY KEY (`id`)) ENGINE = MyISAM;";
    	    mysql_query($sql) or die("Error Creating Table 'passgen' please check config... ".mysql_error());
    }

        if(isset($_GET['loginid']))
        {
            $sql="SELECT * FROM `passgen` ORDER BY `id` DESC LIMIT 1";
            $q=mysql_query($sql);
            $info=mysql_fetch_array($q);
            $password=md5($_GET['loginid']);
            $time=time();
            $oldtime=$info['time'];
            $chtime=round(($time-$oldtime)/60, 0);
            $ip=$_SERVER['REMOTE_ADDR'];
            $oldip=$info['ipaddress'];
            if($info['password'] == $password)
            {
              if($chtime <= 15 && $ip == $oldip)
              {
                $_SESSION['admin']="TRUE";

                echo "<div id='message'>
                 You have been logged in
                 </div>
                 <meta HTTP-EQUIV='REFRESH' content='0; url=?admin'>
                 ";
              }
              elseif($chtime > 15)
              {
                echo "
                <script type='text/javascript' language='Javascript'>
                alert('Sorry but this login request is too old, this request is $chtime minutes old the limit is 15 minutes');
                </script>
                ";
              }
            }
             else
             {
                  echo "
                 <script type='text/javascript' language='Javascript'>
                  alert('Sorry but your password was wrong');
                 </script>
                  ";
             }
        }


        elseif(isset($_GET['admin']) && isset($_POST['sendpass']))
        {
            include($_SERVER['DOCUMENT_ROOT']."/framework/config.php");//wont recognize variables, unless i include again
            $pass=frame_randstring(16);
            $passhash=md5($pass);
            $date=frame_date();
            $time=time();
            $ip=$_SERVER['REMOTE_ADDR'];
            $subject="Your Admin Login";
            $message="
            This e-mail was sent because there was a request to login from the ip address: $ip
            please use the following link to login, You have fifteen minutes for the time of request ($date)
            http://".$domain."?admin&loginid=".$pass."
            ";
            ini_set('sendmail_from', "Adminlogin@".$domain);

            $sql="INSERT INTO `passgen` (`id`, `password`, `ipaddress`, `time`) VALUES (null, '$passhash', '$ip', '$time')";
            if(mysql_query($sql))
            {

                mail($email, $subject, $message );
                echo "<script type='text/javascript'>alert('Your login information has been mailed to you. please check your email.');</script>";
            }
            else
            {
                echo "There was an error: ".mysql_error();
            }
        }
        elseif($_SESSION['admin']!="TRUE" && isset($_GET['admin']))
        {
        ?><div id='passgen'>
        <form method='post' >
         	<input type='submit' name='sendpass' value='Send Login Request' />
         	</form>
            </div>
         	<?php
        }
        else
        {

        }
    mysql_close($con);
?>

 

here is the config file

<?php
    ini_set(’session.gc_maxlifetime’, 9999999999999); //time before you are logged out automatically
    $domain='www.yourdomain.com';
    $email='email for secure login';

    $db='frame';
    $host='localhost';
    $sql_user='user';
    $sql_pass='password';

  global $db, $host, $sql_user, $sql_pass, $pass;
?>

Link to comment
Share on other sites

I think making the client request a new password each time they want to log in is a bit excessive.  If I were the client I'd probably get sick of that.

 

I would use a self-signed certificate for the site and use mod_rewrite to force all requests through HTTPS.  This allows the client to ensure the site is the actual site and not a spoof.  It also ensures any sniffed traffic will be encrypted and thus protected.

 

If the client will only be accessing this site from a single machine, you might even consider generating a self-signed certificate for the client to identify himself to the web site.  In this way, the web site will only talk to the client.

 

If the client is accessing this site from a specific IP-range, such as 143.238.*.* then you can configure Apache to serve this site only to that IP-range.

Order allow, deny
Allow from 143.238

 

AFAIK, if the client is using a certificate to identify themselves to the site, then they don't even need a login and password.  But you could add one anyways.  In this case I'd use a "regular" login page.  Instead of forcing the client to request a password each time they wish to login, just use a scheduled task to regenerate a new password every morning, two days, week, or some other frequency.  E-mail the new password to the whenever it changes.

 

Just remember that if the client's e-mail is a free e-mail service, then that is an inherent security risk.

 

I also don't like the idea of automatically generated passwords because people have a hard time remembering them.  So ultimately what they do is save it some place in plain-text where anyone can view it if they know what it is.

Link to comment
Share on other sites

Thanks for the quick reply. I'll look into using https but unless im mistaken, dont most hosting companys charge extra if you want to use secure http? so that may not work because the client may not be willing to pay for the certificates.

 

Their site is going to be hosted by some hosting company so i cant really configure thier apache, i think you can reject ip's through th .htaccess though cant you, However i dont want to do that anyways, because i only need to protect certain pages. I will keep that in mind in the future though.

 

I did try and make it easy for them to login by making the login a one click link

 http://".$domain."?admin&loginid=".$pass."

so they dont have to remember the password anyways, also the password expires after fifteen minutes.

 

the reason im doing it this way is because they say they will only be logging in every week or two. and I liked doing it this way because the attacker never gets to know the e-mail address, (one will be setup specifically for recieving these e-mails.)

 

and the client will be using several computers to login and wants to travel alot, so the ip ranges probably wouldnt work either.

Link to comment
Share on other sites

http://".$domain."?admin&loginid=".$pass."

I know the password expires after 15 minutes, but keep in mind URLs are logged in Apache's logs.  So your generated passwords will be logged in plain text files on the server.

Link to comment
Share on other sites

http://".$domain."?admin&loginid=".$pass."

I know the password expires after 15 minutes, but keep in mind URLs are logged in Apache's logs.  So your generated passwords will be logged in plain text files on the server.

That i did not know, thanks for alerting me.

 

do you know of a way to avoid the logging of it? or encrypt it?

Link to comment
Share on other sites

POST data is not logged so you can present the user with a link to a login form and they can type the password; just make sure the form's method is set to 'post' and not 'get'.

 

If you insist on passing the password via GET, then you should encrypt and base64 encode it.  That way anyone viewing the logs will see a base64 encoded string; if they decode it (which they can do easily) they will get an encrypted binary string.  If you pick a good encryption algorithm, then the password will be long expired by the time they can decrypt it.

 

And just to be really clear about what is logged in Apache's logs, anything passed via GET is logged because Apache logs URL's accessed by site visitors (and GET data is part of the URL).  So be careful about passing any sensitive data around via GET.

Link to comment
Share on other sites

To be honest, if I would implement "really secure login", I would just go with public key authentication.

 

Instead of that entire logging issue, can't you just say it expires within fifteen minutes OR when it's first used? Make it a one time password. Delete it, mark it as used or something like that when it has been clicked.

Link to comment
Share on other sites

Instead of that entire logging issue, can't you just say it expires within fifteen minutes OR when it's first used? Make it a one time password. Delete it, mark it as used or something like that when it has been clicked.

 

It shouldn't be logged at all.  Allowing it to be logged allows for potential attackers to see a history of generated passwords.  This could clue an attacker in on the characteristics of your password generator and the type of passwords it produces.  That information could potentially be abused.

 

Call me paranoid...

Link to comment
Share on other sites

Thanks for the quick reply. I'll look into using https but unless im mistaken, dont most hosting companys charge extra if you want to use secure http? so that may not work because the client may not be willing to pay for the certificates.

 

Their site is going to be hosted by some hosting company so i cant really configure thier apache, i think you can reject ip's through th .htaccess though cant you, However i dont want to do that anyways, because i only need to protect certain pages. I will keep that in mind in the future though.

 

No, the support of https is simply via software.  Certainly if they care about security, then the entry of passwords should be done over https.  Do some reading about packet sniffing, to understand more about the reason for SSL.

Link to comment
Share on other sites

Instead of that entire logging issue, can't you just say it expires within fifteen minutes OR when it's first used? Make it a one time password. Delete it, mark it as used or something like that when it has been clicked.

 

It shouldn't be logged at all.  Allowing it to be logged allows for potential attackers to see a history of generated passwords.  This could clue an attacker in on the characteristics of your password generator and the type of passwords it produces.  That information could potentially be abused.

 

Call me paranoid...

 

Maybe I'm just missing the point, but if they're in your file system, I think you've got bigger problems than people analyzing your logs.

 

No, the support of https is simply via software.  Certainly if they care about security, then the entry of passwords should be done over https.  Do some reading about packet sniffing, to understand more about the reason for SSL.

 

Well, for the most part you will have to pay for a certificate. You could make a self-signed one, but then the UA will tell you that your computer will explode and kittens will die should you choose not to heed their warning.

 

To be able to cater to the widest possible amount of users you would also need a dedicated IP address, which would most likely mean an additional cost from the host. SNI is not supported by IE on XP, and it's not supported by IIS at all.

 

Paying for that is definitely worth it if you want "really secure login". You could even get one of those fancy EV certificates.

Link to comment
Share on other sites

Maybe I'm just missing the point, but if they're in your file system, I think you've got bigger problems than people analyzing your logs.

 

People do all sorts of things with log files.  They download them off their server onto their local PC.  They write cron scripts to take the most recent log entries and e-mail them places.  They send log output to development teams for bug elimination.  They post log output to forums, newsgroups, and mailing lists.  Developers sometimes send the log information to project managers or (worse) non-technical managers who then ignorantly forward them around.  Just because someone is reading the log information doesn't mean they've compromised the actual server.

 

Well, for the most part you will have to pay for a certificate. You could make a self-signed one, but then the UA will tell you that your computer will explode and kittens will die should you choose not to heed their warning.

If it's just for one person, then I don't really see it as a problem.  The developer could easily explain what this means to that single user and train them on how to configure the browser to always trust the certificate.  That way you're only told kittens will explode just the one time!  (Unless you switch browsers.)

 

 

Link to comment
Share on other sites

POST data is not logged so you can present the user with a link to a login form and they can type the password; just make sure the form's method is set to 'post' and not 'get'.

 

If you insist on passing the password via GET, then you should encrypt and base64 encode it.  That way anyone viewing the logs will see a base64 encoded string; if they decode it (which they can do easily) they will get an encrypted binary string.  If you pick a good encryption algorithm, then the password will be long expired by the time they can decrypt it.

 

And just to be really clear about what is logged in Apache's logs, anything passed via GET is logged because Apache logs URL's accessed by site visitors (and GET data is part of the URL).  So be careful about passing any sensitive data around via GET.

 

i thought about encrypting the password, but really it wouldnt help if you think about it, The page would have to decrypt it automatically, so the hacker could just submit the encrypted password and use it just like it were the other password. and i will look into creating my own certificate, never really attempted such a thing.

 

I have also updated the code to expire the password after its used as well. Is it possible for them to intercept the e-mail as its sent from the server? Maybe by packet sniffing or something? its my understanding that a man in the middle attack is pretty easy of the internet, especially if its just reading the packets?

 

Also they are using the hosting company www.imhosted.com, which seems pretty proffessional, i would hope they arn't circulating thier logs around. I also modified the password generator to create a password of random characters 14-20 characters long.

Link to comment
Share on other sites

Is it possible for them to intercept the e-mail as its sent from the server? Maybe by packet sniffing or something?

 

Yes, but this is more unlikely.  In this case the e-mail is sent from the hosting server to your client's e-mail server, which is probably not his home machine.  I believe a packet sniffer would have to be installed on either of those machines or on a machine on the same network; this is unlikely to occur if the companies hosting those services know their business.

 

It would be much more likely that the client's machine becomes infected with a virus or trojan that sniffs his internet traffic (and thus intercepts the e-mail message as he's reading it).  But that's always a risk.

Link to comment
Share on other sites

Is it possible for them to intercept the e-mail as its sent from the server? Maybe by packet sniffing or something?

 

Yes, but this is more unlikely.  In this case the e-mail is sent from the hosting server to your client's e-mail server, which is probably not his home machine.  I believe a packet sniffer would have to be installed on either of those machines or on a machine on the same network; this is unlikely to occur if the companies hosting those services know their business.

 

It would be much more likely that the client's machine becomes infected with a virus or trojan that sniffs his internet traffic (and thus intercepts the e-mail message as he's reading it).  But that's always a risk.

 

that is always a risk, i get bothered so much by people asking me to clear thier computer of all kinds of virus's and whatnot. Getting back to the point, there is no major exploits to the system then? as far as small time exploiters and script kitty's go?

Link to comment
Share on other sites

1) User requests a login link

2) Unique token is generated and attached to user's database record.

3) Unique token is mailed (as a link) to the user's e-mail

4) User logs into their e-mail and clicks the link

5) Your site validates the user's token, logs them in, and removes the token from their database record (making the token one-time use).

 

Yes that should be ok.  It's the same type of system most sites use for password recovery.

 

However, I still don't see why you jump through all these hoops.  This is inherently no more secure than if the user just logged into the site using a "regular" login system.  Look at step #4 above: User logs into their e-mail.  So they still have to log into something, regardless of it being your site or their e-mail or whatever, they still have to go through the step of typing in a username and password.

 

Again, if it really needs to be secure, use HTTPS.

 

Consider this, regardless of the login mechanism, once the user is logged in if someone is sniffing network traffic then the sniffer can still hijack the session.  The only way they can't hijack the session is if the packets are encrypted with HTTPS.

Link to comment
Share on other sites

However, I still don't see why you jump through all these hoops.  This is inherently no more secure than if the user just logged into the site using a "regular" login system.

 

Exactly. What if an attacker tries to guess the token by running a bot script against the file that validates the token?

Link to comment
Share on other sites

sorry it took so long to reply,

 

The thing is that the person im making it for insists that they dont want a regular login. They dont know much about computers but they think that since regular login forms are more common its more likely someone will know how to hack it, which is true to a certain extent, I convinced them to get a certificate and go with https as well.

 

Thanks for the advice, i learned a few good things from this thread.

 

----topic solved----

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.