Skip to content

Commit

Permalink
Disable autocomplete on CSRF/Security token fields.
Browse files Browse the repository at this point in the history
New versions of Safari will overwrite these fields when a user uses the
back button. If one-time CSRF tokens are in use the request will be
blackholed.

Refs #10486
  • Loading branch information
markstory committed Apr 5, 2017
1 parent 01abf29 commit 5685c03
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 34 deletions.
95 changes: 62 additions & 33 deletions lib/Cake/Test/Case/View/Helper/FormHelperTest.php
Expand Up @@ -592,7 +592,7 @@ public function testCreateWithSecurity() {
'div' => array('style' => 'display:none;'),
array('input' => array('type' => 'hidden', 'name' => '_method', 'value' => 'POST')),
array('input' => array(
'type' => 'hidden', 'name' => 'data[_Token][key]', 'value' => 'testKey', 'id'
'type' => 'hidden', 'name' => 'data[_Token][key]', 'value' => 'testKey', 'id', 'autocomplete'
)),
'/div'
);
Expand Down Expand Up @@ -708,11 +708,13 @@ public function testFormSecurityFields() {
'type' => 'hidden', 'name' => 'data[_Token][fields]',
'value' => $hash, 'id' => 'preg:/TokenFields\d+/',
'form' => 'MyTestForm',
'autocomplete' => 'off',
)),
array('input' => array(
'type' => 'hidden', 'name' => 'data[_Token][unlocked]',
'value' => '', 'id' => 'preg:/TokenUnlocked\d+/',
'form' => 'MyTestForm',
'autocomplete' => 'off',
)),
'/div'
);
Expand Down Expand Up @@ -877,11 +879,13 @@ public function testFormSecurityMultipleFields() {
'div' => array('style' => 'display:none;'),
array('input' => array(
'type' => 'hidden', 'name' => 'data[_Token][fields]',
'value' => $hash, 'id' => 'preg:/TokenFields\d+/'
'value' => $hash, 'id' => 'preg:/TokenFields\d+/',
'autocomplete' => 'off',
)),
array('input' => array(
'type' => 'hidden', 'name' => 'data[_Token][unlocked]',
'value' => '', 'id' => 'preg:/TokenUnlocked\d+/'
'value' => '', 'id' => 'preg:/TokenUnlocked\d+/',
'autocomplete' => 'off',
)),
'/div'
);
Expand Down Expand Up @@ -924,11 +928,13 @@ public function testFormSecurityMultipleSubmitButtons() {
'div' => array('style' => 'display:none;'),
array('input' => array(
'type' => 'hidden', 'name' => 'data[_Token][fields]',
'value' => 'preg:/.+/', 'id' => 'preg:/TokenFields\d+/'
'value' => 'preg:/.+/', 'id' => 'preg:/TokenFields\d+/',
'autocomplete' => 'off',
)),
array('input' => array(
'type' => 'hidden', 'name' => 'data[_Token][unlocked]',
'value' => 'cancel%7Csave', 'id' => 'preg:/TokenUnlocked\d+/'
'value' => 'cancel%7Csave', 'id' => 'preg:/TokenUnlocked\d+/',
'autocomplete' => 'off',
)),
'/div'
);
Expand Down Expand Up @@ -1044,11 +1050,13 @@ public function testFormSecurityMultipleInputFields() {
'div' => array('style' => 'display:none;'),
array('input' => array(
'type' => 'hidden', 'name' => 'data[_Token][fields]',
'value' => $hash, 'id' => 'preg:/TokenFields\d+/'
'value' => $hash, 'id' => 'preg:/TokenFields\d+/',
'autocomplete' => 'off',
)),
array('input' => array(
'type' => 'hidden', 'name' => 'data[_Token][unlocked]',
'value' => '', 'id' => 'preg:/TokenUnlocked\d+/'
'value' => '', 'id' => 'preg:/TokenUnlocked\d+/',
'autocomplete' => 'off',
)),
'/div'
);
Expand Down Expand Up @@ -1108,12 +1116,18 @@ public function testFormSecurityMultipleInputDisabledFields() {
$expected = array(
'div' => array('style' => 'display:none;'),
array('input' => array(
'type' => 'hidden', 'name' => 'data[_Token][fields]',
'value' => $hash, 'id' => 'preg:/TokenFields\d+/'
'type' => 'hidden', 'name' =>
'data[_Token][fields]',
'value' => $hash,
'id' => 'preg:/TokenFields\d+/',
'autocomplete' => 'off'
)),
array('input' => array(
'type' => 'hidden', 'name' => 'data[_Token][unlocked]',
'value' => 'address%7Cfirst_name', 'id' => 'preg:/TokenUnlocked\d+/'
'type' => 'hidden',
'name' => 'data[_Token][unlocked]',
'value' => 'address%7Cfirst_name',
'id' => 'preg:/TokenUnlocked\d+/',
'autocomplete' => 'off'
)),
'/div'
);
Expand Down Expand Up @@ -1157,12 +1171,18 @@ public function testFormSecurityInputUnlockedFields() {
$expected = array(
'div' => array('style' => 'display:none;'),
array('input' => array(
'type' => 'hidden', 'name' => 'data[_Token][fields]',
'value' => $hash, 'id' => 'preg:/TokenFields\d+/'
'type' => 'hidden',
'name' => 'data[_Token][fields]',
'value' => $hash,
'id' => 'preg:/TokenFields\d+/',
'autocomplete' => 'off',
)),
array('input' => array(
'type' => 'hidden', 'name' => 'data[_Token][unlocked]',
'value' => 'address%7Cfirst_name', 'id' => 'preg:/TokenUnlocked\d+/'
'type' => 'hidden',
'name' => 'data[_Token][unlocked]',
'value' => 'address%7Cfirst_name',
'id' => 'preg:/TokenUnlocked\d+/',
'autocomplete' => 'off',
)),
'/div'
);
Expand Down Expand Up @@ -1201,8 +1221,11 @@ public function testFormSecuredInput() {
'div' => array('style' => 'display:none;'),
array('input' => array('type' => 'hidden', 'name' => '_method', 'value' => 'POST')),
array('input' => array(
'type' => 'hidden', 'name' => 'data[_Token][key]',
'value' => 'testKey', 'id' => 'preg:/Token\d+/'
'type' => 'hidden',
'name' => 'data[_Token][key]',
'value' => 'testKey',
'id' => 'preg:/Token\d+/',
'autocomplete' => 'off',
)),
'/div'
);
Expand Down Expand Up @@ -1282,12 +1305,18 @@ public function testFormSecuredInput() {
$expected = array(
'div' => array('style' => 'display:none;'),
array('input' => array(
'type' => 'hidden', 'name' => 'data[_Token][fields]',
'value' => $hash, 'id' => 'preg:/TokenFields\d+/'
'type' => 'hidden',
'name' => 'data[_Token][fields]',
'value' => $hash,
'id' => 'preg:/TokenFields\d+/',
'autocomplete' => 'off',
)),
array('input' => array(
'type' => 'hidden', 'name' => 'data[_Token][unlocked]',
'value' => '', 'id' => 'preg:/TokenUnlocked\d+/'
'type' => 'hidden',
'name' => 'data[_Token][unlocked]',
'value' => '',
'id' => 'preg:/TokenUnlocked\d+/',
'autocomplete' => 'off',
)),
'/div'
);
Expand Down Expand Up @@ -8143,14 +8172,14 @@ public function testSecurePostButton() {
),
array('div' => array('style' => 'display:none;')),
array('input' => array('type' => 'hidden', 'name' => '_method', 'value' => 'POST')),
array('input' => array('type' => 'hidden', 'name' => 'data[_Token][key]', 'value' => 'testkey', 'id' => 'preg:/Token\d+/')),
array('input' => array('type' => 'hidden', 'name' => 'data[_Token][key]', 'value' => 'testkey', 'id' => 'preg:/Token\d+/', 'autocomplete')),
'/div',
'button' => array('type' => 'submit'),
'Delete',
'/button',
array('div' => array('style' => 'display:none;')),
array('input' => array('type' => 'hidden', 'name' => 'data[_Token][fields]', 'value' => 'preg:/[\w\d%]+/', 'id' => 'preg:/TokenFields\d+/')),
array('input' => array('type' => 'hidden', 'name' => 'data[_Token][unlocked]', 'value' => '', 'id' => 'preg:/TokenUnlocked\d+/')),
array('input' => array('type' => 'hidden', 'name' => 'data[_Token][fields]', 'value' => 'preg:/[\w\d%]+/', 'id' => 'preg:/TokenFields\d+/', 'autocomplete')),
array('input' => array('type' => 'hidden', 'name' => 'data[_Token][unlocked]', 'value' => '', 'id' => 'preg:/TokenUnlocked\d+/', 'autocomplete')),
'/div',
'/form',
);
Expand Down Expand Up @@ -8271,10 +8300,10 @@ public function testPostLinkSecurityHash() {
'name', 'id', 'style' => 'display:none;'
),
array('input' => array('type' => 'hidden', 'name' => '_method', 'value' => 'POST')),
array('input' => array('type' => 'hidden', 'name' => 'data[_Token][key]', 'value' => 'test', 'id')),
array('input' => array('type' => 'hidden', 'name' => 'data[_Token][key]', 'value' => 'test', 'id', 'autocomplete')),
'div' => array('style' => 'display:none;'),
array('input' => array('type' => 'hidden', 'name' => 'data[_Token][fields]', 'value' => $hash, 'id')),
array('input' => array('type' => 'hidden', 'name' => 'data[_Token][unlocked]', 'value' => '', 'id')),
array('input' => array('type' => 'hidden', 'name' => 'data[_Token][fields]', 'value' => $hash, 'id', 'autocomplete')),
array('input' => array('type' => 'hidden', 'name' => 'data[_Token][unlocked]', 'value' => '', 'id', 'autocomplete')),
'/div',
'/form',
'a' => array('href' => '#', 'onclick' => 'preg:/document\.post_\w+\.submit\(\); event\.returnValue = false; return false;/'),
Expand Down Expand Up @@ -8353,10 +8382,10 @@ public function testPostLinkAfterGetForm() {
'name' => 'preg:/post_\w+/', 'id' => 'preg:/post_\w+/', 'style' => 'display:none;'
),
array('input' => array('type' => 'hidden', 'name' => '_method', 'value' => 'POST')),
array('input' => array('type' => 'hidden', 'name' => 'data[_Token][key]', 'value' => 'testkey', 'id' => 'preg:/Token\d+/')),
array('input' => array('type' => 'hidden', 'name' => 'data[_Token][key]', 'value' => 'testkey', 'id' => 'preg:/Token\d+/', 'autocomplete' => 'off')),
'div' => array('style' => 'display:none;'),
array('input' => array('type' => 'hidden', 'name' => 'data[_Token][fields]', 'value' => 'preg:/[\w\d%]+/', 'id' => 'preg:/TokenFields\d+/')),
array('input' => array('type' => 'hidden', 'name' => 'data[_Token][unlocked]', 'value' => '', 'id' => 'preg:/TokenUnlocked\d+/')),
array('input' => array('type' => 'hidden', 'name' => 'data[_Token][fields]', 'value' => 'preg:/[\w\d%]+/', 'id' => 'preg:/TokenFields\d+/', 'autocomplete')),
array('input' => array('type' => 'hidden', 'name' => 'data[_Token][unlocked]', 'value' => '', 'id' => 'preg:/TokenUnlocked\d+/', 'autocomplete')),
'/div',
'/form',
'a' => array('href' => '#', 'onclick' => 'preg:/document\.post_\w+\.submit\(\); event\.returnValue = false; return false;/'),
Expand All @@ -8380,10 +8409,10 @@ public function testSecurePostLink() {
'name' => 'preg:/post_\w+/', 'id' => 'preg:/post_\w+/', 'style' => 'display:none;'
),
array('input' => array('type' => 'hidden', 'name' => '_method', 'value' => 'POST')),
array('input' => array('type' => 'hidden', 'name' => 'data[_Token][key]', 'value' => 'testkey', 'id' => 'preg:/Token\d+/')),
array('input' => array('type' => 'hidden', 'name' => 'data[_Token][key]', 'value' => 'testkey', 'id' => 'preg:/Token\d+/', 'autocomplete' => 'off')),
'div' => array('style' => 'display:none;'),
array('input' => array('type' => 'hidden', 'name' => 'data[_Token][fields]', 'value' => 'preg:/[\w\d%]+/', 'id' => 'preg:/TokenFields\d+/')),
array('input' => array('type' => 'hidden', 'name' => 'data[_Token][unlocked]', 'value' => '', 'id' => 'preg:/TokenUnlocked\d+/')),
array('input' => array('type' => 'hidden', 'name' => 'data[_Token][fields]', 'value' => 'preg:/[\w\d%]+/', 'id' => 'preg:/TokenFields\d+/', 'autocomplete')),
array('input' => array('type' => 'hidden', 'name' => 'data[_Token][unlocked]', 'value' => '', 'id' => 'preg:/TokenUnlocked\d+/', 'autocomplete')),
'/div',
'/form',
'a' => array('href' => '#', 'onclick' => 'preg:/document\.post_\w+\.submit\(\); event\.returnValue = false; return false;/'),
Expand Down
5 changes: 4 additions & 1 deletion lib/Cake/View/Helper/FormHelper.php
Expand Up @@ -504,7 +504,8 @@ protected function _csrfField() {
}
return $this->hidden('_Token.key', array(
'value' => $this->request->params['_Token']['key'], 'id' => 'Token' . mt_rand(),
'secure' => static::SECURE_SKIP
'secure' => static::SECURE_SKIP,
'autocomplete' => 'off',
));
}

Expand Down Expand Up @@ -614,12 +615,14 @@ public function secure($fields = array(), $secureAttributes = array()) {
'value' => urlencode($fields . ':' . $locked),
'id' => 'TokenFields' . mt_rand(),
'secure' => static::SECURE_SKIP,
'autocomplete' => 'off',
));
$out = $this->hidden('_Token.fields', $tokenFields);
$tokenUnlocked = array_merge($secureAttributes, array(
'value' => urlencode($unlocked),
'id' => 'TokenUnlocked' . mt_rand(),
'secure' => static::SECURE_SKIP,
'autocomplete' => 'off',
));
$out .= $this->hidden('_Token.unlocked', $tokenUnlocked);
return $this->Html->useTag('hiddenblock', $out);
Expand Down

0 comments on commit 5685c03

Please sign in to comment.