mirror of
https://github.com/kamilwylegala/cakephp2-php8.git
synced 2024-12-24 14:37:25 +00:00
1186 lines
34 KiB
PHP
1186 lines
34 KiB
PHP
<?php
|
|
/**
|
|
* SecurityComponentTest file
|
|
*
|
|
* PHP 5
|
|
*
|
|
* CakePHP(tm) Tests <http://book.cakephp.org/view/1196/Testing>
|
|
* Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
|
|
*
|
|
* Licensed under The MIT License
|
|
* Redistributions of files must retain the above copyright notice
|
|
*
|
|
* @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
|
|
* @link http://book.cakephp.org/view/1196/Testing CakePHP(tm) Tests
|
|
* @package cake.tests.cases.libs.controller.components
|
|
* @since CakePHP(tm) v 1.2.0.5435
|
|
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
|
*/
|
|
|
|
App::uses('SecurityComponent', 'Controller/Component');
|
|
App::uses('Controller', 'Controller');
|
|
|
|
/**
|
|
* TestSecurityComponent
|
|
*
|
|
* @package cake
|
|
* @package cake.tests.cases.libs.controller.components
|
|
*/
|
|
class TestSecurityComponent extends SecurityComponent {
|
|
|
|
/**
|
|
* validatePost method
|
|
*
|
|
* @param Controller $controller
|
|
* @return unknown
|
|
*/
|
|
function validatePost($controller) {
|
|
return $this->_validatePost($controller);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* SecurityTestController
|
|
*
|
|
* @package cake
|
|
* @package cake.tests.cases.libs.controller.components
|
|
*/
|
|
class SecurityTestController extends Controller {
|
|
|
|
/**
|
|
* name property
|
|
*
|
|
* @var string 'SecurityTest'
|
|
* @access public
|
|
*/
|
|
public $name = 'SecurityTest';
|
|
|
|
/**
|
|
* components property
|
|
*
|
|
* @var array
|
|
* @access public
|
|
*/
|
|
public $components = array('Session', 'TestSecurity');
|
|
|
|
/**
|
|
* failed property
|
|
*
|
|
* @var bool false
|
|
* @access public
|
|
*/
|
|
public $failed = false;
|
|
|
|
/**
|
|
* Used for keeping track of headers in test
|
|
*
|
|
* @var array
|
|
* @access public
|
|
*/
|
|
public $testHeaders = array();
|
|
|
|
/**
|
|
* fail method
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
function fail() {
|
|
$this->failed = true;
|
|
}
|
|
|
|
/**
|
|
* redirect method
|
|
*
|
|
* @param mixed $option
|
|
* @param mixed $code
|
|
* @param mixed $exit
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
function redirect($url, $status = null, $exit = true) {
|
|
return $status;
|
|
}
|
|
|
|
/**
|
|
* Conveinence method for header()
|
|
*
|
|
* @param string $status
|
|
* @return void
|
|
*/
|
|
public function header($status) {
|
|
$this->testHeaders[] = $status;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* SecurityComponentTest class
|
|
*
|
|
* @package cake.tests.cases.libs.controller.components
|
|
*/
|
|
class SecurityComponentTest extends CakeTestCase {
|
|
|
|
/**
|
|
* Controller property
|
|
*
|
|
* @var SecurityTestController
|
|
* @access public
|
|
*/
|
|
public $Controller;
|
|
|
|
/**
|
|
* oldSalt property
|
|
*
|
|
* @var string
|
|
* @access public
|
|
*/
|
|
public $oldSalt;
|
|
|
|
/**
|
|
* setUp method
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
function setUp() {
|
|
parent::setUp();
|
|
|
|
$request = new CakeRequest('posts/index', false);
|
|
$request->addParams(array('controller' => 'posts', 'action' => 'index'));
|
|
$this->Controller = new SecurityTestController($request);
|
|
$this->Controller->Components->init($this->Controller);
|
|
$this->Controller->Security = $this->Controller->TestSecurity;
|
|
$this->Controller->Security->blackHoleCallback = 'fail';
|
|
$this->Security = $this->Controller->Security;
|
|
$this->Security->csrfCheck = false;
|
|
|
|
Configure::write('Security.salt', 'foo!');
|
|
}
|
|
|
|
/**
|
|
* Tear-down method. Resets environment state.
|
|
*
|
|
* @return void
|
|
*/
|
|
function tearDown() {
|
|
parent::tearDown();
|
|
$this->Controller->Session->delete('_Token');
|
|
unset($this->Controller->Security);
|
|
unset($this->Controller->Component);
|
|
unset($this->Controller);
|
|
}
|
|
|
|
/**
|
|
* test that initalize can set properties.
|
|
*
|
|
* @return void
|
|
*/
|
|
function testConstructorSettingProperties() {
|
|
$settings = array(
|
|
'requirePost' => array('edit', 'update'),
|
|
'requireSecure' => array('update_account'),
|
|
'requireGet' => array('index'),
|
|
'validatePost' => false,
|
|
);
|
|
$Security = new SecurityComponent($this->Controller->Components, $settings);
|
|
$this->Controller->Security->initialize($this->Controller, $settings);
|
|
$this->assertEqual($Security->requirePost, $settings['requirePost']);
|
|
$this->assertEqual($Security->requireSecure, $settings['requireSecure']);
|
|
$this->assertEqual($Security->requireGet, $settings['requireGet']);
|
|
$this->assertEqual($Security->validatePost, $settings['validatePost']);
|
|
}
|
|
|
|
/**
|
|
* testStartup method
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
function testStartup() {
|
|
$this->Controller->Security->startup($this->Controller);
|
|
$result = $this->Controller->params['_Token']['key'];
|
|
$this->assertNotNull($result);
|
|
$this->assertTrue($this->Controller->Session->check('_Token'));
|
|
}
|
|
|
|
/**
|
|
* testRequirePostFail method
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
function testRequirePostFail() {
|
|
$_SERVER['REQUEST_METHOD'] = 'GET';
|
|
$this->Controller->request['action'] = 'posted';
|
|
$this->Controller->Security->requirePost(array('posted'));
|
|
$this->Controller->Security->startup($this->Controller);
|
|
$this->assertTrue($this->Controller->failed);
|
|
}
|
|
|
|
/**
|
|
* testRequirePostSucceed method
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
function testRequirePostSucceed() {
|
|
$_SERVER['REQUEST_METHOD'] = 'POST';
|
|
$this->Controller->request['action'] = 'posted';
|
|
$this->Controller->Security->requirePost('posted');
|
|
$this->Security->startup($this->Controller);
|
|
$this->assertFalse($this->Controller->failed);
|
|
}
|
|
|
|
/**
|
|
* testRequireSecureFail method
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
function testRequireSecureFail() {
|
|
$_SERVER['HTTPS'] = 'off';
|
|
$_SERVER['REQUEST_METHOD'] = 'POST';
|
|
$this->Controller->request['action'] = 'posted';
|
|
$this->Controller->Security->requireSecure(array('posted'));
|
|
$this->Controller->Security->startup($this->Controller);
|
|
$this->assertTrue($this->Controller->failed);
|
|
}
|
|
|
|
/**
|
|
* testRequireSecureSucceed method
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
function testRequireSecureSucceed() {
|
|
$_SERVER['REQUEST_METHOD'] = 'Secure';
|
|
$this->Controller->request['action'] = 'posted';
|
|
$_SERVER['HTTPS'] = 'on';
|
|
$this->Controller->Security->requireSecure('posted');
|
|
$this->Controller->Security->startup($this->Controller);
|
|
$this->assertFalse($this->Controller->failed);
|
|
}
|
|
|
|
/**
|
|
* testRequireAuthFail method
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
function testRequireAuthFail() {
|
|
$_SERVER['REQUEST_METHOD'] = 'AUTH';
|
|
$this->Controller->request['action'] = 'posted';
|
|
$this->Controller->request->data = array('username' => 'willy', 'password' => 'somePass');
|
|
$this->Controller->Security->requireAuth(array('posted'));
|
|
$this->Controller->Security->startup($this->Controller);
|
|
$this->assertTrue($this->Controller->failed);
|
|
|
|
$this->Controller->Session->write('_Token', array('allowedControllers' => array()));
|
|
$this->Controller->request->data = array('username' => 'willy', 'password' => 'somePass');
|
|
$this->Controller->request['action'] = 'posted';
|
|
$this->Controller->Security->requireAuth('posted');
|
|
$this->Controller->Security->startup($this->Controller);
|
|
$this->assertTrue($this->Controller->failed);
|
|
|
|
$this->Controller->Session->write('_Token', array(
|
|
'allowedControllers' => array('SecurityTest'), 'allowedActions' => array('posted2')
|
|
));
|
|
$this->Controller->request->data = array('username' => 'willy', 'password' => 'somePass');
|
|
$this->Controller->request['action'] = 'posted';
|
|
$this->Controller->Security->requireAuth('posted');
|
|
$this->Controller->Security->startup($this->Controller);
|
|
$this->assertTrue($this->Controller->failed);
|
|
}
|
|
|
|
/**
|
|
* testRequireAuthSucceed method
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
function testRequireAuthSucceed() {
|
|
$_SERVER['REQUEST_METHOD'] = 'AUTH';
|
|
$this->Controller->request['action'] = 'posted';
|
|
$this->Controller->Security->requireAuth('posted');
|
|
$this->Controller->Security->startup($this->Controller);
|
|
$this->assertFalse($this->Controller->failed);
|
|
|
|
$this->Controller->Security->Session->write('_Token', array(
|
|
'allowedControllers' => array('SecurityTest'), 'allowedActions' => array('posted')
|
|
));
|
|
$this->Controller->request['controller'] = 'SecurityTest';
|
|
$this->Controller->request['action'] = 'posted';
|
|
|
|
$this->Controller->request->data = array(
|
|
'username' => 'willy', 'password' => 'somePass', '_Token' => ''
|
|
);
|
|
$this->Controller->action = 'posted';
|
|
$this->Controller->Security->requireAuth('posted');
|
|
$this->Controller->Security->startup($this->Controller);
|
|
$this->assertFalse($this->Controller->failed);
|
|
}
|
|
|
|
/**
|
|
* testRequirePostSucceedWrongMethod method
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
function testRequirePostSucceedWrongMethod() {
|
|
$_SERVER['REQUEST_METHOD'] = 'GET';
|
|
$this->Controller->request['action'] = 'getted';
|
|
$this->Controller->Security->requirePost('posted');
|
|
$this->Controller->Security->startup($this->Controller);
|
|
$this->assertFalse($this->Controller->failed);
|
|
}
|
|
|
|
/**
|
|
* testRequireGetFail method
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
function testRequireGetFail() {
|
|
$_SERVER['REQUEST_METHOD'] = 'POST';
|
|
$this->Controller->request['action'] = 'getted';
|
|
$this->Controller->Security->requireGet(array('getted'));
|
|
$this->Controller->Security->startup($this->Controller);
|
|
$this->assertTrue($this->Controller->failed);
|
|
}
|
|
|
|
/**
|
|
* testRequireGetSucceed method
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
function testRequireGetSucceed() {
|
|
$_SERVER['REQUEST_METHOD'] = 'GET';
|
|
$this->Controller->request['action'] = 'getted';
|
|
$this->Controller->Security->requireGet('getted');
|
|
$this->Controller->Security->startup($this->Controller);
|
|
$this->assertFalse($this->Controller->failed);
|
|
}
|
|
|
|
/**
|
|
* testRequireGetSucceedWrongMethod method
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
function testRequireGetSucceedWrongMethod() {
|
|
$_SERVER['REQUEST_METHOD'] = 'POST';
|
|
$this->Controller->request['action'] = 'posted';
|
|
$this->Security->requireGet('getted');
|
|
$this->Security->startup($this->Controller);
|
|
$this->assertFalse($this->Controller->failed);
|
|
}
|
|
|
|
/**
|
|
* testRequirePutFail method
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
function testRequirePutFail() {
|
|
$_SERVER['REQUEST_METHOD'] = 'POST';
|
|
$this->Controller->request['action'] = 'putted';
|
|
$this->Controller->Security->requirePut(array('putted'));
|
|
$this->Controller->Security->startup($this->Controller);
|
|
$this->assertTrue($this->Controller->failed);
|
|
}
|
|
|
|
/**
|
|
* testRequirePutSucceed method
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
function testRequirePutSucceed() {
|
|
$_SERVER['REQUEST_METHOD'] = 'PUT';
|
|
$this->Controller->request['action'] = 'putted';
|
|
$this->Controller->Security->requirePut('putted');
|
|
$this->Controller->Security->startup($this->Controller);
|
|
$this->assertFalse($this->Controller->failed);
|
|
}
|
|
|
|
/**
|
|
* testRequirePutSucceedWrongMethod method
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
function testRequirePutSucceedWrongMethod() {
|
|
$_SERVER['REQUEST_METHOD'] = 'POST';
|
|
$this->Controller->request['action'] = 'posted';
|
|
$this->Controller->Security->requirePut('putted');
|
|
$this->Controller->Security->startup($this->Controller);
|
|
$this->assertFalse($this->Controller->failed);
|
|
}
|
|
|
|
/**
|
|
* testRequireDeleteFail method
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
function testRequireDeleteFail() {
|
|
$_SERVER['REQUEST_METHOD'] = 'POST';
|
|
$this->Controller->request['action'] = 'deleted';
|
|
$this->Controller->Security->requireDelete(array('deleted', 'other_method'));
|
|
$this->Controller->Security->startup($this->Controller);
|
|
$this->assertTrue($this->Controller->failed);
|
|
}
|
|
|
|
/**
|
|
* testRequireDeleteSucceed method
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
function testRequireDeleteSucceed() {
|
|
$_SERVER['REQUEST_METHOD'] = 'DELETE';
|
|
$this->Controller->request['action'] = 'deleted';
|
|
$this->Controller->Security->requireDelete('deleted');
|
|
$this->Controller->Security->startup($this->Controller);
|
|
$this->assertFalse($this->Controller->failed);
|
|
}
|
|
|
|
/**
|
|
* testRequireDeleteSucceedWrongMethod method
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
function testRequireDeleteSucceedWrongMethod() {
|
|
$_SERVER['REQUEST_METHOD'] = 'POST';
|
|
$this->Controller->request['action'] = 'posted';
|
|
$this->Controller->Security->requireDelete('deleted');
|
|
$this->Controller->Security->startup($this->Controller);
|
|
$this->assertFalse($this->Controller->failed);
|
|
}
|
|
|
|
/**
|
|
* Simple hash validation test
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
function testValidatePost() {
|
|
$this->Controller->Security->startup($this->Controller);
|
|
|
|
$key = $this->Controller->request->params['_Token']['key'];
|
|
$fields = 'a5475372b40f6e3ccbf9f8af191f20e1642fd877%3AModel.valid';
|
|
|
|
$this->Controller->request->data = array(
|
|
'Model' => array('username' => 'nate', 'password' => 'foo', 'valid' => '0'),
|
|
'_Token' => compact('key', 'fields')
|
|
);
|
|
$this->assertTrue($this->Controller->Security->validatePost($this->Controller));
|
|
}
|
|
|
|
/**
|
|
* test that validatePost fails if any of its required fields are missing.
|
|
*
|
|
* @return void
|
|
*/
|
|
function testValidatePostFormHacking() {
|
|
$this->Controller->Security->startup($this->Controller);
|
|
$key = $this->Controller->params['_Token']['key'];
|
|
$fields = 'a5475372b40f6e3ccbf9f8af191f20e1642fd877%3AModel.valid';
|
|
|
|
$this->Controller->request->data = array(
|
|
'Model' => array('username' => 'nate', 'password' => 'foo', 'valid' => '0'),
|
|
'_Token' => compact('key')
|
|
);
|
|
$result = $this->Controller->Security->validatePost($this->Controller);
|
|
$this->assertFalse($result, 'validatePost passed when fields were 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->request->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->request->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
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
function testValidatePostArray() {
|
|
$this->Controller->Security->startup($this->Controller);
|
|
|
|
$key = $this->Controller->request->params['_Token']['key'];
|
|
$fields = 'f7d573650a295b94e0938d32b323fde775e5f32b%3A';
|
|
|
|
$this->Controller->request->data = array(
|
|
'Model' => array('multi_field' => array('1', '3')),
|
|
'_Token' => compact('key', 'fields')
|
|
);
|
|
$this->assertTrue($this->Controller->Security->validatePost($this->Controller));
|
|
}
|
|
|
|
/**
|
|
* testValidatePostNoModel method
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
function testValidatePostNoModel() {
|
|
$this->Controller->Security->startup($this->Controller);
|
|
|
|
$key = $this->Controller->request->params['_Token']['key'];
|
|
$fields = '540ac9c60d323c22bafe997b72c0790f39a8bdef%3A';
|
|
|
|
$this->Controller->request->data = array(
|
|
'anything' => 'some_data',
|
|
'_Token' => compact('key', 'fields')
|
|
);
|
|
|
|
$result = $this->Controller->Security->validatePost($this->Controller);
|
|
$this->assertTrue($result);
|
|
}
|
|
|
|
/**
|
|
* testValidatePostSimple method
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
function testValidatePostSimple() {
|
|
$this->Controller->Security->startup($this->Controller);
|
|
|
|
$key = $this->Controller->request->params['_Token']['key'];
|
|
$fields = '69f493434187b867ea14b901fdf58b55d27c935d%3A';
|
|
|
|
$this->Controller->request->data = $data = array(
|
|
'Model' => array('username' => '', 'password' => ''),
|
|
'_Token' => compact('key', 'fields')
|
|
);
|
|
|
|
$result = $this->Controller->Security->validatePost($this->Controller);
|
|
$this->assertTrue($result);
|
|
}
|
|
|
|
/**
|
|
* Tests hash validation for multiple records, including locked fields
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
function testValidatePostComplex() {
|
|
$this->Controller->Security->startup($this->Controller);
|
|
|
|
$key = $this->Controller->request->params['_Token']['key'];
|
|
$fields = 'c9118120e680a7201b543f562e5301006ccfcbe2%3AAddresses.0.id%7CAddresses.1.id';
|
|
|
|
$this->Controller->request->data = array(
|
|
'Addresses' => array(
|
|
'0' => array(
|
|
'id' => '123456', 'title' => '', 'first_name' => '', 'last_name' => '',
|
|
'address' => '', 'city' => '', 'phone' => '', 'primary' => ''
|
|
),
|
|
'1' => array(
|
|
'id' => '654321', 'title' => '', 'first_name' => '', 'last_name' => '',
|
|
'address' => '', 'city' => '', 'phone' => '', 'primary' => ''
|
|
)
|
|
),
|
|
'_Token' => compact('key', 'fields')
|
|
);
|
|
$result = $this->Controller->Security->validatePost($this->Controller);
|
|
$this->assertTrue($result);
|
|
}
|
|
|
|
/**
|
|
* test ValidatePost with multiple select elements.
|
|
*
|
|
* @return void
|
|
*/
|
|
function testValidatePostMultipleSelect() {
|
|
$this->Controller->Security->startup($this->Controller);
|
|
|
|
$key = $this->Controller->request->params['_Token']['key'];
|
|
$fields = '422cde416475abc171568be690a98cad20e66079%3A';
|
|
|
|
$this->Controller->request->data = array(
|
|
'Tag' => array('Tag' => array(1, 2)),
|
|
'_Token' => compact('key', 'fields'),
|
|
);
|
|
$result = $this->Controller->Security->validatePost($this->Controller);
|
|
$this->assertTrue($result);
|
|
|
|
$this->Controller->request->data = array(
|
|
'Tag' => array('Tag' => array(1, 2, 3)),
|
|
'_Token' => compact('key', 'fields'),
|
|
);
|
|
$result = $this->Controller->Security->validatePost($this->Controller);
|
|
$this->assertTrue($result);
|
|
|
|
$this->Controller->request->data = array(
|
|
'Tag' => array('Tag' => array(1, 2, 3, 4)),
|
|
'_Token' => compact('key', 'fields'),
|
|
);
|
|
$result = $this->Controller->Security->validatePost($this->Controller);
|
|
$this->assertTrue($result);
|
|
|
|
$fields = '19464422eafe977ee729c59222af07f983010c5f%3A';
|
|
$this->Controller->request->data = array(
|
|
'User.password' => 'bar', 'User.name' => 'foo', 'User.is_valid' => '1',
|
|
'Tag' => array('Tag' => array(1)), '_Token' => compact('key', 'fields'),
|
|
);
|
|
$result = $this->Controller->Security->validatePost($this->Controller);
|
|
$this->assertTrue($result);
|
|
}
|
|
|
|
/**
|
|
* testValidatePostCheckbox method
|
|
*
|
|
* First block tests un-checked checkbox
|
|
* Second block tests checked checkbox
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
function testValidatePostCheckbox() {
|
|
$this->Controller->Security->startup($this->Controller);
|
|
$key = $this->Controller->request->params['_Token']['key'];
|
|
$fields = 'a5475372b40f6e3ccbf9f8af191f20e1642fd877%3AModel.valid';
|
|
|
|
$this->Controller->request->data = array(
|
|
'Model' => array('username' => '', 'password' => '', 'valid' => '0'),
|
|
'_Token' => compact('key', 'fields')
|
|
);
|
|
|
|
$result = $this->Controller->Security->validatePost($this->Controller);
|
|
$this->assertTrue($result);
|
|
|
|
$fields = '874439ca69f89b4c4a5f50fb9c36ff56a28f5d42%3A';
|
|
|
|
$this->Controller->request->data = array(
|
|
'Model' => array('username' => '', 'password' => '', 'valid' => '0'),
|
|
'_Token' => compact('key', 'fields')
|
|
);
|
|
|
|
$result = $this->Controller->Security->validatePost($this->Controller);
|
|
$this->assertTrue($result);
|
|
|
|
|
|
$this->Controller->request->data = array();
|
|
$this->Controller->Security->startup($this->Controller);
|
|
$key = $this->Controller->request->params['_Token']['key'];
|
|
|
|
$this->Controller->request->data = $data = array(
|
|
'Model' => array('username' => '', 'password' => '', 'valid' => '0'),
|
|
'_Token' => compact('key', 'fields')
|
|
);
|
|
|
|
$result = $this->Controller->Security->validatePost($this->Controller);
|
|
$this->assertTrue($result);
|
|
}
|
|
|
|
/**
|
|
* testValidatePostHidden method
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
function testValidatePostHidden() {
|
|
$this->Controller->Security->startup($this->Controller);
|
|
$key = $this->Controller->request->params['_Token']['key'];
|
|
$fields = '51ccd8cb0997c7b3d4523ecde5a109318405ef8c%3AModel.hidden%7CModel.other_hidden';
|
|
$fields .= '';
|
|
|
|
$this->Controller->request->data = array(
|
|
'Model' => array(
|
|
'username' => '', 'password' => '', 'hidden' => '0',
|
|
'other_hidden' => 'some hidden value'
|
|
),
|
|
'_Token' => compact('key', 'fields')
|
|
);
|
|
$result = $this->Controller->Security->validatePost($this->Controller);
|
|
$this->assertTrue($result);
|
|
}
|
|
|
|
/**
|
|
* testValidatePostWithDisabledFields method
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
function testValidatePostWithDisabledFields() {
|
|
$this->Controller->Security->disabledFields = array('Model.username', 'Model.password');
|
|
$this->Controller->Security->startup($this->Controller);
|
|
$key = $this->Controller->request->params['_Token']['key'];
|
|
$fields = 'ef1082968c449397bcd849f963636864383278b1%3AModel.hidden';
|
|
|
|
$this->Controller->request->data = array(
|
|
'Model' => array(
|
|
'username' => '', 'password' => '', 'hidden' => '0'
|
|
),
|
|
'_Token' => compact('fields', 'key')
|
|
);
|
|
|
|
$result = $this->Controller->Security->validatePost($this->Controller);
|
|
$this->assertTrue($result);
|
|
}
|
|
|
|
/**
|
|
* testValidateHiddenMultipleModel method
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
function testValidateHiddenMultipleModel() {
|
|
$this->Controller->Security->startup($this->Controller);
|
|
$key = $this->Controller->request->params['_Token']['key'];
|
|
$fields = 'a2d01072dc4660eea9d15007025f35a7a5b58e18%3AModel.valid%7CModel2.valid%7CModel3.valid';
|
|
|
|
$this->Controller->request->data = array(
|
|
'Model' => array('username' => '', 'password' => '', 'valid' => '0'),
|
|
'Model2' => array('valid' => '0'),
|
|
'Model3' => array('valid' => '0'),
|
|
'_Token' => compact('key', 'fields')
|
|
);
|
|
$result = $this->Controller->Security->validatePost($this->Controller);
|
|
$this->assertTrue($result);
|
|
}
|
|
|
|
/**
|
|
* testValidateHasManyModel method
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
function testValidateHasManyModel() {
|
|
$this->Controller->Security->startup($this->Controller);
|
|
$key = $this->Controller->request->params['_Token']['key'];
|
|
$fields = '51e3b55a6edd82020b3f29c9ae200e14bbeb7ee5%3AModel.0.hidden%7CModel.0.valid';
|
|
$fields .= '%7CModel.1.hidden%7CModel.1.valid';
|
|
|
|
$this->Controller->request->data = array(
|
|
'Model' => array(
|
|
array(
|
|
'username' => 'username', 'password' => 'password',
|
|
'hidden' => 'value', 'valid' => '0'
|
|
),
|
|
array(
|
|
'username' => 'username', 'password' => 'password',
|
|
'hidden' => 'value', 'valid' => '0'
|
|
)
|
|
),
|
|
'_Token' => compact('key', 'fields')
|
|
);
|
|
|
|
$result = $this->Controller->Security->validatePost($this->Controller);
|
|
$this->assertTrue($result);
|
|
}
|
|
|
|
/**
|
|
* testValidateHasManyRecordsPass method
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
function testValidateHasManyRecordsPass() {
|
|
$this->Controller->Security->startup($this->Controller);
|
|
$key = $this->Controller->request->params['_Token']['key'];
|
|
$fields = '7a203edb3d345bbf38fe0dccae960da8842e11d7%3AAddress.0.id%7CAddress.0.primary%7C';
|
|
$fields .= 'Address.1.id%7CAddress.1.primary';
|
|
|
|
$this->Controller->request->data = array(
|
|
'Address' => array(
|
|
0 => array(
|
|
'id' => '123',
|
|
'title' => 'home',
|
|
'first_name' => 'Bilbo',
|
|
'last_name' => 'Baggins',
|
|
'address' => '23 Bag end way',
|
|
'city' => 'the shire',
|
|
'phone' => 'N/A',
|
|
'primary' => '1',
|
|
),
|
|
1 => array(
|
|
'id' => '124',
|
|
'title' => 'home',
|
|
'first_name' => 'Frodo',
|
|
'last_name' => 'Baggins',
|
|
'address' => '50 Bag end way',
|
|
'city' => 'the shire',
|
|
'phone' => 'N/A',
|
|
'primary' => '1'
|
|
)
|
|
),
|
|
'_Token' => compact('key', 'fields')
|
|
);
|
|
|
|
$result = $this->Controller->Security->validatePost($this->Controller);
|
|
$this->assertTrue($result);
|
|
}
|
|
|
|
/**
|
|
* testValidateHasManyRecords method
|
|
*
|
|
* validatePost should fail, hidden fields have been changed.
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
function testValidateHasManyRecordsFail() {
|
|
$this->Controller->Security->startup($this->Controller);
|
|
$key = $this->Controller->request->params['_Token']['key'];
|
|
$fields = '7a203edb3d345bbf38fe0dccae960da8842e11d7%3AAddress.0.id%7CAddress.0.primary%7C';
|
|
$fields .= 'Address.1.id%7CAddress.1.primary';
|
|
|
|
$this->Controller->request->data = array(
|
|
'Address' => array(
|
|
0 => array(
|
|
'id' => '123',
|
|
'title' => 'home',
|
|
'first_name' => 'Bilbo',
|
|
'last_name' => 'Baggins',
|
|
'address' => '23 Bag end way',
|
|
'city' => 'the shire',
|
|
'phone' => 'N/A',
|
|
'primary' => '5',
|
|
),
|
|
1 => array(
|
|
'id' => '124',
|
|
'title' => 'home',
|
|
'first_name' => 'Frodo',
|
|
'last_name' => 'Baggins',
|
|
'address' => '50 Bag end way',
|
|
'city' => 'the shire',
|
|
'phone' => 'N/A',
|
|
'primary' => '1'
|
|
)
|
|
),
|
|
'_Token' => compact('key', 'fields')
|
|
);
|
|
|
|
$result = $this->Controller->Security->validatePost($this->Controller);
|
|
$this->assertFalse($result);
|
|
}
|
|
|
|
/**
|
|
* testFormDisabledFields method
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
function testFormDisabledFields() {
|
|
$this->Controller->Security->startup($this->Controller);
|
|
$key = $this->Controller->request->params['_Token']['key'];
|
|
$fields = '11842060341b9d0fc3808b90ba29fdea7054d6ad%3An%3A0%3A%7B%7D';
|
|
|
|
$this->Controller->request->data = array(
|
|
'MyModel' => array('name' => 'some data'),
|
|
'_Token' => compact('key', 'fields')
|
|
);
|
|
$result = $this->Controller->Security->validatePost($this->Controller);
|
|
$this->assertFalse($result);
|
|
|
|
$this->Controller->Security->startup($this->Controller);
|
|
$this->Controller->Security->disabledFields = array('MyModel.name');
|
|
$key = $this->Controller->request->params['_Token']['key'];
|
|
|
|
$this->Controller->request->data = array(
|
|
'MyModel' => array('name' => 'some data'),
|
|
'_Token' => compact('key', 'fields')
|
|
);
|
|
|
|
$result = $this->Controller->Security->validatePost($this->Controller);
|
|
$this->assertTrue($result);
|
|
}
|
|
|
|
/**
|
|
* testRadio method
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
function testRadio() {
|
|
$this->Controller->Security->startup($this->Controller);
|
|
$key = $this->Controller->request->params['_Token']['key'];
|
|
$fields = '575ef54ca4fc8cab468d6d898e9acd3a9671c17e%3An%3A0%3A%7B%7D';
|
|
|
|
$this->Controller->request->data = array(
|
|
'_Token' => compact('key', 'fields')
|
|
);
|
|
$result = $this->Controller->Security->validatePost($this->Controller);
|
|
$this->assertFalse($result);
|
|
|
|
$this->Controller->request->data = array(
|
|
'_Token' => compact('key', 'fields'),
|
|
'Test' => array('test' => '')
|
|
);
|
|
$result = $this->Controller->Security->validatePost($this->Controller);
|
|
$this->assertTrue($result);
|
|
|
|
$this->Controller->request->data = array(
|
|
'_Token' => compact('key', 'fields'),
|
|
'Test' => array('test' => '1')
|
|
);
|
|
$result = $this->Controller->Security->validatePost($this->Controller);
|
|
$this->assertTrue($result);
|
|
|
|
$this->Controller->request->data = array(
|
|
'_Token' => compact('key', 'fields'),
|
|
'Test' => array('test' => '2')
|
|
);
|
|
$result = $this->Controller->Security->validatePost($this->Controller);
|
|
$this->assertTrue($result);
|
|
}
|
|
|
|
/**
|
|
* test that a requestAction's controller will have the _Token appended to
|
|
* the params.
|
|
*
|
|
* @return void
|
|
* @see http://cakephp.lighthouseapp.com/projects/42648/tickets/68
|
|
*/
|
|
function testSettingTokenForRequestAction() {
|
|
$this->Controller->Security->startup($this->Controller);
|
|
$key = $this->Controller->request->params['_Token']['key'];
|
|
|
|
$this->Controller->params['requested'] = 1;
|
|
unset($this->Controller->request->params['_Token']);
|
|
|
|
$this->Controller->Security->startup($this->Controller);
|
|
$this->assertEqual($this->Controller->request->params['_Token']['key'], $key);
|
|
}
|
|
|
|
/**
|
|
* test that blackhole doesn't delete the _Token session key so repeat data submissions
|
|
* stay blackholed.
|
|
*
|
|
* @link http://cakephp.lighthouseapp.com/projects/42648/tickets/214
|
|
* @return void
|
|
*/
|
|
function testBlackHoleNotDeletingSessionInformation() {
|
|
$this->Controller->Security->startup($this->Controller);
|
|
|
|
$this->Controller->Security->blackHole($this->Controller, 'auth');
|
|
$this->assertTrue($this->Controller->Security->Session->check('_Token'), '_Token was deleted by blackHole %s');
|
|
}
|
|
|
|
/**
|
|
* test setting
|
|
*
|
|
* @return void
|
|
*/
|
|
function testCsrfSettings() {
|
|
$this->Security->validatePost = false;
|
|
$this->Security->csrfCheck = true;
|
|
$this->Security->csrfExpires = '+10 minutes';
|
|
$this->Security->startup($this->Controller);
|
|
|
|
$token = $this->Security->Session->read('_Token');
|
|
$this->assertEquals(count($token['csrfTokens']), 1, 'Missing the csrf token.');
|
|
$this->assertEquals(strtotime('+10 minutes'), current($token['csrfTokens']), 'Token expiry does not match');
|
|
}
|
|
|
|
/**
|
|
* Test setting multiple nonces, when startup() is called more than once, (ie more than one request.)
|
|
*
|
|
* @return void
|
|
*/
|
|
function testCsrfSettingMultipleNonces() {
|
|
$this->Security->validatePost = false;
|
|
$this->Security->csrfCheck = true;
|
|
$this->Security->csrfExpires = '+10 minutes';
|
|
$this->Security->startup($this->Controller);
|
|
$this->Security->startup($this->Controller);
|
|
|
|
$token = $this->Security->Session->read('_Token');
|
|
$this->assertEquals(count($token['csrfTokens']), 2, 'Missing the csrf token.');
|
|
foreach ($token['csrfTokens'] as $key => $expires) {
|
|
$this->assertEquals(strtotime('+10 minutes'), $expires, 'Token expiry does not match');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* test that nonces are consumed by form submits.
|
|
*
|
|
* @return void
|
|
*/
|
|
function testCsrfNonceConsumption() {
|
|
$this->Security->validatePost = false;
|
|
$this->Security->csrfCheck = true;
|
|
$this->Security->csrfExpires = '+10 minutes';
|
|
|
|
$this->Security->Session->write('_Token.csrfTokens', array('nonce1' => strtotime('+10 minutes')));
|
|
|
|
$this->Controller->request = $this->getMock('CakeRequest', array('is'));
|
|
$this->Controller->request->expects($this->once())->method('is')
|
|
->with('post')
|
|
->will($this->returnValue(true));
|
|
|
|
$this->Controller->request->params['action'] = 'index';
|
|
$this->Controller->request->data = array(
|
|
'_Token' => array(
|
|
'key' => 'nonce1'
|
|
),
|
|
'Post' => array(
|
|
'title' => 'Woot'
|
|
)
|
|
);
|
|
$this->Security->startup($this->Controller);
|
|
$token = $this->Security->Session->read('_Token');
|
|
$this->assertFalse(isset($token['csrfTokens']['nonce1']), 'Token was not consumed');
|
|
}
|
|
|
|
/**
|
|
* test that expired values in the csrfTokens are cleaned up.
|
|
*
|
|
* @return void
|
|
*/
|
|
function testCsrfNonceVacuum() {
|
|
$this->Security->validatePost = false;
|
|
$this->Security->csrfCheck = true;
|
|
$this->Security->csrfExpires = '+10 minutes';
|
|
|
|
$this->Security->Session->write('_Token.csrfTokens', array(
|
|
'valid' => strtotime('+30 minutes'),
|
|
'poof' => strtotime('-11 minutes'),
|
|
'dust' => strtotime('-20 minutes')
|
|
));
|
|
$this->Security->startup($this->Controller);
|
|
$tokens = $this->Security->Session->read('_Token.csrfTokens');
|
|
$this->assertEquals(2, count($tokens), 'Too many tokens left behind');
|
|
$this->assertNotEmpty('valid', $tokens, 'Valid token was removed.');
|
|
|
|
}
|
|
|
|
/**
|
|
* test that when the key is missing the request is blackHoled
|
|
*
|
|
* @return void
|
|
*/
|
|
function testCsrfBlackHoleOnKeyMismatch() {
|
|
$this->Security->validatePost = false;
|
|
$this->Security->csrfCheck = true;
|
|
$this->Security->csrfExpires = '+10 minutes';
|
|
|
|
$this->Security->Session->write('_Token.csrfTokens', array('nonce1' => strtotime('+10 minutes')));
|
|
|
|
$this->Controller->request = $this->getMock('CakeRequest', array('is'));
|
|
$this->Controller->request->expects($this->once())->method('is')
|
|
->with('post')
|
|
->will($this->returnValue(true));
|
|
|
|
$this->Controller->request->params['action'] = 'index';
|
|
$this->Controller->request->data = array(
|
|
'_Token' => array(
|
|
'key' => 'not the right value'
|
|
),
|
|
'Post' => array(
|
|
'title' => 'Woot'
|
|
)
|
|
);
|
|
$this->Security->startup($this->Controller);
|
|
$this->assertTrue($this->Controller->failed, 'fail() was not called.');
|
|
}
|
|
|
|
/**
|
|
* test that when the key is missing the request is blackHoled
|
|
*
|
|
* @return void
|
|
*/
|
|
function testCsrfBlackHoleOnExpiredKey() {
|
|
$this->Security->validatePost = false;
|
|
$this->Security->csrfCheck = true;
|
|
$this->Security->csrfExpires = '+10 minutes';
|
|
|
|
$this->Security->Session->write('_Token.csrfTokens', array('nonce1' => strtotime('-5 minutes')));
|
|
|
|
$this->Controller->request = $this->getMock('CakeRequest', array('is'));
|
|
$this->Controller->request->expects($this->once())->method('is')
|
|
->with('post')
|
|
->will($this->returnValue(true));
|
|
|
|
$this->Controller->request->params['action'] = 'index';
|
|
$this->Controller->request->data = array(
|
|
'_Token' => array(
|
|
'key' => 'nonce1'
|
|
),
|
|
'Post' => array(
|
|
'title' => 'Woot'
|
|
)
|
|
);
|
|
$this->Security->startup($this->Controller);
|
|
$this->assertTrue($this->Controller->failed, 'fail() was not called.');
|
|
}
|
|
|
|
/**
|
|
* test that csrfUseOnce = false works.
|
|
*
|
|
* @return void
|
|
*/
|
|
function testCsrfNotUseOnce() {
|
|
$this->Security->validatePost = false;
|
|
$this->Security->csrfCheck = true;
|
|
$this->Security->csrfUseOnce = false;
|
|
$this->Security->csrfExpires = '+10 minutes';
|
|
|
|
// Generate one token
|
|
$this->Security->startup($this->Controller);
|
|
$token = $this->Security->Session->read('_Token.csrfTokens');
|
|
$this->assertEquals(1, count($token), 'Should only be one token.');
|
|
|
|
$this->Security->startup($this->Controller);
|
|
$token2 = $this->Security->Session->read('_Token.csrfTokens');
|
|
$this->assertEquals(1, count($token2), 'Should only be one token.');
|
|
$this->assertEquals($token, $token2, 'Tokens should not be different.');
|
|
}
|
|
|
|
/**
|
|
* ensure that longer session tokens are not consumed
|
|
*
|
|
* @return void
|
|
*/
|
|
function testCsrfNotUseOnceValidationLeavingToken() {
|
|
$this->Security->validatePost = false;
|
|
$this->Security->csrfCheck = true;
|
|
$this->Security->csrfUseOnce = false;
|
|
$this->Security->csrfExpires = '+10 minutes';
|
|
|
|
$this->Security->Session->write('_Token.csrfTokens', array('nonce1' => strtotime('+10 minutes')));
|
|
|
|
$this->Controller->request = $this->getMock('CakeRequest', array('is'));
|
|
$this->Controller->request->expects($this->once())->method('is')
|
|
->with('post')
|
|
->will($this->returnValue(true));
|
|
|
|
$this->Controller->request->params['action'] = 'index';
|
|
$this->Controller->request->data = array(
|
|
'_Token' => array(
|
|
'key' => 'nonce1'
|
|
),
|
|
'Post' => array(
|
|
'title' => 'Woot'
|
|
)
|
|
);
|
|
$this->Security->startup($this->Controller);
|
|
$token = $this->Security->Session->read('_Token');
|
|
$this->assertTrue(isset($token['csrfTokens']['nonce1']), 'Token was consumed');
|
|
}
|
|
}
|