Category Archives: Uncategorized

CakePHP – Updated Cryptable Behavior

Almost 2 years ago, I created the Cryptable behavior, documented here. It worked well, and served it’s purpose, but I missed a feature that I soon wished I’d added. So, today, I was working on a new project, and I decided it was time to fix the behavior to add the missing feature.

The old version used the same Initialization Vector for every string it encrypted. This isn’t HORRIBLE, but it does somewhat reduce the security of the encrypted strings. The ‘best practice’ is to generate a unique IV every time you encrypt something, and just store it with the encrypted string to use when you need to decrypt it later. It’s considered safe to store them together, and even transmit them together in the clear without further encryption.

So, without further ado, here’s the updated code for the behavior:

<?php
class CryptableBehavior extends ModelBehavior {
	public $settings = array();
 
	private $iv_size;
	private $base64_iv_size;
 
	function setup(&$model, $settings) {
		if (!isset($this->settings[$model->alias])) {
			$this->settings[$model->alias] = array(
				'fields' => array()
			);
		}
 
		$this->settings[$model->alias] = array_merge($this->settings[$model->alias], $settings);
		$this->iv_size = mcrypt_get_iv_size(Configure::read('Cryptable.cipher'), 'cbc');
		$this->base64_iv_size = strlen(base64_encode(mcrypt_create_iv($this->iv_size, MCRYPT_DEV_URANDOM)));
	}
 
	function beforeFind(&$model, $queryData) {
		foreach ($this->settings[$model->alias]['fields'] AS $field) {
			if (isset($queryData['conditions'][$model->alias.'.'.$field])) {
				$queryData['conditions'][$model->alias.'.'.$field] = $this->encrypt($queryData['conditions'][$model->alias.'.'.$field]);
			}
		}
		return $queryData;
	}
 
	function afterFind(&$model, $results, $primary) {
		foreach ($this->settings[$model->alias]['fields'] AS $field) {
			if ($primary) {
				foreach ($results AS $key => $value) {
					if (isset($value[$model->alias][$field])) {
						$results[$key][$model->alias][$field] = $this->decrypt($value[$model->alias][$field]);
					}
				}
			} else {
				if (isset($results[$field])) {
					$results[$field] = $this->decrypt($results[$field]);
				}
			}
		}
 
		return $results;
	}
 
	function beforeSave(&$model) {
		foreach ($this->settings[$model->alias]['fields'] AS $field) {
			if (isset($model->data[$model->alias][$field])) {
				$model->data[$model->alias]['cleartext_'.$field] = $model->data[$model->alias][$field];
				$model->data[$model->alias][$field] = $this->encrypt($model->data[$model->alias][$field]);
			}
		}
 
		return true;
	}
 
	public function encrypt($data) {
		if ($data !== '') {
			$iv = mcrypt_create_iv($this->iv_size, MCRYPT_DEV_URANDOM);
 
			return base64_encode($iv).base64_encode(mcrypt_encrypt(Configure::read('Cryptable.cipher'), Configure::read('Cryptable.key'), $data, 'cbc', $iv));
		} else {
			return '';
		}
	}
 
	public function decrypt($data, $data2 = null) {
		if (is_object($data)) {
			unset($data);
			$data = $data2;
		}
 
		if ($data != '') {
			$iv = base64_decode(substr($data, 0, $this->base64_iv_size));
			$data = base64_decode(substr($data, $this->base64_iv_size));
 
			return trim(mcrypt_decrypt(Configure::read('Cryptable.cipher'), Configure::read('Cryptable.key'), $data, 'cbc', $iv));
		} else {
			return '';
		}
	}
}

For those using the old behavior, it is possible to upgrade, but you need to do a little bit of work. This amounts to running queries to inject your current IV onto the start of every encrypted field in the database. (PLEASE be careful doing this, and make sure to keep backups.) Also note that you may need to provide more room in the fields, because the data will be somewhat longer now. You can find out how many characters long it will be by running this command in PHP:

echo strlen(base64_encode(mcrypt_create_iv(mcrypt_get_iv_size('CIPHER_HERE', 'cbc'), MCRYPT_DEV_URANDOM)))

The next time the encrypted records are saved, the old default IV will be replaced with a new random one. In fact, any time a record is re-encrypted, it will get a new IV, since I don’t bother with storing the old one when the value is decrypted.

You may also remove the Configure line that holds your old IV, once you’ve injected it into the database on all the records, and tested that the new Cryptable behavior is working as intended.

Please see the original post for any other questions, or feel free to ask in the comments and I’ll do my best to help. :)

Quick Update

A few things to cover in this update, but I’ll keep it short, and try to have something more substantial for later this week.

First, I’ve hit 25% of my weight loss goal! As of this morning, I’ve lost 25.1 pounds. My trend weight is at 283.9, and heading down at a very steady pace. I’m thrilled, and flabbergasted that it’s going so well.

Second, a couple weeks ago, I took and passed the tests for both Technician and General class, so I am now the proud holder of an amateur radio license. My callsign is KF7JLF, but I’m not on the air yet because I don’t have a radio. I’m in the market for a good handheld or mobile radio, preferably at least VHF/UHF dual band. Can’t afford much right now, but I’d be glad to do some PHP or Perl development in trade. Pass the word if you know any ham operators.

Third, my wife has just launched a blog of her own, where she’ll be doing reviews and who knows what else. She’s just getting her feet wet, but check it out sometime, if you have a minute! You can visit it at http://www.tarynn.net/blog/.

That’s about it for today.

DRM – When will they give up?

Well, it’s happened yet again. Ubisoft came up with a grand new copy protection scheme that was going to stop pirates in their tracks. It would be the holy grail that would make it so only paying customers could use the game. If they had an internet connection. Every time they wanted to play the game. Huh. That sounds… annoying. But if it works, maybe it’ll help. Right? Read more »

Hacker’s Diet – Take 2

I’ve tried the Hacker’s Diet once before in the past, and did fairly well, but eventually lost motivation and just stopped. But this year, my employer has offered us what amounts to a free gym membership, and I took the extra step of paying for a trainer. So I’m taking the opportunity to start the Hacker’s Diet back up, and to get deadly serious about getting in better health.

I’m going to the gym 3 times a week, for at least 30 minutes each time. I’m also participating in a bowling league weekly (more exercise than you might think… it makes me break a sweat in a hurry), and once the weather improves, I’ll be golfing at least 9 holes a week (walking and carrying clubs). That plus the great weight tracking provided by the Hacker’s Diet tools has already started to make a big difference in my health. I’m feeling more energetic, and I’ve lost several pounds in the last month.

I’ve added a little weight tracking badge to the sidebar here, and I’ll be posting update regularly to my twitter feed. I want all my friends to hold me accountable on this. Ask me how I’m doing. Chew me out if I start to slip and climb back up in weight. My eventual goal is ~210 pounds, which will take a little more than a year to achieve at 1.5 pounds per week, so by the end of this year, I should be around 225 or so. Which would be amazing. I haven’t weighed 225 since around the time I got married, over 10 years ago.

New Security Plans

Due to repeated problems with hackers on servers at my day job, I’ve developed a new security plan that I’m going to share in a second. First, a little background, and then I’ll list my requirements that I used to develop the plan.

First, we have no official system administrator, and we have 15 or more servers right now, all running CentOS 5. No one really has time to do everything that should be done to keep them up to date and secured. I’ve made loud noises about this for some time, but for various reasons, nothing much has been done about this.

So, my requirements for the new security setup are: 1. Extremely low maintenance once it is in place. I understand that updates are important, but we don’t have someone to do that full time. 2. Because of that lack of personel, it should reduce exposure of possibly vulnerable services as much as possible. 3. Simple to work with and update as needed.

I did some research, and settled upon the following security ‘layers’ if you will.

First layer: Cracklib configured to require much more secure passwords. Most if not all of our compromised servers have been caused by weak passwords on key accounts.

Second layer: SSH daemon configured to not allow remote root login. There is no reason this should be necessary.

Third layer: IP Tables to lock down system so that only ports that are required for the purpose of the server are available publiclly, and all other ports are only open to the systems that need them. This includes locking the SSH and cPanel ports to only be available by default from the main office network, and any static home IPs of workers.

Fourth layer: Port Knocking daemon set up to give the ability to open the SSH port as needed from other locations. I’ve set it up with a 10 port sequence randomly generated from the 10,000 – 49,151 range, and randomly selected as TCP or UDP. Even at only 10 ports long, there’s 8.66 × 1048 possible sequences, which is plenty secure, when in combination with all the other layers. When the knock sequence is detected, it opens port 22 to the origin IP for 15 seconds, and then closes it again.

Fifth layer: DenyHosts daemon set up using global pool of blocked hosts to keep anyone who somehow happens to get through the port knocking from being able to bruteforce the SSH passwords.

I’ve already implemented the five layers above on several servers, and tested them for a while. It seems to be working flawlessly so far, and it should make the servers much more secure. As part of the implimentation process, I have mandated that we re-install the OS on the servers, to make sure they have a clean system with no backdoors built in. I don’t think there’s much chance of someone having a back door in place that could compromise this, but I’m not taking the chance.

If you have any further suggestions, enhancements, or questions, please let me know. I’m always willing to look at improving this plan further.