Skip to content

Commit c8bdac6

Browse files
authored
Merge pull request #459 from lakshya-webkul/gli-1046
Security update: Allow admin user to configure the SameSite cookie attribute
2 parents 73843a8 + b66151a commit c8bdac6

File tree

4 files changed

+70
-7
lines changed

4 files changed

+70
-7
lines changed

Diff for: classes/Cookie.php

+49-5
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,25 @@
2626

2727
class CookieCore
2828
{
29+
const SAMESITE_NONE = 'None';
30+
const SAMESITE_LAX = 'Lax';
31+
const SAMESITE_STRICT = 'Strict';
32+
33+
const SAMESITE_AVAILABLE_VALUES = array(
34+
array(
35+
"type" => self::SAMESITE_NONE,
36+
"name" => self::SAMESITE_NONE
37+
),
38+
array(
39+
"type" => self::SAMESITE_LAX,
40+
"name" => self::SAMESITE_LAX
41+
),
42+
array(
43+
"type" => self::SAMESITE_STRICT,
44+
"name" => self::SAMESITE_STRICT
45+
),
46+
);
47+
2948
/** @var array Contain cookie content in a key => value format */
3049
protected $_content;
3150

@@ -73,6 +92,7 @@ public function __construct($name, $path = '', $expire = null, $shared_urls = nu
7392
$this->_path = str_replace('%2F', '/', $this->_path);
7493
$this->_path = str_replace('%7E', '~', $this->_path);
7594
$this->_domain = $this->getDomain($shared_urls);
95+
$this->_sameSite = Configuration::get('PS_COOKIE_SAMESITE');
7696
$this->_name = 'PrestaShop-'.md5(($this->_standalone ? '' : _PS_VERSION_).$name.$this->_domain);
7797
$this->_allow_writing = true;
7898
$this->_salt = $this->_standalone ? str_pad('', 8, md5('ps'.__FILE__)) : _COOKIE_IV_;
@@ -82,7 +102,7 @@ public function __construct($name, $path = '', $expire = null, $shared_urls = nu
82102
} else {
83103
$this->_cipherTool = new PhpEncryption(_NEW_COOKIE_KEY_);
84104
}
85-
105+
86106
$this->_secure = (bool)$secure;
87107

88108
$this->update();
@@ -342,11 +362,35 @@ protected function _setcookie($cookie = null)
342362
$content = 0;
343363
$time = 1;
344364
}
345-
if (PHP_VERSION_ID <= 50200) { /* PHP version > 5.2.0 */
346-
return setcookie($this->_name, $content, $time, $this->_path, $this->_domain, $this->_secure);
347-
} else {
348-
return setcookie($this->_name, $content, $time, $this->_path, $this->_domain, $this->_secure, true);
365+
366+
/*
367+
* The alternative signature supporting an options array is only available since
368+
* PHP 7.3.0, before there is no support for SameSite attribute.
369+
*/
370+
if (PHP_VERSION_ID < 70300) {
371+
return setcookie(
372+
$this->_name,
373+
$content,
374+
$time,
375+
$this->_path,
376+
$this->_domain . '; SameSite=' . $this->_sameSite,
377+
$this->_secure,
378+
true
379+
);
349380
}
381+
382+
return setcookie(
383+
$this->_name,
384+
$content,
385+
[
386+
'expires' => $time,
387+
'path' => $this->_path,
388+
'domain' => $this->_domain,
389+
'secure' => $this->_secure,
390+
'httponly' => true,
391+
'samesite' => $this->_sameSite,
392+
]
393+
);
350394
}
351395

352396
public function __destruct()

Diff for: config/config.inc.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -161,10 +161,10 @@
161161
$cookie_lifetime = time() + (max($cookie_lifetime, 1) * 3600);
162162
}
163163

164+
$force_ssl = Configuration::get('PS_SSL_ENABLED') && Configuration::get('PS_SSL_ENABLED_EVERYWHERE');
164165
if (defined('_PS_ADMIN_DIR_')) {
165-
$cookie = new Cookie('psAdmin', '', $cookie_lifetime);
166+
$cookie = new Cookie('psAdmin', '', $cookie_lifetime, null, false, $force_ssl);
166167
} else {
167-
$force_ssl = Configuration::get('PS_SSL_ENABLED') && Configuration::get('PS_SSL_ENABLED_EVERYWHERE');
168168
if ($context->shop->getGroup()->share_order) {
169169
$cookie = new Cookie('ps-sg'.$context->shop->getGroup()->id, '', $cookie_lifetime, $context->shop->getUrlsSharedCart(), false, $force_ssl);
170170
} else {

Diff for: controllers/admin/AdminAdminPreferencesController.php

+16
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,16 @@ public function __construct()
8585
'default' => '480',
8686
'visibility' => Shop::CONTEXT_ALL
8787
),
88+
'PS_COOKIE_SAMESITE' => array(
89+
'title' => $this->l('Same site cookie'),
90+
'hint' => $this->l('Allows you to declare if your cookie should be restricted to a first-party or same-site context.'),
91+
'validation' => 'isGenericName',
92+
'type' => 'select',
93+
'cast' => 'strval',
94+
'identifier' => 'type',
95+
'list' => CookieCore::SAMESITE_AVAILABLE_VALUES,
96+
'visibility' => Shop::CONTEXT_ALL
97+
),
8898
),
8999
'submit' => array('title' => $this->l('Save'))
90100
),
@@ -159,6 +169,12 @@ public function postProcess()
159169
$upload_max_size = (int)str_replace('M', '', ini_get('upload_max_filesize'));
160170
$post_max_size = (int)str_replace('M', '', ini_get('post_max_size'));
161171
$max_size = $upload_max_size < $post_max_size ? $upload_max_size : $post_max_size;
172+
$forceSsl = Configuration::get('PS_SSL_ENABLED') && Configuration::get('PS_SSL_ENABLED_EVERYWHERE');
173+
174+
if (!$forceSsl && Tools::getValue('PS_COOKIE_SAMESITE') === Cookie::SAMESITE_NONE) {
175+
$this->errors[] = Tools::displayError('The SameSite=None is only available in secure mode.');
176+
return;
177+
}
162178

163179
if (Tools::getValue('PS_LIMIT_UPLOAD_FILE_VALUE') > $max_size || Tools::getValue('PS_LIMIT_UPLOAD_IMAGE_VALUE') > $max_size) {
164180
$this->errors[] = Tools::displayError('The limit chosen is larger than the server\'s maximum upload limit. Please increase the limits of your server.');

Diff for: install/data/xml/configuration.xml

+3
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,9 @@
446446
<configuration id="PS_COOKIE_LIFETIME_BO" name="PS_COOKIE_LIFETIME_BO">
447447
<value>480</value>
448448
</configuration>
449+
<configuration id="PS_COOKIE_SAMESITE" name="PS_COOKIE_SAMESITE">
450+
<value>Lax</value>
451+
</configuration>
449452
<configuration id="PS_RESTRICT_DELIVERED_COUNTRIES" name="PS_RESTRICT_DELIVERED_COUNTRIES">
450453
<value>0</value>
451454
</configuration>

0 commit comments

Comments
 (0)