如何保护没有SSL的身份验证Cookie [英] How to secure an authentication cookie without SSL

查看:184
本文介绍了如何保护没有SSL的身份验证Cookie的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在创建一个使用两个会话的登录系统(对于不允许使用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 generate 126 in hex format you need to understand that there is Browser Cookie Limits so i suggest you reduce it to 256

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆