Challenge Response login problems!

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
rtc4lyfee
Forum Newbie
Posts: 8
Joined: Wed Jun 27, 2007 5:53 pm

Challenge Response login problems!

Post by rtc4lyfee »

feyd | Please use

Code: Select all

,

Code: Select all

and [syntax="..."] tags where appropriate when posting code. Your post has been edited to reflect how we'd like it posted. Please read: :arrow: [url=http://forums.devnetwork.net/viewtopic.php?t=21171]Posting Code in the Forums[/url] to learn how to do it too.[/color]


I'm in the process of merging challenge/response into my login auth.

Code for the login page:

Code: Select all

<?php
/*
    Start the PHP Session
*/
session_start();

require_once('db.php');
include('functions.php');


/*
    We will use feyd's SHA256 PHP implementation to support SHA256 (does not require mcrypt enabled).
    Depending on where you get your version ensure no echo() statements are left uncommented out
*/
require_once('sha256.inc.php');

/*
    Generate a Challenge hash using feyd's class
*/
$challenge = SHA256::hash(uniqid(mt_rand(), true));

/*
    All new Challenges are given a 5 minute lifetime. Delete anything older then the current time() value
*/
mysql_query("delete from challenge_record where sess_id = '" . session_id() . "' or timestamp < " . time()) or die("Invalid query: " . mysql_error());

/*
    Store our generated Challenge to the database - and give 5 minutes of life before being invalidated
*/
mysql_query("insert into challenge_record (sess_id, challenge, timestamp) values ('". session_id() ."', '". $challenge ."', ". (time() + 360) .")") or die("Invalid query: " . mysql_error());

/*
    HTML for login form now follows
*/
?>
<?php if(isset($error)){ echo $error;}?>
<!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" />
<!--
    Include a javascript implementation of the SHA256 algorithim
    Download from: http://www.mad-teaparty.com/Chrstph/sha256.html
-->
<title>Untitled Document</title>
<script language="javascript" src="sha256.js" type="text/javascript"></script>
<!--
    Include a javascript function to manipulate our form data, i.e. to generate a Response string, delete
    password and challenge prior to allowing submission. Rem: we don't want to send a plain text password!
-->
<script language="javascript" type="text/javascript">
<!--
  function doChallengeResponse() {
    str = document.myForm.username.value.toLowerCase() + ":" +
    sha256_digest(document.myForm.password.value) + ":" +
    document.myForm.challenge.value;
    document.myForm.password.value = "";
    document.myForm.challenge.value = "";
    document.myForm.response.value = sha256_digest(str);
    return false;
  }
// -->
</script>
<script type="text/javascript">
function SendTo(id){
        //shortening form elements
        var myForm      = document.getElementById('myForm');
        var image_id = document.getElementById('imageid');
        
        image_id.value = id;

        myForm.submit();            

}
		</script>
</head>
<body>
<div id="container">
  <div id="top">
    <h1>Please complete the form bellow</h1>
  </div>
  <div id="leftSide">
  <fieldset>
  <legend>Login details</legend>
  We have added another layer of security to protect your accounts.
  <div style="clear:both;"></div>
  To login:
  <div style="clear:both;"></div>
  1: Enter your username and password
  <div style="clear:both;"></div>
  2: Enter a name for one of the pictures on the right.
  <div style="clear:both;"></div>
  3: Click on that picture.
  <div style="clear:both;"></div>
  Each time you login after the first time, you will need to enter the same picture name and click on the same picture.</font> <br />
  <div style="clear:both;"></div>
  <?php if(isset($error)){ echo $error;}?>
  <!--
        Our form has 5 fields - but only 3 are submitted. The doChallengeResponse() javascript function
        will generate a Response and set it as the value of 'response'. The same function will also unset
        the value of the 'password' field, and 'challenge' field which we DO NOT want sent!

        The javacript function is called when the user submits the form - see the onsubmit tag...
    -->
  <form name="myForm" id="myForm" action="dologin.php" method="post" class="form" onsubmit="doChallengeResponse()">
    <label for="username">Username</label>
    <div class="div_texbox">
      <input name="username" type="text" class="username" id="username" size="32"  value="username" />
    </div>
    <label for="password">Password</label>
    <div class="div_texbox">
      <input name="password" type="password" class="password" id="password" size="32"   value="password" />
    </div>
    <label for="imagename">Image Name</label>
    <div class="div_texbox">
      <input name="imagename" type="text" class="imagename" id="imagename" value="Image Name" />
    </div>
    <div class="clear"></div>
    </fieldset>
    <hr size="1" />
    </div>
    <div id="rightSide">
    <p>Confused? Submit your login by clicking on your picture below.</p>
    <p id="flagbar">
      <!--begin submit login images-->
      <input type='hidden' name='imageid' id='imageid' value='00'/>
      <input type='image' name="Login" src='images/securitypics/01.jpg' name='imageid' id='01' onClick="SendTo(01)" value="Login" />
      <input type='image' name="Login" src='images/securitypics/02.jpg' name='imageid' id='01' onClick="SendTo(02)" value="Login" />
      <input type='image' name="Login" src='images/securitypics/03.jpg' name='imageid' id='03' onClick="SendTo(03)" value="Login" />
      <input type='image' name="Login" src='images/securitypics/04.jpg' name='imageid' id='04' onClick="SendTo(04)" value="Login" />
      <input type='image' name="Login" src='images/securitypics/05.jpg' name='imageid' id='05' onClick="SendTo(05)" value="Login" />
      <input type='image' name="Login" src='images/securitypics/06.jpg' name='imageid' id='06' onClick="SendTo(06)" value="Login" />
      <input type='image' name="Login" src='images/securitypics/07.jpg' name='imageid' id='07' onClick="SendTo(07)" value="Login" />
      <input type='image' name="Login" src='images/securitypics/08.jpg' name='imageid' id='08' onClick="SendTo(08)" value="Login" />
      <input type='image' name="Login" src='images/securitypics/09.jpg' name='imageid' id='09' onClick="SendTo(09)" value="Login" />
      <input type='image' name="Login" src='images/securitypics/10.jpg' name='imageid' id='10' onClick="SendTo(10)" value="Login" />
      <input type='image' name="Login" src='images/securitypics/11.jpg' name='imageid' id='11' onClick="SendTo(11)" value="Login" />
      <input type='image' name="Login" src='images/securitypics/12.jpg' name='imageid' id='12' onClick="SendTo(12)" value="Login" />
      <input type='image' name="Login" src='images/securitypics/13.jpg' name='imageid' id='13' onClick="SendTo(13)" value="Login" />
      <input type='image' name="Login" src='images/securitypics/14.jpg' name='imageid' id='14' onClick="SendTo(14)" value="Login" />
      <input type='image' name="Login" src='images/securitypics/15.jpg' name='imageid' id='15' onClick="SendTo(15)" value="Login" />
      <input type='image' name="Login" src='images/securitypics/16.jpg' name='imageid' id='16' onClick="SendTo(16)" value="Login" />
      <input type='image' name="Login" src='images/securitypics/17.jpg' name='imageid' id='17' onClick="SendTo(17)" value="Login" />
      <input type='image' name="Login" src='images/securitypics/18.jpg' name='imageid' id='18' onClick="SendTo(18)" value="Login" />
      <input type='image' name="Login" src='images/securitypics/19.jpg' name='imageid' id='19' onClick="SendTo(19)" value="Login" />
      <input type='image' name="Login" src='images/securitypics/20.jpg' name='imageid' id='20' onClick="SendTo(20)" value="Login" />
      <input type='image' name="Login" src='images/securitypics/21.jpg' name='imageid' id='21' onClick="SendTo(21)" value="Login" />
      <input type='image' name="Login" src='images/securitypics/22.jpg' name='imageid' id='22' onClick="SendTo(22)" value="Login" />
      <input type='image' name="Login" src='images/securitypics/23.jpg' name='imageid' id='23' onClick="SendTo(23)" value="Login" />
      <input type='image' name="Login" src='images/securitypics/24.jpg' name='imageid' id='24' onClick="SendTo(24)" value="Login" />
      <input type='image' name="Login" src='images/securitypics/25.jpg' name='imageid' id='25' onClick="SendTo(25)" value="Login" />
      <!--end submit login images-->
      <!--
        Insert the Challenge value from the server with a small PHP echo()
    -->
      <input type="hidden" name="challenge" id="challenge" value="<?php echo($challenge); ?>" />
      <!--
        Our 'response' field will be filled by the javascript function once the Response string is generated
    -->
      <input type="hidden" name="response" id="response" value="" />
  </form>
  </p>
</div>
<div class="clear"></div>
</div>
</body>
</html>

Code for dologin.php page (page the data is submitted to):

Code: Select all

<?php
session_start(); 


require_once('db.php');
include('functions.php');

/*
    Get our server stored Challenge from the database
    Rem: ensure we only select Challenges which have not timed out!
*/
$result = mysql_query("select challenge from challenge_record where sess_id = '" . session_id() . "' and timestamp > " . time()) or die("Invalid query: " . mysql_error());
/*
    Check we got a matching result
    If this is not so, its most likely the Challenge has timed out - user waited too long to submit form
*/
if(mysql_num_rows($result) == 0)
{
    header('Location: timedout.php'); //simple file with a die() statement - see the download pack
}

/*
    Fetch the array containing the Challenge
*/
$c_array = mysql_fetch_assoc($result);

/*
    Execute a query to select User data based on the submitted username imaageid and imagename
    Normally we would use some escaping here - its omitted for clarity (is magic_quotes dependent)
*/
	 if(isset($_POST['Login']))
$result = mysql_query('SELECT ID, Username, imageid, imagename, Active FROM users WHERE Username = "'.mysql_real_escape_string($_POST['username']).'" AND imageid = "'.mysql_real_escape_string($_POST['imageid']).'" AND imagename = "'.mysql_real_escape_string($_POST['imagename']).'"');

if(mysql_num_rows($result) == 1)
			{
				$row = mysql_fetch_assoc($result);
				if($row['Active'] == 1)
				{
					session_start();
				 
/*
    Fetch the User data into an associative array
*/
$user = mysql_fetch_assoc($result);

/*
    We're back to worship at the Altar of Feyd ;)
    Include feyd's PHP sha256 implementation
*/
require_once('sha256.inc.php');

$response_string = strtolower($user['username']).':'.$user['password'].':'.$c_array['challenge'];
$expected_response = SHA256::hash($response_string);

/*
    Compare the actual client Response hash against our expected Response hash
    1. If they match, we will authenticate the user
*/	
	
if($_POST['response'] == $expected_response)
{
					session_start();
					$_SESSION['user_id'] = $row['ID'];
					$_SESSION['logged_in'] = FALSE;
					header("Location: members.php");
					
					echo " hey!! ";
}
 else {  echo $_SESSION['logged_in']; } }
else {  echo $_SESSION['logged_in']; } }
SQL Data

Code: Select all

-- --------------------------------------------------------

-- 
-- Table structure for table `challenge_record`
-- 

CREATE TABLE `challenge_record` (
  `challenge` varchar(64) NOT NULL default '',
  `sess_id` varchar(64) NOT NULL default '',
  `timestamp` int(11) NOT NULL default '0'
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

-- 
-- Dumping data for table `challenge_record`
-- 

INSERT INTO `challenge_record` VALUES ('7e3e1c205b0ed458193e1588b4230fc42413cc44db07cbc9eaf3865b00f07597', '3d816e9135e207ec98aca6042a708b6a', 1183004324);

-- --------------------------------------------------------

-- 
-- Table structure for table `users`
-- 

CREATE TABLE `users` (
  `ID` int(11) NOT NULL auto_increment,
  `Username` varchar(255) NOT NULL default '',
  `Password` varchar(255) NOT NULL default '',
  `imageid` int(2) NOT NULL default '0',
  `imagename` varchar(55) default NULL,
  `Temp_pass` varchar(55) default NULL,
  `Temp_pass_active` tinyint(1) NOT NULL default '0',
  `Email` varchar(255) NOT NULL default '',
  `Active` int(11) NOT NULL default '0',
  `Level_access` int(11) NOT NULL default '2',
  `Random_key` varchar(32) default NULL,
  PRIMARY KEY  (`ID`),
  UNIQUE KEY `Username` (`Username`),
  UNIQUE KEY `Email` (`Email`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;

-- 
-- Dumping data for table `users`
-- 

INSERT INTO `users` VALUES (1, 'ryan', '10c7ccc7a4f0aff03c915c485565b9da', 1, 'bus', NULL, 0, 'rtchaffin@gmail.com', 1, 2, 'sficDXl7ih4JE6Eazo7RM1wWAI35JhX2');
INSERT INTO `users` VALUES (2, 'devnetwork', '5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8', 1, 'bus', NULL, 0, 'rtchaffin@tmail.com', 1, 2, NULL);
I already know I have errors all over the place. If I could get anyone to go through all of them because I'm at a loss right now. You can view a version online already to see what the code does http://www.fhhsbandhome.com/authalpha/login.php The page submits to dologin and it just sits there... If anyone could take this code and fix it that would be great!

Please help guys/gals. I really need this. Read my post below this for a little bit more info.

feyd | Please use

Code: Select all

,

Code: Select all

and [syntax="..."] tags where appropriate when posting code. Your post has been edited to reflect how we'd like it posted. Please read: :arrow: [url=http://forums.devnetwork.net/viewtopic.php?t=21171]Posting Code in the Forums[/url] to learn how to do it too.[/color]
Last edited by rtc4lyfee on Thu Jun 28, 2007 12:22 am, edited 3 times in total.
rtc4lyfee
Forum Newbie
Posts: 8
Joined: Wed Jun 27, 2007 5:53 pm

Post by rtc4lyfee »

Before I took the challenge of trying to add this challenge/response system, the auth looked like this.


This code worked 100% and did what it was supposse to do. Now that I've tried adding the challenge response, and spliting the data between login.php and dologin.php, and isn't doing what it's suppose to any more.


Host=www.fhhsbandhome.com
User-Agent=Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.8.1.4) Gecko/20070515 Firefox/2.0.0.4
Accept=text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language=en-gb,en;q=0.5
Accept-Encoding=gzip,deflate
Accept-Charset=ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive=300
Connection=keep-alive
Referer=http://www.fhhsbandhome.com/authalpha/login.php
Cookie=pageCount=3; PHPSESSID=3d816e9135e207ec98aca6042a708b6a
Content-Type=application/x-www-form-urlencoded
Content-Length=166
POSTDATA=username=ryan&password=&imagename=bus&imageid=1&Login.x=30&Login.y=17&Login=Login&challenge=&response=c4b446dc595240ef7cbbdfd8dae0595153760c2bdc488e82401f6eb5de36482c

This is the headers on submit. As you can see it's passing the username, password (it passes the password as blank as it merges the password into the response), imagename, imageid (it's passing 1 because I clicked on the first image, the bus) and Login=Login correctly (the Submit). It's also erasing the challenge like it's supposed to and passing response instead. The post data seems to be right it's just the PHP backend!!! Please help me guys/gals. I really need this working correctly.
Last edited by rtc4lyfee on Thu Jun 28, 2007 1:14 am, edited 2 times in total.
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

$_POST['password'] != '' will fail.
rtc4lyfee
Forum Newbie
Posts: 8
Joined: Wed Jun 27, 2007 5:53 pm

Post by rtc4lyfee »

Eh it's obvious that you know what your talking about and that my mind isn't apparently able to cope with your higher intelligence :-/ lol anyways to get to the point I have no idea how that fixes my problem ;) The code that I needed help with is above that, the code in the second post was me showing my login.php page before I added all of the response crap to the script. I'm still looking for help. Short and sweet it great, but I just don't get what to do with what you said lol.
User avatar
s.dot
Tranquility In Moderation
Posts: 5001
Joined: Sun Feb 06, 2005 7:18 pm
Location: Indiana

Post by s.dot »

With the challenge/response login system, your password will not be sent. Therefore, this line:

Code: Select all

if($_POST['username']!='' && $_POST['password']!='' && $_POST['imagename']!='')
Will evalute to false, because $_POST['password'] is not being sent, therefor it's == '', and in your line you're requiring a password to be sent by using !=.
rtc4lyfee
Forum Newbie
Posts: 8
Joined: Wed Jun 27, 2007 5:53 pm

Post by rtc4lyfee »

ok i've taken that out, please review the code in the top post so we can figure out why this isn't working. you can go to the link in top post to see a live demo.
User avatar
s.dot
Tranquility In Moderation
Posts: 5001
Joined: Sun Feb 06, 2005 7:18 pm
Location: Indiana

Post by s.dot »

turn error reporting on, and print_r($_POST) on your processing page
you can see what's going on ;)
rtc4lyfee
Forum Newbie
Posts: 8
Joined: Wed Jun 27, 2007 5:53 pm

Post by rtc4lyfee »

http://www.fhhsbandhome.com/authalpha/dologin.php

Everything is being posted correctly. I just don't know how to code the PHP backend correctly for the challenge response system.. that is what I need help with.

Code: Select all

<?php
error_reporting(E_ALL);

session_start(); 


require_once('db.php');
include('functions.php');

/*
    Get our server stored Challenge from the database
    Rem: ensure we only select Challenges which have not timed out!
*/
$result = mysql_query("select challenge from challenge_record where sess_id = '" . session_id() . "' and timestamp > " . time()) or die("Invalid query: " . mysql_error());
/*
    Check we got a matching result
    If this is not so, its most likely the Challenge has timed out - user waited too long to submit form
*/
if(mysql_num_rows($result) == 0)
{
    header('Location: timedout.php'); //simple file with a die() statement - see the download pack
}

/*
    Fetch the array containing the Challenge
*/
$c_array = mysql_fetch_assoc($result);

/*
    Execute a query to select User data based on the submitted username imaageid and imagename
    Normally we would use some escaping here - its omitted for clarity (is magic_quotes dependent)
*/
	 if(isset($_POST['Login']))
$result = mysql_query('SELECT ID, Username, imageid, imagename, Active FROM users WHERE Username = "'.mysql_real_escape_string($_POST['username']).'" AND imageid = "'.mysql_real_escape_string($_POST['imageid']).'" AND imagename = "'.mysql_real_escape_string($_POST['imagename']).'"');

if(mysql_num_rows($result) == 1)
			{
				$row = mysql_fetch_assoc($result);
				if($row['Active'] == 1)
				{
				 
/*
    Fetch the User data into an associative array
*/
$user = mysql_fetch_assoc($result);

/*
    We're back to worship at the Altar of Feyd 
    Include feyd's PHP sha256 implementation
*/
require_once('sha256.inc.php');

$response_string = strtolower($user['username']).':'.$user['password'].':'.$c_array['challenge'];
$expected_response = SHA256::hash($response_string);

/*
    Compare the actual client Response hash against our expected Response hash
    1. If they match, we will authenticate the user
*/	
	
if($_POST['response'] == $expected_response)
{
					session_start();
					$_SESSION['user_id'] = $row['ID'];
					$_SESSION['logged_in'] = TRUE;
					header("Location: members.php");
					
					
}
 else {  } }
else {  } } 

 print_r($_POST);
The SQL data for the challenge response stuff is in the second post.
Post Reply