如何保护没有SSL的身份验证Cookie [英] How to secure an authentication cookie without SSL
问题描述
我正在创建一个使用两个会话的登录系统(对于不允许使用Cookie的用户(同意 )。我使用的网站)或查找现有的安全身份验证服务。 @ircmaxell最近提醒我 Schneier's Law :
@Baba:惊喜是安全的敌人。应该是秘密的唯一的东西是私钥。记住施尼尔定律:任何人都可以发明他们自己不能打破的加密方案。我的答案是基于尝试和真正的加密原则。
我认为你也应该接受这个建议。
I am in the process of creating a login system which uses both sessions (for those who disallow the use of cookies (to agree with the cookie law.. I am using the site http://www.cookielaw.org/the-cookie-law.aspx as a reference)
Now, I have this system for my cookie authentication
function GenerateString(){
$length = mt_rand(0,25);
$characters = '0123456789abcdefghijklmnopqrstuvwxyz';
$string = '';
for ($p = 0; $p < $length; $p++) {
$string .= $characters[mt_rand(5, strlen($characters) -1)];
}
return $string;
}
$RandomString = GenerateString();
$CookieAuth = $DB->prepare("INSERT INTO cookieauth (Username,RandomString) VALUES (?,?)");
$CookieAuth->bind_param('ss',$_POST['Username'],$RandomString);
$CookieAuth->execute(); // Insert the Authentication Methods into the database
$CookieAuth->close(); // Allow another query/statement
$GetInsertID = $DB->prepare("SELECT ID FROM CookieAuth WHERE RandomString=?");
$GetInsertID->bind_param('s',$Randomstring);
$GetInsertID->execute();
$GetInsertID->bind_result($RowID);
$GetInsertID->fetch();
$GetInsertID->close();
setcookie("Auth[ID]",$RowID);
setcookie("Auth[UName],$_POST['Username']);
setcookie("Auth[RandomString]",$RandomString);
Then to process the cookie:
if(isset($_COOKIE['Auth'])){
$Authenticate = $DB->prepare("SELECT Username,RandomString FROM cookieauth WHERE ID=?");
$Authenticate->bind_param('i',$_COOKIE['Auth']['ID']);
$Authenticate->execute();
$Authenticate->bind_result($RowUsername,$RowString);
$Authenticate->fetch();
$Authenticate->close();
if ($_Cookie['Auth']['UName'] == $RowUsername){
if ($_COOKIE['Auth']['RandomString'] == $RowString){
header("Location: LoggedIn.php");
}else{
die("Possible Cookie Manipulation, Autologin Cannot Continue");
}
}else{
die("Possible Cookie Manupulation, Autologin Cannot Continue!");
}
My overall objective is to provide an auto login feature by using cookies. As people should know they are essentially stored on the hard drive as plain text.. So If i include a randomly generated string which will be changed on further processing each time (then updating the cookie to match the database) is this a reasonably secure way to achieve the task? I mean, I understand that this is not 100% secure due to some users might attempt to manipulate the random string, so I could resort to a salt, random key then use hash_hmac
to sha512 the salt+key and save that as the cookie...
My overall question, is the chunks I have provided a semi-secure method to process automatic logins via cookies and can minimize the possibility of some bad guys manipulating the keys to achieve the required data?
Introduction
Why do you want to authenticate cookie when that is exactly what sessions are going ? If you want to change the ID
you can easily achieve that with session_regenerate_id
as @MarcB has pointed.
My Assumptions
I want to assume i did not understand the question clearly and probably this is what you want to achieve
- Store Values to Cookie
- Know if such values have been modified
You solved it already
I could resort to a salt, random key then use hash_hmac to sha512 the salt+key and save that as the cookie...
That is exactly the the solution but you need to note that
- Session Can Sill be hijacked
- PHP has better ways of generating random strings
- Imagine the overhead having to updated your mysql table every time for something sessions can easily do for you
- using
hash_hmac 512
would generate126
in hex format you need to understand that there is Browser Cookie Limits so i suggest you reduce it to256
Your Solution Modified
If we are going to use your solution we need some little modification
session_start();
// Strong private key stored Securly stored
// Used SESSION For demo
$privateKey = isset($_SESSION['key']) ? $_SESSION['key'] : mcrypt_create_iv(128, MCRYPT_DEV_URANDOM);
$my = new SignedCookie($privateKey);
$my->setCookie("test", "hello world", time() + 3600);
echo $my->getCookie("test");
Output
hello world
But the Data was stored like this :
This just uses hash_hmac
to sign and verify your values and also uses a random variable to make sure the bad guys are not able to build table of possible values because really they don't have to break the hash .. the can just study it can also use a valid one previously used eg.
10 Cookies = AAAA
1 Cookie = BBBB
He can login with valid session and changed cookies from BBBB
to AAAA
so even if you re not storing to database always include a random argument
You can also still remove the cookies like this :
$my->setCookie("test", null, time() - 3600);
Simple Class Used
class SignedCookie {
private $prifix = '$x$';
private $privateKey;
function __construct($privateKey) {
$this->privateKey = $privateKey;
}
function setCookie($name, $value, $expire, $path = null, $domain = null, $secure = null, $httponly = null) {
$value = $value === null ? $value : $this->hash($value, mcrypt_create_iv(2, MCRYPT_DEV_URANDOM));
return setcookie($name, $value, $expire, $path, $domain, $secure, $httponly);
}
function getCookie($name, $ignore = false) {
if (! isset($_COOKIE[$name]) || empty($_COOKIE[$name]))
return null; // does not exist
if ($ignore === false) {
if (substr($_COOKIE[$name], 0, 3) !== $this->prifix)
return - 1; // modified
$data = pack("H*", substr($_COOKIE[$name], 3)); // Unpack hex
$value = substr($data, 32, - 2); // Get Value
$rand = substr($data, - 2, 2); // Get Random prifix
if ($this->hash($value, $rand) !== $_COOKIE[$name])
return - 1; // modified
return $value;
}
return $_COOKIE[$name];
}
function hash($value, $suffix) {
// Added random suffix to help the hash keep changing
return $this->prifix . bin2hex(hash_hmac('sha256', $value . $suffix, $this->privateKey, true) . $value . $suffix);
}
}
Conclusion
You are not a security expert Just Use so just use SSL (SSL also has its issues but far better) or Look for an existing secure authentication service. @ircmaxell reminded me of Schneier's Law recently :
@Baba: "surprise" is the enemy of security. The ONLY thing that should be secret is the private key. Remember Schneier's Law: Anyone can invent an encryption scheme that they themselves can't break. My answer is based on tried and true cryptographic principles.
well i think you should take to that advice too.
这篇关于如何保护没有SSL的身份验证Cookie的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!