blackenedheart Posted May 3, 2013 Share Posted May 3, 2013 (edited) Hi, Maybe someone here can give me an opinion. So i'm trying to implement your standard "key and lock" system for a login for my website. Instead of using a username and password, I wanted to use a grid of pictures, which when clicked in the correct sequence, would permit access. Nothing too revolutionary here or particularly high security, but I thought it would be fun. So, I have 25 different images on my server, and when I click through the links, nothing happens. Basically, my code doesn't work, and now i'm depressed. Any thoughts as to why? <html> <body> <?php class fortress { function lockandkey ($checkforkeys){ $gate1= "[url=http://www.mywebsite.com/01.png]http://www.mywebsite.com/01.png[/url]"; $gate2= "[url=http://www.mywebsite.com/02.png]http://www.mywebsite.com/02.png[/url]"; $gate3= "[url=http://www.mywebsite.com/03.png]http://www.mywebsite.com/03.png[/url]"; $gate4= "[url=http://www.mywebsite.com/04.png]http://www.mywebsite.com/04.png[/url]"; $gate5= "[url=http://www.mywebsite.com/05.png]http://www.mywebsite.com/05.png[/url]"; $gate6= "[url=http://www.mywebsite.com/06.png]http://www.mywebsite.com/06.png[/url]"; $gate7= "[url=http://www.mywebsite.com/07.png]http://www.mywebsite.com/07.png[/url]"; if ($gate1 == $gate1) {($key1=1);} else if ($gate1 != $gate1) {($key1=0);} if ($gate2 == $gate2) {($key2=1);} else if ($gate2 != $gate2) {($key2=0);} if ($gate3 == $gate3) {($key3=1);} else if ($gate3 != $gate3) {($key3=0);} if ($gate4 == $gate4) {($key4=1);} else if ($gate4 != $gate4) {($key4=0);} if ($gate5 == $gate5) {($key5=1);} else if ($gate5 != $gate5) {($key5=0);} if ($gate6 == $gate6) {($key6=1);} else if ($gate6 != $gate6) {($key6=0);} if ($gate7 == $gate7) {($key7=1);} else if ($gate7 != $gate7) {($key7=0);} $accessgranted=7; if ($key1 + $key2 + $key3 + $key4 + $key5 + $key6 + $key7 == $accessgranted) {($fortressopen);} else if ($key1 + $key2 + $key3 + $key4 + $key5 + $key6 + $key7 != $accessgranted) {($fortressclosed);} $fortressopen = "<a href= [url=http://www.zebradatasolutions.com/main.php]http://www.mywebsite.com/main.php[/url] </a>"; $fortressclosed = "<a href= [url=http://www.zebradatasolutions.com/loginfailed.php]http://www.mywebsite.com/loginfailed.php[/url] </a>"; } } ?> <body bgcolor="#000000" text="#FFFFFF" link="#FF0000"> <p style="text-align: center; font-family: 'Courier New', Courier, monospace; font-size: 24px; color: #FFF;">GATE ONE</p> <div align="center"> <table width="48%" height="358" border="0" cellpadding="10" cellspacing="10"> <tr bgcolor="#333333" style="text-align: center"> <td><a href="gate2.php <?php echo new fortress;?>"><img src="01.png" width="100" height="100" /></a></td> <td><a href="gate2.php <?php echo new fortress;?>"><img src="02.png" width="100" height="100" /></a></td> <td><a href="gate2.php <?php echo new fortress;?>"><img src="03.png" width="100" height="100" /></a></td> <td><a href="gate2.php <?php echo new fortress;?>"><img src="04.png" width="100" height="100" /></a></td> <td><a href="gate2.php <?php echo new fortress;?>"><img src="05.png" width="100" height="100" /></a></td> </tr> <tr bgcolor="#333333" style="text-align: center"> <td><a href="gate2.php <?php echo new fortress;?>"><img src="06.png" width="100" height="100" /></a></td> <td><a href="gate2.php <?php echo new fortress;?>"><img src="07.png" width="100" height="100" /></a></td> <td><a href="gate2.php <?php echo new fortress;?>"><img src="08.png" width="100" height="100" /></a></td> <td><a href="gate2.php <?php echo new fortress;?>"><img src="09.png" width="100" height="100" /></a></td> <td><a href="gate2.php <?php echo new fortress;?>"><img src="10.png" width="100" height="100" /></a></td> </tr> <tr bgcolor="#333333" style="text-align: center"> <td><a href="gate2.php <?php echo new fortress;?>"><img src="11.png" width="100" height="100" /></a></td> <td><a href="gate2.php <?php echo new fortress;?>"><img src="12.png" width="100" height="100" /></a></td> <td><a href="gate2.php <?php echo new fortress;?>"><img src="13.png" width="100" height="100" /></a></td> <td><a href="gate2.php <?php echo new fortress;?>"><img src="14.png" width="100" height="100" /></a></td> <td><a href="gate2.php <?php echo new fortress;?>"><img src="15.png" width="100" height="100" /></a></td> </tr> <tr bgcolor="#333333" style="text-align: center"> <td><a href="gate2.php <?php echo new fortress;?>"><img src="16.png" width="100" height="100" /></a></td> <td><a href="gate2.php <?php echo new fortress;?>"><img src="17.png" width="100" height="100" /></a></td> <td><a href="gate2.php <?php echo new fortress;?>"><img src="18.png" width="100" height="100" /></a></td> <td><a href="gate2.php <?php echo new fortress;?>"><img src="19.png" width="100" height="100" /></a></td> <td><a href="gate2.php <?php echo new fortress;?>"><img src="20.png" width="100" height="100" /></a></td> </tr> <tr bgcolor="#333333" style="text-align: center"> <td><a href="gate2.php <?php echo new fortress;?>"><img src="21.png" width="100" height="100" /></a></td> <td><a href="gate2.php <?php echo new fortress;?>"><img src="22.png" width="100" height="100" /></a></td> <td><a href="gate2.php <?php echo new fortress;?>"><img src="23.png" width="100" height="100" /></a></td> <td><a href="gate2.php <?php echo new fortress;?>"><img src="24.png" width="100" height="100" /></a></td> <td><a href="gate2.php <?php echo new fortress;?>"><img src="25.png" width="100" height="100" /></a></td> </tr> </table> </div> </body> </html> It's important to note that each page has the same code, but the only thing that changes is the link to the next "gate." Cheers Edited May 4, 2013 by ignace Added code tags Quote Link to comment Share on other sites More sharing options...
captbeagle Posted May 3, 2013 Share Posted May 3, 2013 (edited) if ($gate1 == $gate1) What else would it ever equal? Edit for more observations: {($fortressopen);} else if ($key1 + $key2 + $key3 + $key4 + $key5 + $key6 + $key7 != $accessgranted) {($fortressclosed);} $fortressopen = "<a href= http://www.mywebsite.com/main.php </a>"; $fortressclosed = "<a href= http://www.mywebsite...loginfailed.php </a>"; You defined $fortressopen and $fortressclosed after using them. That's surely not going to help things along. Edited May 3, 2013 by captbeagle Quote Link to comment Share on other sites More sharing options...
blackenedheart Posted May 3, 2013 Author Share Posted May 3, 2013 Hmm. These are good observations. I didn't realize it matters where you put a variable inside a class. Can you tell me why? Also, am I calling the "fortress" class correctly? Quote Link to comment Share on other sites More sharing options...
blackenedheart Posted May 3, 2013 Author Share Posted May 3, 2013 Also, my idea was that the "correct" key has a value of 1, and the "incorrect" keys have a value of 0. So, if the sequence is correct, that will equal 7. Nonetheless, I am having trouble passing these values from page to page. Maybe it's something very basic here, or this could be much more complicated. Anyone have any ideas? Quote Link to comment Share on other sites More sharing options...
captbeagle Posted May 3, 2013 Share Posted May 3, 2013 Hmm. These are good observations. I didn't realize it matters where you put a variable inside a class. Can you tell me why? You don't have to initialize variables in PHP, but if you don't, they'll have some default value depending on the context in which they're used (eg, integers and floats default to 0). In your case, you're trying to output a link - it's simply going to output an empty string since you haven't otherwise initialized it yet. Take a look at http://www.php.net/manual/en/language.variables.basics.php Quote Link to comment Share on other sites More sharing options...
blackenedheart Posted May 3, 2013 Author Share Posted May 3, 2013 Could someone also be so kind to tell me if I am calling the links correctly. I know it's not working because I have it set up live on my website. The links are working, but the PHP is basically doing nothing. Quote Link to comment Share on other sites More sharing options...
blackenedheart Posted May 3, 2013 Author Share Posted May 3, 2013 Is there a way to test the PHP's output? Almost like NSLog in xCode? Quote Link to comment Share on other sites More sharing options...
jcbones Posted May 3, 2013 Share Posted May 3, 2013 My take is that you should be looking at arrays: <?php session_start(); //editable variables: $correctLockSequence = array(1,2,3,4,5,6); $lockURI = 'http://www.mywebsite.com/main.php'; $lockOpenedURI = 'http://www.mywebsite.com/passed.php'; $lockBarricadedURI = 'http://www.mywebsite.com/loginfailed.php'; //dynamic variable knowledge base: $numberOfLocks = count($correctLockSequence); //starting processing: //get the lock number sent in the URL: $currentLockNumber = (isset($_GET['lock'])) ? $_GET['lock'] : 0; //Lets us know that the lock rotation is NOT complete. $rotationComplete = false; //set our current selected lock in the session array: $_SESSION['selectedLocks'][] = $currentLockNumber; //if our number of locks selected is equal to the number of locks needed: if(count($_SESSION['selectedLocks']) == $numberOfLocks) { //then our rotation is complete. $rotationComplete = true; //but our page is locked: $pageLocked = array(); //so we look at each index in the array: foreach($_SESSION['selectedLocks'] as $key => $lock) { //if each index does equal the corresponding index in the correctly sequenced array: (unlock the page, else lock it down)! if($correctLockSequence[$key] == $lock) { $pageLocked[] =0; } else { $pageLocked[] = 1; } } //redirects: //if the rotation is not complete, go get another lock code: if($rotationComplete == false) { header('Location: ' . $lockURI); exit(); } elseif(in_array(1,$pageLocked)) { //else if rotation is complete, and some keys did not match, then barricade the store: header('Location: ' . $lockBarricadedURI); exit(); } else { //else everything matched up, and you can let them in. header('Location: ' . $lockOpenedURI); exit(); } Quote Link to comment Share on other sites More sharing options...
blackenedheart Posted May 3, 2013 Author Share Posted May 3, 2013 Dear Bones, Could you elaborate as to why you believe this would work better? I was hoping my implementation was at least workable in some form. Do you believe it is not workable at all? If so, what problems do you see? Kind Regards... Quote Link to comment Share on other sites More sharing options...
blackenedheart Posted May 4, 2013 Author Share Posted May 4, 2013 Also, you definitely made me aware of something here. This idea cannot work without a session in play because those variable values cannot be passed to each successive page without a session. This is most likely why it is not working. Again, bones, can you elaborate a bit more if I can do something with the code I wrote? I just have a hard time using someone else's code if you don't mind sir. Again, Kind Regards Quote Link to comment Share on other sites More sharing options...
jcbones Posted May 4, 2013 Share Posted May 4, 2013 I just think the logic flows better with arrays. Right now you are trying to compare if all of the values end up the same a the access key: ($key1 + $key2 + $key3 + $key4 + $key5 + $key6 + $key7 != $accessgranted) This will work NO MATTER HOW the keys are chosen. The sequence could be reversed and they would still get the access. Matter of fact, there could be 1,000's of different sequences that you could come up with that would equal the pass code in that one line of code. With arrays, you can be sure that the pass code was clicked in the correct order. Quote Link to comment Share on other sites More sharing options...
blackenedheart Posted May 5, 2013 Author Share Posted May 5, 2013 I appreciate the insight here. I am trying to pear this code down to be as short as it can possibly be. I have implemented session variables and it still does not work. With PHP, it seems there is no way to log every step so that I can know what is going wrong. If you can't identify where things are going wrong, how can you ever fix the problem? Does anyone know a way I can see the logic flow? Quote Link to comment Share on other sites More sharing options...
blackenedheart Posted May 5, 2013 Author Share Posted May 5, 2013 The suggestions offered here are great, but this problem is nowhere near solved. Quote Link to comment Share on other sites More sharing options...
ignace Posted May 5, 2013 Share Posted May 5, 2013 (edited) session_start(); // our sequence container if (!isset($_SESSION['sequence']) || (isset($_GET['sequence']) && $_GET['sequence'] === 'clear')) { $_SESSION['sequence'] = array(); } // user passed a code, store the code in the sequence container if (isset($_GET['code'])) { $_SESSION['sequence'][] = (int) $_GET['code']; } // user asked us to verify what is currently in the sequence container (omit if empty) if (isset($_GET['verify']) && !empty($_SESSION['sequence'])) { $db = mysqli_connect('host', 'user', 'pass', 'db') or die('Database has left the building!'); if ($stmt = mysqli_prepare('SELECT username FROM users WHERE password_sequence = ?')) { $sequence = implode(',', $_SESSION['sequence']); $stmt->bind_param('s', sha1($sequence)); $stmt->execute(); $stmt->bind_result($username); $stmt->fetch(); echo 'Hello, ', $username; exit; } } // our numbers $numbers = range(1, 10); // corresponding images $images = array_combine( $numbers, array_map(function($i) { return sprintf('%02d.jpg', $i); }, $numbers) ); // display images foreach ($images as $number => $image) { printf( '<a href="?code=%d"><img src="%s" alt="" width="100" height="100"></a>', $number, $image ); } // display verify link echo '<a href="?verify=1">verify</a>';A user can create a sequence as long as he likes (just like a password, the longer the better). When he presses verify the currently stored codes are converted to a string and separated by a , so that a sequence of 1,2 and 12 do not match the same thing. The sequence is then encrypted with sha1 (the same rules as with a password still apply here). For this to work you need a UNIQUE constraint on the password_sequence. No 2 people can have the same sequence. This of course imposes a problem because a hacker would now be able to simply enter simple sequences to login to someone's account (without having to know their username or e-mail or any other info). So to put the security at the same level as a normal login you need to provide a username field. Edited May 5, 2013 by ignace Quote Link to comment Share on other sites More sharing options...
blackenedheart Posted May 5, 2013 Author Share Posted May 5, 2013 Hello Again Guys, First off I want to say thanks to everyone who has been kind enough to chime in. I wanted to post a link to my website to show how I am implementing this. The idea of a "sequence container" is something new and foreign to me. ignace... could you describe this piece of code a bit more in detail? // our numbers$numbers = range(1, 10);// corresponding images$images = array_combine($numbers,array_map(function($i) { return sprintf('%02d.jpg', $i); }, $numbers));// display imagesforeach ($images as $number => $image) {printf('<a href="?code=%d"><img src="%s" alt="" width="100" height="100"></a>', $number, $image);}// display verify linkecho '<a href="?verify=1">verify</a>'; www.zebradatasolutions.com/gate1.php Right now it's just a loop because it doesn't work, but with time maybe... Quote Link to comment Share on other sites More sharing options...
ignace Posted May 5, 2013 Share Posted May 5, 2013 (edited) You don't need multiple gate*.php files. One file will do. Every time you click on an image it sends you to the same page with a different ?code=X, it stores these codes and when the user clicks verify it tries to find a match in the database containing the entered codes. Suppose my sequence is the images clicked in this order: 1, 7, 13, 19, 25 (diagonal) then I would send the following requests: gate1.php?code=1 gate1.php?code=7 gate1.php?code=13 gate1.php?code=19 gate1.php?code=25 I have entered my sequence and therefor I send the last request: gate1.php?verify=1 The database is queried a match is (hopefully) found and I am logged in. Edited May 5, 2013 by ignace Quote Link to comment Share on other sites More sharing options...
blackenedheart Posted May 5, 2013 Author Share Posted May 5, 2013 So if I am understanding this correctly, we are using the array_map function to keep a record of the array in a session. The arrays correspond to an image in a MYSQL database, and from there, if the users pattern of images lines up with the array sequence in the database, for example: array (image 1, image 7, image 9, image 17, image 20, image 21, image 25) Then we have access. This makes sense. I don't have the skill to implement it (not yet anyway), but it makes sense. Quote Link to comment Share on other sites More sharing options...
blackenedheart Posted May 5, 2013 Author Share Posted May 5, 2013 DEAR IGNACE, I agree that it would be okay to have one page... let's get into this a bit more since I have your attention. It is divided into "gates" for a specific reason (in my mind anyway.) My hope is to develop a cryptographic login system based on images. The odds of breaking such a system, if coded correctly, are 1 in 95 trillion or more. For example, if there are 10 "gates" and 25 symbols, choosing all ten correctly in order would equal 25 to the power of 10: 1 in 95,367,431,640,625 ...thats 95 trillion 367 billion... And I believe that hashing algorithms and AES 256 are possibly becoming outdated. This is just an idea, but it's more like a puzzle. I am assuming that someone will jump in here and tell me why this won't work, but I have coded some fairly complex algorithms in C and C++. The problem is I am not too experienced with PHP. Soooo... hoping that I don't get laughed off this forum, this is mostly an idea. I was hoping to not involve MYSQL and maybe even not use sessions but that may be unavoidable. Also, maybe someone can answer the $$$ million dollar question here. If the images are dynamic, let's just say they move with every reload, and they are coming from a database, does that decrease my security? How long would a brute force attack take to crack something like this? How would a brute force attack even recognize images? This is why I wanted to stay away from using a database. I was hoping that the "keys" could be stored in the code itself, which may seem strange, but I may want to use this on a microcchip in the future. Quote Link to comment Share on other sites More sharing options...
blackenedheart Posted May 5, 2013 Author Share Posted May 5, 2013 And again, it is my understanding that PHP is a good choice for something like this, because PHP is always on the server, and technically invisible from the browser. I am wondering if that is even 100% correct at this point. Quote Link to comment Share on other sites More sharing options...
ignace Posted May 5, 2013 Share Posted May 5, 2013 No. He is my code again more thoroughly documented. /** * We start the session here to store our steps between requests. */ session_start(); /** * If the 'sequence' does not yet exist, create it. Or clear it if ?sequence=1 is passed. */ if (!isset($_SESSION['sequence']) || (isset($_GET['sequence']) && $_GET['sequence'] === 'clear')) { $_SESSION['sequence'] = array(); } /** * When a user clicks an image it will contain ?code=X we check here if this is the case */ if (isset($_GET['code'])) { /** * It is. Store the code in our session so that it persists between requests. */ $_SESSION['sequence'][] = (int) $_GET['code']; } /** * User appears to be finished and asks us to find the user with this sequence. * Just to be sure we check if 'sequence' infact contains codes. */ if (isset($_GET['verify']) && !empty($_SESSION['sequence'])) { $db = mysqli_connect('host', 'user', 'pass', 'db') or die('Database has left the building!'); if ($stmt = mysqli_prepare('SELECT username FROM users WHERE password_sequence = ?')) { $sequence = implode(',', $_SESSION['sequence']); $stmt->bind_param('s', sha1($sequence)); $stmt->execute(); $stmt->bind_result($username); $stmt->fetch(); echo 'Hello, ', $username; exit; } } /** * Creates an array with numbers from 1..10 */ $numbers = range(1, 10); /** * Create an array with key=>value pairs where key is the number and the value is the image. * * In other words the result will look like: * array ( 1 => '01.jpg', .. ) */ $images = array_combine( $numbers, array_map(function($i) { return sprintf('%02d.jpg', $i); }, $numbers) ); /** * Display the images to the user * * This outputs: * <a href="?code=1"><img src="01.jpg" alt="" width="100" height="100"></a> */ foreach ($images as $number => $image) { printf( '<a href="?code=%d"><img src="%s" alt="" width="100" height="100"></a>', $number, $image ); } // display verify link echo '<a href="?verify=1">verify</a>'; Quote Link to comment Share on other sites More sharing options...
ignace Posted May 5, 2013 Share Posted May 5, 2013 (edited) It is divided into "gates" for a specific reason (in my mind anyway.) My hope is to develop a cryptographic login system based on images. The odds of breaking such a system, if coded correctly, are 1 in 95 trillion or more. 1. The hacker knows each password has 10 symbols (no way to stop after 5 for example), so it is a limited finite set. So 95,367,431,640,625 is highly exaggerated. 2. User's can't go beyond 10 gates, so "passwords" can't be made stronger. Which is not a problem in my above code, a user can select one code or 1000. 3. Your system has the same weaknesses a normal password has suppose someone selects the first image of each gate. 4. Because you require no username all "passwords" have to be unique otherwise 2 people can no longer login. Because "passwords" have to be unique it's possible for someone to unwillingly hack someone else's account. Just like you have collisions with regular passwords. And that is just out of the top of my hat. If the images are dynamic, let's just say they move with every reload, and they are coming from a database, does that decrease my security? No, what this does is make it harder for anyone to login (they have to remember the exact symbols in the exact order) while a hacker just simply uses a script to send the sequence. How long would a brute force attack take to crack something like this? How would a brute force attack even recognize images? It doesn't need to recognize images you send the user from gate1 to gate2 with an identifier. The script would simply query each gate with a new set. Edited May 5, 2013 by ignace Quote Link to comment Share on other sites More sharing options...
blackenedheart Posted May 5, 2013 Author Share Posted May 5, 2013 Fair enough. I was thinking this could be an "extra" measure of security... meaning that once someone is logged in, this puzzle would show up. I think it is a cool idea because... USERNAMES and PASSWORDS get compromised all the time. I am not sure as to the validity of your claim that my numbers are exaggerated. Powerball players know there are 7 numbers, and 50 to chose from, but very few ever win. I believe the odds are as good as I am saying they are. I could always be mistaken though. I don't want you to think I am back tracking. I am going to try to work with your suggestions for sure. Quote Link to comment Share on other sites More sharing options...
ignace Posted May 5, 2013 Share Posted May 5, 2013 (edited) Powerball players know there are 7 numbers, and 50 to chose from, but very few ever win. I think the lottery is a bad reference, I don't know how poweball lottery works but if it's lottery like we have it, every week somebody wins and sometimes multiple people guess the same numbers. So there is a high collision rate. Not preferable for something that should beat AES256. I believe the odds are as good as I am saying they are. It doesn't matter how good or bad the odds are, there is still a thing called usability. Show a person the 25 images and let them select 1 each time, tell them to remember it, note their choices down. After 10 symbols are selected ask them to repeat the symbols in the correct order. The odds of someone repeating the symbols in the correct order is as slim as an attacker trying to brute-force their way in. Not to mention that there are already ways to bypass the "flaws" of md5 or sha1 or the like. Which is why most now use PBKDF2 (designed to be slow so that decrypting takes years not mere minutes/seconds like hashing algorithms) and people are encouraged to use phrases (easier to remember, longer then passwords, and harder to crack) instead of passwords. Which achieves the goal without getting in the way of users. Edited May 5, 2013 by ignace Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.