Use the form action URL in generated form hashes.

By including the URL in generated hash for secured forms we prevent
a class of abuse where a user uses one secured form to post into a
controller action the form was not originally intended for. These cross
action requests could potentially violate developer's mental model of
how SecurityComponent works and produce unexpected/undesirable outcomes.

Thanks to Kurita Takashi for pointing this issue out, and suggesting
a fix.
This commit is contained in:
mark_story 2014-04-25 22:05:58 -04:00
parent 4a24d6ea31
commit f23d811ff5
4 changed files with 61 additions and 25 deletions

View file

@ -117,6 +117,14 @@ class FormHelper extends AppHelper {
*/
protected $_domIdSuffixes = array();
/**
* The action attribute value of the last created form.
* Used to make form/request specific hashes for SecurityComponent.
*
* @var string
*/
protected $_lastAction = '';
/**
* Copies the validationErrors variable from the View object into this instance
*
@ -458,6 +466,7 @@ class FormHelper extends AppHelper {
$this->setEntity($model, true);
$this->_introspectModel($model, 'fields');
}
$this->_lastAction = $action;
return $this->Html->useTag('form', $action, $htmlAttributes) . $append;
}
@ -563,7 +572,13 @@ class FormHelper extends AppHelper {
$locked = implode(array_keys($locked), '|');
$unlocked = implode($unlockedFields, '|');
$fields = Security::hash(serialize($fields) . $unlocked . Configure::read('Security.salt'), 'sha1');
$hashParts = array(
$this->_lastAction,
serialize($fields),
$unlocked,
Configure::read('Security.salt')
);
$fields = Security::hash(implode('', $hashParts), 'sha1');
$out = $this->hidden('_Token.fields', array(
'value' => urlencode($fields . ':' . $locked),