Merge pull request #264 from caffeineinc/bugfix-3.1/xss-session-cookies

Prevent storing formdata to cookies.
This commit is contained in:
Robbie Averill 2018-09-24 18:07:07 +02:00 committed by GitHub
commit 9f9dc67950
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -2,7 +2,11 @@
namespace SilverStripe\Comments\Forms; namespace SilverStripe\Comments\Forms;
use SilverStripe\Comments\Controllers\CommentingController;
use SilverStripe\Comments\Model\Comment;
use SilverStripe\Control\Controller;
use SilverStripe\Control\HTTPResponse; use SilverStripe\Control\HTTPResponse;
use SilverStripe\Core\Convert;
use SilverStripe\Forms\CompositeField; use SilverStripe\Forms\CompositeField;
use SilverStripe\Forms\EmailField; use SilverStripe\Forms\EmailField;
use SilverStripe\Forms\FieldList; use SilverStripe\Forms\FieldList;
@ -14,13 +18,7 @@ use SilverStripe\Forms\RequiredFields;
use SilverStripe\Forms\TextareaField; use SilverStripe\Forms\TextareaField;
use SilverStripe\Forms\TextField; use SilverStripe\Forms\TextField;
use SilverStripe\Security\Member; use SilverStripe\Security\Member;
use SilverStripe\Control\Cookie;
use SilverStripe\Core\Convert;
use SilverStripe\Security\Security; use SilverStripe\Security\Security;
use SilverStripe\Comments\Model\Comment;
use SilverStripe\Control\Controller;
use SilverStripe\Comments\Controllers\CommentingController;
use SilverStripe\Core\Config\Config;
class CommentForm extends Form class CommentForm extends Form
{ {
@ -122,31 +120,39 @@ class CommentForm extends Form
// we do not want to read a new URL when the form has already been submitted // we do not want to read a new URL when the form has already been submitted
// which in here, it hasn't been. // which in here, it hasn't been.
$this->loadDataFrom(array( $this->loadDataFrom([
'ParentID' => $record->ID, 'ParentID' => $record->ID,
'ReturnURL' => $controller->getRequest()->getURL(), 'ReturnURL' => $controller->getRequest()->getURL(),
'ParentClassName' => $controller->getParentClass() 'ParentClassName' => $controller->getParentClass()
)); ]);
} }
// Set it so the user gets redirected back down to the form upon form fail // Set it so the user gets redirected back down to the form upon form fail
$this->setRedirectToFormOnValidationError(true); $this->setRedirectToFormOnValidationError(true);
// load any data from the cookies // load any data from the session
if ($data = Cookie::get('CommentsForm_UserData')) { $data = $this->getSessionData();
$data = Convert::json2array($data); if (!is_array($data)) {
return;
}
$this->loadDataFrom(array( // load user data from previous form request back into form.
'Name' => isset($data['Name']) ? $data['Name'] : '', if (array_key_exists('UserData', $data)) {
'URL' => isset($data['URL']) ? $data['URL'] : '', $formData = Convert::json2array($data['UserData']);
'Email' => isset($data['Email']) ? $data['Email'] : ''
));
// allow previous value to fill if comment not stored in cookie (i.e. validation error) $this->loadDataFrom([
$prevComment = Cookie::get('CommentsForm_Comment'); 'Name' => isset($formData['Name']) ? $formData['Name'] : '',
'URL' => isset($formData['URL']) ? $formData['URL'] : '',
'Email' => isset($formData['Email']) ? $formData['Email'] : ''
]);
}
// allow previous value to fill if comment
if (array_key_exists('Comment', $data)) {
$prevComment = $data['Comment'];
if ($prevComment && $prevComment != '') { if ($prevComment && $prevComment != '') {
$this->loadDataFrom(array('Comment' => $prevComment)); $this->loadDataFrom(['Comment' => $prevComment]);
} }
} }
} }
@ -184,8 +190,10 @@ class CommentForm extends Form
} }
// cache users data // cache users data
Cookie::set('CommentsForm_UserData', Convert::raw2json($data)); $form->setSessionData([
Cookie::set('CommentsForm_Comment', $data['Comment']); 'UserData' => Convert::raw2json($data),
'Comment' => $data['Comment']
]);
// extend hook to allow extensions. Also see onAfterPostComment // extend hook to allow extensions. Also see onAfterPostComment
$this->controller->extend('onBeforePostComment', $form); $this->controller->extend('onBeforePostComment', $form);
@ -246,8 +254,16 @@ class CommentForm extends Form
$this->getRequest()->getSession()->set('CommentsModerated', 1); $this->getRequest()->getSession()->set('CommentsModerated', 1);
} }
// clear the users comment since it passed validation // clear the users comment since the comment was successful.
Cookie::set('CommentsForm_Comment', false); if ($comment->exists()) {
// Remove the comment data as it's been saved already.
unset($data['Comment']);
}
// cache users data (name, email, etc to prepopulate on other forms).
$form->setSessionData([
'UserData' => Convert::raw2json($data),
]);
// Find parent link // Find parent link
if (!empty($data['ReturnURL'])) { if (!empty($data['ReturnURL'])) {