diff --git a/cake/libs/controller/components/security.php b/cake/libs/controller/components/security.php index c267c6ce189..7e5b3b28f3d 100644 --- a/cake/libs/controller/components/security.php +++ b/cake/libs/controller/components/security.php @@ -618,10 +618,15 @@ function _validatePost(&$controller) { } unset($check['_Token']); + $locked = str_rot13($locked); + if (preg_match('/(\A|;|{|})O\:[0-9]+/', $locked)) { + return false; + } + $lockedFields = array(); $fields = Set::flatten($check); $fieldList = array_keys($fields); - $locked = unserialize(str_rot13($locked)); + $locked = unserialize($locked); $multi = array(); foreach ($fieldList as $i => $key) { diff --git a/cake/tests/cases/libs/controller/components/security.test.php b/cake/tests/cases/libs/controller/components/security.test.php index 883f1c810b9..bbd51410041 100644 --- a/cake/tests/cases/libs/controller/components/security.test.php +++ b/cake/tests/cases/libs/controller/components/security.test.php @@ -608,6 +608,30 @@ function testValidatePostFormHacking() { $result = $this->Controller->Security->validatePost($this->Controller); $this->assertFalse($result, 'validatePost passed when key was missing. %s'); } + +/** + * Test that objects can't be passed into the serialized string. This was a vector for RFI and LFI + * attacks. Thanks to Felix Wilhelm + * + * @return void + */ + function testValidatePostObjectDeserialize() { + $this->Controller->Security->startup($this->Controller); + $key = $this->Controller->params['_Token']['key']; + $fields = 'a5475372b40f6e3ccbf9f8af191f20e1642fd877'; + + // a corrupted serialized object, so we can see if it ever gets to deserialize + $attack = 'O:3:"App":1:{s:5:"__map";a:1:{s:3:"foo";s:7:"Hacked!";s:1:"fail"}}'; + $fields .= urlencode(':' . str_rot13($attack)); + + $this->Controller->data = array( + 'Model' => array('username' => 'mark', 'password' => 'foo', 'valid' => '0'), + '_Token' => compact('key', 'fields') + ); + $result = $this->Controller->Security->validatePost($this->Controller); + $this->assertFalse($result, 'validatePost passed when key was missing. %s'); + } + /** * Tests validation of checkbox arrays *