Skip to content

Commit ad31319

Browse files
committed
working on cookie fingerprinting.
1 parent 9fae4dc commit ad31319

File tree

4 files changed

+45
-7
lines changed

4 files changed

+45
-7
lines changed

laravel/cookie.php

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,14 @@ public static function has($name)
4444
*/
4545
public static function get($name, $default = null)
4646
{
47-
if (isset(static::$jar[$name])) return static::$jar[$name]['value'];
47+
if (isset(static::$jar[$name])) return static::parse(static::$jar[$name]['value']);
4848

49-
return array_get(Request::foundation()->cookies->all(), $name, $default);
49+
if ( ! is_null($value = Request::foundation()->cookies->get($name)))
50+
{
51+
return static::parse($value);
52+
}
53+
54+
return value($default);
5055
}
5156

5257
/**
@@ -75,6 +80,8 @@ public static function put($name, $value, $expiration = 0, $path = '/', $domain
7580
$expiration = time() + ($expiration * 60);
7681
}
7782

83+
$value = sha1($value.Config::get('application.key')).'+'.$value;
84+
7885
// If the secure option is set to true, yet the request is not over HTTPS
7986
// we'll throw an exception to let the developer know that they are
8087
// attempting to send a secure cookie over the insecure HTTP.
@@ -120,4 +127,35 @@ public static function forget($name, $path = '/', $domain = null, $secure = fals
120127
return static::put($name, null, -2000, $path, $domain, $secure);
121128
}
122129

130+
/**
131+
* Parse a hash fingerprinted cookie value.
132+
*
133+
* @param string $value
134+
* @return string
135+
*/
136+
protected static function parse($value)
137+
{
138+
$segments = explode('+', $value);
139+
140+
// First we will make sure the cookie actually has enough segments to even
141+
// be valid as being set by the application. If it does not we will go
142+
// ahead and throw exceptions now since there the cookie is invalid.
143+
if ( ! (count($segments) >= 2))
144+
{
145+
throw new \Exception("Cookie was not set by application.");
146+
}
147+
148+
$value = implode('+', array_slice($segments, 1));
149+
150+
// Now we will check if the SHA-1 hash present in the first segment matches
151+
// the ShA-1 hash of the rest of the cookie value, since the hash should
152+
// have been set when the cookie was first created by the application.
153+
if ($segments[0] == sha1($value.Config::get('application.key')))
154+
{
155+
return $value;
156+
}
157+
158+
throw new \Exception("Cookie has been modified by client.");
159+
}
160+
123161
}

laravel/tests/cases/auth.test.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ public function testLoginStoresRememberCookieWhenNeeded()
269269

270270
$this->assertTrue(isset(Cookie::$jar['laravel_auth_drivers_fluent_remember']));
271271

272-
$cookie = Cookie::$jar['laravel_auth_drivers_fluent_remember']['value'];
272+
$cookie = Cookie::get('laravel_auth_drivers_fluent_remember');
273273
$cookie = explode('|', Crypter::decrypt($cookie));
274274
$this->assertEquals(1, $cookie[0]);
275275
$this->assertEquals('foo', Cookie::$jar['laravel_auth_drivers_fluent_remember']['path']);

laravel/tests/cases/cookie.test.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ protected function restartRequest()
6767
*/
6868
public function testHasMethodIndicatesIfCookieInSet()
6969
{
70-
Cookie::$jar['foo'] = array('value' => 'bar');
70+
Cookie::$jar['foo'] = array('value' => sha1('bar'.Config::get('application.key')).'+bar');
7171
$this->assertTrue(Cookie::has('foo'));
7272
$this->assertFalse(Cookie::has('bar'));
7373

@@ -82,7 +82,7 @@ public function testHasMethodIndicatesIfCookieInSet()
8282
*/
8383
public function testGetMethodCanReturnValueOfCookies()
8484
{
85-
Cookie::$jar['foo'] = array('value' => 'bar');
85+
Cookie::$jar['foo'] = array('value' => sha1('bar'.Config::get('application.key')).'+bar');
8686
$this->assertEquals('bar', Cookie::get('foo'));
8787

8888
Cookie::put('bar', 'baz');
@@ -97,7 +97,7 @@ public function testGetMethodCanReturnValueOfCookies()
9797
public function testForeverShouldUseATonOfMinutes()
9898
{
9999
Cookie::forever('foo', 'bar');
100-
$this->assertEquals('bar', Cookie::$jar['foo']['value']);
100+
$this->assertEquals(sha1('bar'.Config::get('application.key')).'+bar', Cookie::$jar['foo']['value']);
101101

102102
// Shouldn't be able to test this cause while we indicate -2000 seconds
103103
// cookie expiration store timestamp.

laravel/tests/cases/session.test.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ public function testSaveMethodSetsCookieWithCorrectValues()
372372

373373
$cookie = Cookie::$jar[Config::get('session.cookie')];
374374

375-
$this->assertEquals('foo', $cookie['value']);
375+
$this->assertEquals(sha1('foo'.Config::get('application.key')).'+foo', $cookie['value']);
376376
// Shouldn't be able to test this cause session.lifetime store number of minutes
377377
// while cookie expiration store timestamp when it going to expired.
378378
// $this->assertEquals(Config::get('session.lifetime'), $cookie['expiration']);

0 commit comments

Comments
 (0)