Not signed in (Sign In)
 
Oct 17th 2008
 
I got the following email this morning from Reed Loden, who suggested a patch to make Vanilla cookies more secure:

Mark,

I'm contacting you personally to submit a security patch for Vanilla
that will make it use secure cookies for storing the userid and auth
key of the user. There doesn't seem to be a way for normal users to
file bugs via lussamo.com, nor do I see a security contact address
anywhere, so I figured I'd just e-mail you directly.

The attached patch adds support for both the 'secure' and 'httponly'
parameters of PHP's setcookie(). Note that it has not been tested on an
actual Vanilla instance, so it may contain bugs. However, a similar
patch to what I've attached has been deployed to my internal
Vanilla-based forums, and it works just fine. I generalized this patch
more to meet the minimum PHP version specified on getvanilla.com.

Recent talks at DEFCON and BlackHat have shown how important using
secure cookies are when using an SSL environment to keep your data
secure. I hope your team will take a look at this patch and hopefully
incorporate it or something similar to it in the next release of
Vanilla.

Let me know if you have any questions/comments/etc. concerning the
patch.

~reed

-- Reed Loden - reed [at] reedloden [dot] com
 
Oct 17th 2008
 
Index: People.Class.Authenticator.php
===================================================================
--- People.Class.Authenticator.php (revision 120)
+++ People.Class.Authenticator.php (working copy)
@@ -85,18 +85,28 @@
if (session_id()) session_destroy();

// Destroy the cookies as well
- setcookie($this->Context->Configuration['COOKIE_USER_KEY'],
- ' ',
- time()-3600,
- $this->Context->Configuration['COOKIE_PATH'],
- $this->Context->Configuration['COOKIE_DOMAIN']);
- unset($_COOKIE[$this->Context->Configuration['COOKIE_USER_KEY']]);
- setcookie($this->Context->Configuration['COOKIE_VERIFICATION_KEY'],
- ' ',
- time()-3600,
- $this->Context->Configuration['COOKIE_PATH'],
- $this->Context->Configuration['COOKIE_DOMAIN']);
- unset($_COOKIE[$this->Context->Configuration['COOKIE_VERIFICATION_KEY']]);
+ $cookies = array('COOKIE_USER_KEY', 'COOKIE_VERIFICATION_KEY');
+ $use_ssl = (substr($this->Context->Configuration['BASE_URL'], 0, 5) == "https") ? 1 : 0;
+ foreach($cookies as $cookie) {
+ // PHP 5.2.0 required for HTTP only parameter of setcookie()
+ if (version_compare(PHP_VERSION, '5.2.0', '>=')) {
+ setcookie($this->Context->Configuration['$cookie'],
+ ' ',
+ time()-3600,
+ $this->Context->Configuration['COOKIE_PATH'],
+ $this->Context->Configuration['COOKIE_DOMAIN'],
+ $use_ssl, // Secure connections only
+ 1); // HTTP only
+ } else {
+ setcookie($this->Context->Configuration['$cookie'],
+ ' ',
+ time()-3600,
+ $this->Context->Configuration['COOKIE_PATH'],
+ $this->Context->Configuration['COOKIE_DOMAIN'],
+ $use_ssl); // Secure connections only
+ }
+ unset($_COOKIE[$this->Context->Configuration['$cookie']]);
+ }
return true;
}

@@ -159,16 +169,27 @@

function SetCookieCredentials($CookieUserID, $VerificationKey) {
// Note: 2592000 is 60*60*24*30 or 30 days
- setcookie($this->Context->Configuration['COOKIE_USER_KEY'],
- $CookieUserID,
- time()+2592000,
- $this->Context->Configuration['COOKIE_PATH'],
- $this->Context->Configuration['COOKIE_DOMAIN']);
- setcookie($this->Context->Configuration['COOKIE_VERIFICATION_KEY'],
- $VerificationKey,
- time()+2592000,
- $this->Context->Configuration['COOKIE_PATH'],
- $this->Context->Configuration['COOKIE_DOMAIN']);
+ $cookies = array('COOKIE_USER_KEY' => $CookieUserID, 'COOKIE_VERIFICATION_KEY' => $VerificationKey);
+ $use_ssl = (substr($this->Context->Configuration['BASE_URL'], 0, 5) == "https") ? 1 : 0;
+ foreach($cookies as $cookie => $cookie_value) {
+ // PHP 5.2.0 required for HTTP only parameter of setcookie()
+ if (version_compare(PHP_VERSION, '5.2.0', '>=')) {
+ setcookie($this->Context->Configuration['$cookie'],
+ $cookie_value,
+ time()+2592000,
+ $this->Context->Configuration['COOKIE_PATH'],
+ $this->Context->Configuration['COOKIE_DOMAIN'],
+ $use_ssl, // Secure connections only
+ 1); // HTTP only
+ } else {
+ setcookie($this->Context->Configuration['$cookie'],
+ $cookie_value,
+ time()+2592000,
+ $this->Context->Configuration['COOKIE_PATH'],
+ $this->Context->Configuration['COOKIE_DOMAIN'],
+ $use_ssl); // Secure connections only
+ }
+ }
}

/**
@@ -185,4 +206,4 @@
}

}
-?>
\ No newline at end of file
+?>
 
Oct 17th 2008
 
Index: People.Class.SQLiteAuthenticator.php
===================================================================
--- People.Class.SQLiteAuthenticator.php (revision 120)
+++ People.Class.SQLiteAuthenticator.php (working copy)
@@ -83,18 +83,28 @@
if (session_id()) session_destroy();

// Destroy the cookies as well
- setcookie($this->Context->Configuration['COOKIE_USER_KEY'],
- ' ',
- time()-3600,
- $this->Context->Configuration['COOKIE_PATH'],
- $this->Context->Configuration['COOKIE_DOMAIN']);
- unset($_COOKIE[$this->Context->Configuration['COOKIE_USER_KEY']]);
- setcookie($this->Context->Configuration['COOKIE_VERIFICATION_KEY'],
- ' ',
- time()-3600,
- $this->Context->Configuration['COOKIE_PATH'],
- $this->Context->Configuration['COOKIE_DOMAIN']);

- unset($_COOKIE[$this->Context->Configuration['COOKIE_VERIFICATION_KEY']]);
+ $cookies = array('COOKIE_USER_KEY', 'COOKIE_VERIFICATION_KEY');
+ $use_ssl = (substr($this->Context->Configuration['BASE_URL'], 0, 5) == "https") ? 1 : 0;
+ foreach($cookies as $cookie) {
+ // PHP 5.2.0 required for HTTP only parameter of setcookie()
+ if (version_compare(PHP_VERSION, '5.2.0', '>=')) {
+ setcookie($this->Context->Configuration['$cookie'],
+ ' ',
+ time()-3600,
+ $this->Context->Configuration['COOKIE_PATH'],
+ $this->Context->Configuration['COOKIE_DOMAIN'],
+ $use_ssl, // Secure connections only
+ 1); // HTTP only
+ } else {
+ setcookie($this->Context->Configuration['$cookie'],
+ ' ',
+ time()-3600,
+ $this->Context->Configuration['COOKIE_PATH'],
+ $this->Context->Configuration['COOKIE_DOMAIN'],
+ $use_ssl); // Secure connections only
+ }
+ unset($_COOKIE[$this->Context->Configuration['$cookie']]);
+ }
return true;
}

@@ -174,17 +184,28 @@
}

function SetCookieCredentials($EncryptedUserID, $VerificationKey) {
- // Note: 31104000 is 60*60*24*30*12.. or 1 year
- setcookie($this->Context->Configuration['COOKIE_USER_KEY'],
- $EncryptedUserID,
- time()+31104000,
- $this->Context->Configuration['COOKIE_PATH'],
- $this->Context->Configuration['COOKIE_DOMAIN']);
- setcookie($this->Context->Configuration['COOKIE_VERIFICATION_KEY'],
- $VerificationKey,
- time()+31104000,
- $this->Context->Configuration['COOKIE_PATH'],
- $this->Context->Configuration['COOKIE_DOMAIN']);
+ // Note: 2592000 is 60*60*24*30 or 30 days
+ $cookies = array('COOKIE_USER_KEY' => $EncryptedUserID, 'COOKIE_VERIFICATION_KEY' => $VerificationKey);
+ $use_ssl = (substr($this->Context->Configuration['BASE_URL'], 0, 5) == "https") ? 1 : 0;
+ foreach($cookies as $cookie => $cookie_value) {
+ // PHP 5.2.0 required for HTTP only parameter of setcookie()
+ if (version_compare(PHP_VERSION, '5.2.0', '>=')) {
+ setcookie($this->Context->Configuration['$cookie'],
+ $cookie_value,
+ time()+2592000,
+ $this->Context->Configuration['COOKIE_PATH'],
+ $this->Context->Configuration['COOKIE_DOMAIN'],
+ $use_ssl, // Secure connections only
+ 1); // HTTP only
+ } else {
+ setcookie($this->Context->Configuration['$cookie'],
+ $cookie_value,
+ time()+2592000,
+ $this->Context->Configuration['COOKIE_PATH'],
+ $this->Context->Configuration['COOKIE_DOMAIN'],
+ $use_ssl); // Secure connections only
+ }
+ }
}

function UpdateLastVisit($UserID, $VerificationKey) {
@@ -201,4 +222,4 @@
false); // fail silently
}
}
-?>
\ No newline at end of file
+?>
 
Oct 19th 2008
 
 
1 day ago
 
There should probably be an option to turn HTTPOnly on/off. It can could break extension that need to read the user id cookie on the client side for example.

Issue information

  • 93
  • Dinoboff

    Dinoboff

    Bug Tracker

  • Resolved
  • Low
  • Bug

Vanilla 1.1.5 is a product of Lussumo. More Information: Documentation, Community Support.