observances

web * programming * the higher end

Virtual Keyboard Login – Version wicked.evil [avoid screenshots]

Mon, 28th Jul, '08

Ok, so we had virtual keyboards for some time on login pages being served worldwide. In fact so long that we had this. So we have virtual keyboards here again, and some smartness, some.

Earlier in this blog we covered some crypt way to send passwords to the server from the browser, and thanks to the response, i feel motivated enough. Now we are onto making a virtual keyboard, and yeah, this is a proof-of-concept and you are free to take it to the moon alongwith you.

We are just going to blank out all buttons just before the user is going to click on one. Basically do a backgroundColor = fontColor on all buttons to make it difficult what is written on the buttons on mouseover and restore on mouseout. Normally a user figures out which button to click on and then positions the mouse on the button and clicks, so if the button is showing what is written on it, definitely some proof-of-concept program can take a snapshot of the web page to figure out which button was clicked on. We are just going to wipe the face of the button off. For some more fun, we are going to randomize the order of buttons at will by calling randomizekeys() and supplying the order of the keys as an argument. And yeah, the styling class is closely tied to the javascript functions, so keep that in mind while playing with styles or the javascript. So here we go[look at the onload handler in the body tag] …

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
    "http://www.w3.org/TR/html4/loose.dtd">
<html>

<head>
    <meta http-equiv="content-type" content="text/html; charset=iso-8859-1">

    <title>Virtual Login Panel</title>
    <style>
    .loginnumkey {
        background:#000;
        color:#FFF;
        padding:5px 0 5px 0;
        min-width:40px;
        font-size:16px;
        font-family:tahoma;
        margin:1px;
    }
    </style>
    <script>
    function randomizekeys(assigncode, numkeysclass)
    {
        var j = 0;
        var els = document.getElementsByTagName('input');
        var elsLen = els.length;
        var pattern = new RegExp('\\b'+numkeysclass+'\\b');
        for (var i = 0; i < elsLen; i++)
        {
            if ( pattern.test(els[i].className) && j < assigncode.length)
            {
                els[i].value = assigncode[j];
                j++;
            }
        }
    }
    function keysoff(numkeysclass)
    {
        var i = 0;
        var els = document.getElementsByTagName('input');
        var elsLen = els.length;
        var pattern = new RegExp('\\b'+numkeysclass+'\\b');
        for (i = 0; i < elsLen; i++)
        {
            if ( pattern.test(els[i].className) )
            {
                els[i].style.backgroundColor = '#FFF';
            }
        }
    }
    function keyson(numkeysclass)
    {
        var i = 0;
        var els = document.getElementsByTagName('input');
        var elsLen = els.length;
        var pattern = new RegExp('\\b'+numkeysclass+'\\b');
        for (i = 0; i < elsLen; i++)
        {
            if ( pattern.test(els[i].className) )
            {
                els[i].style.backgroundColor = '#000';
            }
        }
    }
    function clicknumkey(inputid, inputvalue)
    {
        document.getElementById(inputid).value =
		document.getElementById(inputid).value + inputvalue;
    }
    </script>
</head>

<body onload="javascript:randomizekeys('1095673824', 'loginnumkey');">

    <input type='text' id='passwordbox'>
    <br><br>
    <input type='button' id='lkey1' value='1' class='loginnumkey'
    onclick="javascript:clicknumkey('passwordbox', this.value);"
    onmouseover="javascript:keysoff('loginnumkey');"
    onmouseout="javascript:keyson('loginnumkey');">

    <input type='button' id='lkey2' value='2' class='loginnumkey'
    onclick="javascript:clicknumkey('passwordbox', this.value);"
    onmouseover="javascript:keysoff('loginnumkey');"
    onmouseout="javascript:keyson('loginnumkey');">

    <input type='button' id='lkey3' value='3' class='loginnumkey'
    onclick="javascript:clicknumkey('passwordbox', this.value);"
    onmouseover="javascript:keysoff('loginnumkey');"
    onmouseout="javascript:keyson('loginnumkey');">

    <br>

    <input type='button' id='lkey4' value='4' class='loginnumkey'
    onclick="javascript:clicknumkey('passwordbox', this.value);"
    onmouseover="javascript:keysoff('loginnumkey');"
    onmouseout="javascript:keyson('loginnumkey');">

    <input type='button' id='lkey5' value='5' class='loginnumkey'
    onclick="javascript:clicknumkey('passwordbox', this.value);"
    onmouseover="javascript:keysoff('loginnumkey');"
    onmouseout="javascript:keyson('loginnumkey');">

    <input type='button' id='lkey6' value='6' class='loginnumkey'
    onclick="javascript:clicknumkey('passwordbox', this.value);"
    onmouseover="javascript:keysoff('loginnumkey');"
    onmouseout="javascript:keyson('loginnumkey');">

    <br>

    <input type='button' id='lkey7' value='7' class='loginnumkey'
    onclick="javascript:clicknumkey('passwordbox', this.value);"
    onmouseover="javascript:keysoff('loginnumkey');"
    onmouseout="javascript:keyson('loginnumkey');">

    <input type='button' id='lkey8' value='8' class='loginnumkey'
    onclick="javascript:clicknumkey('passwordbox', this.value);"
    onmouseover="javascript:keysoff('loginnumkey');"
    onmouseout="javascript:keyson('loginnumkey');">

    <input type='button' id='lkey9' value='9' class='loginnumkey'
    onclick="javascript:clicknumkey('passwordbox', this.value);"
    onmouseover="javascript:keysoff('loginnumkey');"
    onmouseout="javascript:keyson('loginnumkey');">

    <br>

    <input type='button' id='lkey0' value='0' class='loginnumkey'
    onclick="javascript:clicknumkey('passwordbox', this.value);"
    onmouseover="javascript:keysoff('loginnumkey');"
    onmouseout="javascript:keyson('loginnumkey');">

    <input type='button' id='lkeyclear' value='reset' class='loginnumkey'
    onclick="javascript:document.getElementById('passwordbox').value='';"
    onmouseover="javascript:keysoff('loginnumkey');"
    onmouseout="javascript:keyson('loginnumkey');">

</body>

</html>

This may not work in IE, I mean this code snippet. If you want to make it work, just fiddle with i, j declarations in the function randomizekeys(), like moving them around in the function.

Posted by krahulg
Filed in Experiment, This Works
Tags: Javascript, login, secure, virtual keyboard
Leave a Comment »

Preparing a secure login form with PHP & JavaScript

Wed, 26th Dec, '07


We have had encryption, we have had SSLs, … well we also had digitally signed certificates, but where’s the hack?? How can you cook up a secure login form that does the following:

[1] doesn’t send the login information in clear-text

[2] in case somebody is sniffing the line, he/she shouldn’t be able to login with the sniffed information

So, with the above information in hand, here is what we do, and how we do.

You need:

[1] http://www.webtoolkit.info/javascript-md5.html [javascript implementation of MD5]

[2] Two php functions. runquery($query) , which will run a query supplied as string & getcol($query) will get the column asked for in a select statement.

Now, create a table, if you don’t already have, to store user information. What we do want to be stored is the login timestamp.

create table user(
loginid varchar(200),
password varchar(200),
lastLoginTS bigint
);

Now your login.php file should look like this:

<html>
<head>
<title>Secure Login Form</title>
<script type=”text/javascript” src=”md5.js”></script>
</head>
<body>
<form action=”dologin.php” method=”post” onsubmit=”javascript:document.getElementById(‘phash’).value = MD5(document.getElementById(‘password’).value + document.getElementById(‘hts’).value); document.getElementById(‘password’).value = ” ;”>
LoginID: <input type=”text” name=”loginid”><br>
Password: <input type=”password” name=”password” id=”password”><br>
<?php
$TS = time(); //the current timestamp
echo “<input type=’hidden’ value=’”.$TS.”‘ name=’hts’ id=’hts’><br>”;
?>
<input type=’hidden’ name=’phash’ id=’phash’ value=”>
<input type=”submit” value=”send”>
</form>
</body>
</html>

This file assumes in the line “<script type=”text/javascript” src=”md5.js”></script>” that you have a file named md5.js in the same directory as login.php, and the javascript file should have a function named MD5(). So make sure this is the case. Next up is dologin.php:

<?php

$loginid = $_REQUEST['loginid'];
$phash = $_REQUEST['phash'];
$hts = $_REQUEST['hts'];
$password = getcolumn(“select password from user where loginid=’$loginid’;”);
$lastLoginTS = getcolumn(“select lastLoginTS from user where loginid=’$loginid’;”);

if(strlen($loginid) > 0 && strlen($phash) > 0 && $phash == md5($password.$hts) && $hts > $lastLoginTS)
{
runquery(“update user set lastLoginTS=’”.time().”‘ where loginid=’$loginid’;”);
echo “done”;
}
else
echo “failed”;
?>

That’s it. So now what is the deal here. This is your regular login form except that the password is hashed with a timestamp value sent in a hidden form field named ‘hts’. The hashing is done in the event handler for the Javascript onsubmit event, and the password field is cleared as well, to prevent it from being sent in the clear.

The server receives the loginid, timestamp and the hashed value from the client. Retrieve from your database the original password for the loginid specified and calculate another hash at the server with the help of the retrieved original password and the timestamp sent by the client. If the user typed the password correctly, the hashes will match.

This method of course, sort of, encrypts the password and hence prevents the password from being sent in clear, should anybody be sniffing the lines. But should anybody be really sniffing the lines, he/she can just store the values and send them again and again to validate him/herself at the server posing as the valid user. To prevent that, there is another check at the server just before validating. The timestamp sent by the client should be always greater than the last login timestamp stored in the database for that user. Since the last login timestamp is only updated on a successful login, as soon as a valid user logs in, the last login timestamp for the user is updated in the database, and as a result, the sniffed information is rendered stale. The hash now needs to be calculated again using a fresh timestamp and a password which only the user and server know.

I hope this suffices for most of you out there.

UPDATE : This is a proof of concept. The system described here lacks certain things which are very obvious and shouldn’t omit them just because I haven’t mentioned them here to make it simple to grasp. Foremost[thanks William], don’t store passwords in cleartext on the server. Try looking up “hashing password with salts” for that.

Posted by krahulg
Filed in Experiment, This Works
Tags: hash, Javascript, login, md5, php, secure, security, sniff
15 Comments »

  • Kumar Rahul's Facebook profile
    View kumar rahul ghosh's profile on LinkedIn

  • Blog Hotness

    • 14,325 cool/hot people have been here

  • Add to Technorati Favorites
    add to del.icio.us Add to Blinkslist add to furl Digg it add to ma.gnolia Stumble It! add to simpy seed the vine TailRank


  • Pressed Just Now

    • Web 2.0: The birth of Social Media and You
    • Why are all the tectonic faults vertical??
    • Virtual Keyboard Login – Version wicked.evil [avoid screenshots]
    • Social Networking Websites – Revenue Models
    • Animate this …
    • Walking the HTML DOM tree in PHP
    • Search Friendly URLs or No-Question-Marks-Or-Equals URLs
    • Add content dynamically as you reach end of page with AJAX
    • Preparing a secure login form with PHP & JavaScript
    • How long do your users stay on a page??
  • Top Posts

    • Walking the HTML DOM tree in PHP
    • Social Networking Websites - Revenue Models
    • Preparing a secure login form with PHP & JavaScript
    • Search Friendly URLs or No-Question-Marks-Or-Equals URLs
    • Virtual Keyboard Login - Version wicked.evil [avoid screenshots]
    • How long do your users stay on a page??
    • Add content dynamically as you reach end of page with AJAX
  • You said ...

    MiKu on Social Networking Websites …
    tw on Social Networking Websites …
    How to Get Six Pack … on Social Networking Websites …
    Thorix » Siche… on Preparing a secure login form …
    Stefan Wagner on Walking the HTML DOM tree in…
    Stefan Wagner on Walking the HTML DOM tree in…
    Stefan Wagner on Walking the HTML DOM tree in…
    krahulg on Walking the HTML DOM tree in…
    Melvin J. on Walking the HTML DOM tree in…
    krahulg on Automatic Javascript Bug Repor…
  • My Blog-O-Sphere

    • Big Money List
    • Chris Shiflett’s Blog
    • Position Is Everything
  • tags

    adsense ajax animate apache automatic browser Document Object Model DOM dynamic earthquakes error friendly urls hash htaccess Javascript login MATLAB md5 micro-payments mod_rewrite monetizing monitoring page optimization php prototype question reporting revenue models revenue sharing scriptaculous scroll secure security seismic activity seo settimeout sniff social networking tectonic faults tectonic plates timer url rewriting virtual keyboard web 1.0 web 2.0
  • Events I am attending


Theme: Simpla by Phu. Blog at WordPress.com.