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