benanamen Posted October 23, 2015 Share Posted October 23, 2015 Cuing @Jacques1 in 3...2...1 Quote Link to comment https://forums.phpfreaks.com/topic/298729-forgotten-password/page/2/#findComment-1524170 Share on other sites More sharing options...
scootstah Posted October 23, 2015 Share Posted October 23, 2015 Ah, I believe the reason is so that you get A-Z and not A-F. So in fact you're getting a lot more entropy by hashing it. Quote Link to comment https://forums.phpfreaks.com/topic/298729-forgotten-password/page/2/#findComment-1524176 Share on other sites More sharing options...
Jacques1 Posted October 23, 2015 Share Posted October 23, 2015 The tokens are equivalent to passwords, because anybody who knows them can take over the account. That's why you need to protect them in the same way that you protect passwords. An SQL injection attack that reveals all current tokens would be a disaster. Even worse: Since anybody can request a token, it's even possible to target specific accounts (e. g. admins). Quote Link to comment https://forums.phpfreaks.com/topic/298729-forgotten-password/page/2/#findComment-1524180 Share on other sites More sharing options...
scootstah Posted October 23, 2015 Share Posted October 23, 2015 (edited) Even worse: Since anybody can request a token, it's even possible to target specific accounts (e. g. admins). Hmm, excellent point. That would be nasty. EDIT: Although, that's kind of not solving anything. If you have an SQL injection vulnerability, couldn't you just change the column value for an admin's password or token? Or, promote yourself to admin level? Edited October 23, 2015 by scootstah Quote Link to comment https://forums.phpfreaks.com/topic/298729-forgotten-password/page/2/#findComment-1524181 Share on other sites More sharing options...
Jacques1 Posted October 23, 2015 Share Posted October 23, 2015 If there's a vulnerability specifically within an “UPDATE users SET ...” query, then the entire authentication and authorization system is worthless. But this is rare. Most attacks happen by finding any vulnerable query and using that to fetch secret data from arbitrary tables. Quote Link to comment https://forums.phpfreaks.com/topic/298729-forgotten-password/page/2/#findComment-1524187 Share on other sites More sharing options...
scootstah Posted October 23, 2015 Share Posted October 23, 2015 Fair enough. Quote Link to comment https://forums.phpfreaks.com/topic/298729-forgotten-password/page/2/#findComment-1524191 Share on other sites More sharing options...
Tom8001 Posted October 24, 2015 Author Share Posted October 24, 2015 I dont understand how i can get rid of the vulnerability in the url you can change the username and token and take over accounts with my current code i don't understand how i can prevent this Quote Link to comment https://forums.phpfreaks.com/topic/298729-forgotten-password/page/2/#findComment-1524218 Share on other sites More sharing options...
Jacques1 Posted October 24, 2015 Share Posted October 24, 2015 Did you read my explanation in #22? I'd suggest that you forget about your current code for now and start with two fresh PHP scripts. The first script generates a token, sends it by e-mail and stores the hash in the database. Try it. Quote Link to comment https://forums.phpfreaks.com/topic/298729-forgotten-password/page/2/#findComment-1524219 Share on other sites More sharing options...
scootstah Posted October 24, 2015 Share Posted October 24, 2015 I dont understand how i can get rid of the vulnerability in the url you can change the username and token and take over accounts with my current code i don't understand how i can prevent this You need to SELECT the user first, to make sure the information given is valid. Then you can perform the update. Quote Link to comment https://forums.phpfreaks.com/topic/298729-forgotten-password/page/2/#findComment-1524221 Share on other sites More sharing options...
benanamen Posted March 10, 2016 Share Posted March 10, 2016 (edited) You're not supposed to store the plaintext token, but you do store its SHA-256 hash. To check if a token is valid, you hash it and search that hash in the database. Generating a token: <?php // generate 16 random bytes $rawToken = mcrypt_create_iv(16, MCRYPT_DEV_URANDOM); // encode the random bytes and send the result to the user $encodedToken = bin2hex($rawToken); // hash the random bytes and store this hash in the database $tokenHash = hash('sha256', $rawToken); Looking up a token: <?php $encodedToken = $_GET['token']; // decode the token and hash it $rawToken = hex2bin($encodedToken); $tokenHash = hash('sha256', $rawToken); // now look up $tokenHash Edit* Never mind. I see the mistake. It is in the comment what to send to user I just got around to trying this and it seems to not make sense. You generate (encode) the token hash and then store that in the DB. I assume that is also what is emailed to user. Now it appears on lookup you decode the emailed token first, then compare to DB token, but this wont match since what was sent to user is exact match for what is stored in db. Am I missing something? Edited March 10, 2016 by benanamen Quote Link to comment https://forums.phpfreaks.com/topic/298729-forgotten-password/page/2/#findComment-1531875 Share on other sites More sharing options...
Jacques1 Posted March 10, 2016 Share Posted March 10, 2016 I send the original token (in some human-readable format), not the hash. The hash is used to protect the token from being stolen from the database, just like a password hash (after all, the token is equivalent to a password). When the user submits the human-readable token, I transform it back into the original binary form, calculate the hash and check if that hash is stored in the database. Quote Link to comment https://forums.phpfreaks.com/topic/298729-forgotten-password/page/2/#findComment-1531876 Share on other sites More sharing options...
benanamen Posted March 10, 2016 Share Posted March 10, 2016 Thanks. Works beautifully! I had just missed the comment about what part to send to the user. Quote Link to comment https://forums.phpfreaks.com/topic/298729-forgotten-password/page/2/#findComment-1531877 Share on other sites More sharing options...
benanamen Posted March 10, 2016 Share Posted March 10, 2016 It is appearing that on the return trip to transforming the users token to match the binary version in the DB that an additional record identifier such as user_id is required to get the correct row to compare to. Since the users token is not the same as the DB token you cant do a SELECT dbtoken WHERE user token = DB token. Am I correct in this? Quote Link to comment https://forums.phpfreaks.com/topic/298729-forgotten-password/page/2/#findComment-1531883 Share on other sites More sharing options...
Jacques1 Posted March 10, 2016 Share Posted March 10, 2016 No. The (hexadecimal) hash of the submitted token is exactly the same as the stored hash. It's also effectively unique, so no further identifiers are required. The workflow is like this: generating: raw_token := secure_rand(16) mail(hex_encode(raw_token)) database_store(hash(raw_token)) validating: raw_token := hex_decode(url_param("token")) database_search(hash(raw_token)) Quote Link to comment https://forums.phpfreaks.com/topic/298729-forgotten-password/page/2/#findComment-1531885 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.