My Ride
Started: Friday 17th May 2013 4:42pm
Distance: 11.18km
Duration: 00:24:36
Rest Time: 00:03:04
Climb: 111m
Max Speed: 43.2kmph
Average Speed: 27.26kmphInstagrams
-
Recent Posts
Recent Comments
- Arie on Tag Time: CakePHP Tag Plugin
- Paul on Sign Me Up A CakePHP User Registration Plugin
- Paul on Sign Me Up A CakePHP User Registration Plugin
- Watch The Big Bang Theory season 6 episode 13 on On My Tv: With Trakt.tv
- veloura et bellagenix on Ultimate Guestbook Tutorial: How to build a Guestbook with a honeypot, error checking, IP banning, pagination, e-mail notification and smilies with PHP and mySQL
Archives
- February 2013
- December 2012
- September 2012
- July 2012
- January 2012
- September 2011
- August 2011
- February 2011
- January 2011
- November 2010
- October 2010
- August 2010
- June 2010
- May 2010
- April 2010
- March 2010
- February 2010
- January 2010
- December 2009
- November 2009
- October 2009
- September 2009
- August 2009
- July 2009
- June 2009
- May 2009
- April 2009
- March 2009
- February 2009
- January 2009
- December 2008
- November 2008
- October 2008
- September 2008
- August 2008
- July 2008
- June 2008
- May 2008
- April 2008
Categories
Meta
CakePHP Rainbow Table Protection Behaviour
April 18, 2010,
2,710 views
So after looking over some security techniques and discovering the quite interestingly named Rainbow table password cracking mechanism I decided to look into a way around this table password cracker. The default way that CakePHP hashes its passwords into the database is via hashing from a single salt string in core.php. This is a lot better than no salt string, however if someone was keen/bored/lame enough to get to work a rainbow table based on your single salt string then all the passwords/hashed-data stored in your tables would become readable.
**Please note use this post as a guide below. For updated code please see my github repository page as this contains updated code & guides**
GitHub: http://github.com/voidet/grey_tables
A way around this is to add a unique salt string per record, along with the CakePHP’s salt string from core.php. This was a rainbow table would have to be constructed based on a per record basis, and not just on a table. This would mean that the lamer would have to wait a few lifetimes to crack all the passwords in your database table, or wait a long time to crack a single user’s. So my initial behaviour is as follows, and it does require some work arounds:
<?php
class GreyTablesBehavior extends ModelBehavior {
function setup(&$model, $settings = array()) {
$default = array('field' => 'salt');
if (!isset($this->settings[$model->name])) {
$this->settings[$model->name] = $default;
}
$this->settings[$model->name] = array_merge($this->settings[$model->name], ife(is_array($settings), $settings, array()));
}
function beforeFind(&$model, $queryData) {
if(!empty($queryData['conditions'][$model->name.'.password']) && !empty($queryData['conditions'][$model->name.'.username'])) {
$user_id = $this->findSaltedUser($model, $queryData['conditions']);
if (!empty($user_id)) {
unset($queryData['conditions']);
$queryData['conditions'] = $user_id;
}
}
return $queryData;
}
function beforeSave(&$model) {
if (empty($this->id) && !empty($model->data[$model->name])) {
$data = &$model->data[$model->name];
$data['password'] = $this->generateSaltedPassword($data['password'], $data[$this->settings[$model->name]['field']]);
}
return parent::beforeSave(&$model);
}
function generateSaltedPassword($password = '', $saltString) {
if (!empty($password)) {
return Security::hash($password.$saltString, null, false);
}
}
function findSaltedUser(&$model, $fields = array()) {
if (!empty($fields)) {
$user_id = $model->query('SELECT `'.$model->name.'`.`id` as 'id' FROM '.$model->table.' as '.$model->name.' WHERE `'.$model->name.'`.`username` = ''.$fields[$model->name.'.username'].'' AND `'.$model->name.'`.`password` = SHA1(CONCAT(''.$fields[$model->name.'.password'].'', `'.$this->settings[$model->name]['field'].'`)) LIMIT 1');
if (!empty($user_id)) {
$fields[$model->name.'.id'] = $user_id[0][$model->name]['id'];
unset($fields[$model->name.'.password'], $fields[$model->name.'.username']);
}
}
return $fields;
}
function hashPasswords(&$data, $alias) {
if (isset($data[$alias]['password'])) {
$model->data = $data;
$model->data[$alias][$this->settings[$alias]['field']] = Security::hash(String::uuid(), null, true);
$model->data[$alias]['password'] = Security::hash($data[$alias]['password'], null, true);
return $model->data;
}
return $data;
}
}
?>
Now in your model you would do something like:
<?php
class Member extends AppModel {
var $actsAs = array('GreyTables');
function hashPasswords($data) {
return $this->Behaviors->GreyTables->hashPasswords($data, $this->alias);
}
}
?>
It’s a simple work around to get the behaviour to use the hashPasswords method automatically called. I am yet to do any extensive benchmarks on this code, and will have to include more settings in regards to how the salting is handled, and also the default username/password/email fields to be used to check the Auth. That will come soon. There is one flaw however, in that the conditions are constructed in two parts. The first part looks for the resalted username/password combo, then the second part uses the id found from that query and follows up with any other conditions to be used for the query. For example:
First query:
SELECT `Member`.`id` as 'id' FROM members as Member WHERE `Member`.`username` = 'testuser' AND `Member`.`password` = SHA1(CONCAT('1e71a44447c4e3ea05e8f81f031702f00d19c48e', `salt`)) LIMIT 1
Second query:
SELECT `Member`.`id`, `Member`.`username`, `Member`.`email`, `Member`.`password`, `Member`.`salt`, `Member`.`active`, `Member`.`created`, `Member`.`modified` FROM `members` AS `Member` WHERE `Member`.`active` = 1 AND `Member`.`id` = 52 LIMIT 1
I will be working to make the second query work as a read via the Id, as apposed to extra conditions.
More to come!





