-
Notifications
You must be signed in to change notification settings - Fork 144
/
update_com.woltlab.wcf_5.4_session_1_cookies.php
110 lines (96 loc) · 3.34 KB
/
update_com.woltlab.wcf_5.4_session_1_cookies.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
<?php
/**
* Sets the new session cookies.
*
* @author Tim Duesterhus
* @copyright 2001-2021 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
* @package WoltLabSuite\Core
*/
use wcf\system\application\ApplicationHandler;
use wcf\system\form\container\GroupFormElementContainer;
use wcf\system\form\element\LabelFormElement;
use wcf\system\form\FormDocument;
use wcf\system\request\RouteHandler;
use wcf\system\WCF;
use wcf\util\CryptoUtil;
use wcf\util\HeaderUtil;
// 1) Check whether the cookies are already in place.
$hasValidSessionCookie = false;
if (!empty($_COOKIE[COOKIE_PREFIX . "user_session"])) {
$cookieValue = CryptoUtil::getValueFromSignedString($_COOKIE[COOKIE_PREFIX . "user_session"]);
if ($cookieValue && \mb_strlen($cookieValue, '8bit') === 22) {
$sessionID = \bin2hex(\mb_substr($cookieValue, 1, 20, '8bit'));
if ($sessionID === WCF::getSession()->sessionID) {
$hasValidSessionCookie = true;
}
}
}
$hasValidXsrfToken = false;
if (!empty($_COOKIE['XSRF-TOKEN'])) {
if (CryptoUtil::validateSignedString($_COOKIE['XSRF-TOKEN'])) {
$hasValidXsrfToken = true;
}
}
if ($hasValidSessionCookie && $hasValidXsrfToken) {
// The process may continue;
return;
}
// 2) Set new session cookie.
HeaderUtil::setCookie(
"user_session",
CryptoUtil::createSignedString(
\pack(
'CA20C',
1,
\hex2bin(WCF::getSession()->sessionID),
0
)
)
);
// 3) Set new XSRF-TOKEN cookie.
$sameSite = $cookieDomain = '';
if (ApplicationHandler::getInstance()->isMultiDomainSetup()) {
// We need to specify the cookieDomain in a multi domain set-up, because
// otherwise no cookies are sent to subdomains.
$cookieDomain = HeaderUtil::getCookieDomain();
$cookieDomain = ($cookieDomain !== null ? '; domain=' . $cookieDomain : '');
} else {
// SameSite=strict is not supported in a multi domain set-up, because
// it breaks cross-application requests.
$sameSite = '; SameSite=strict';
}
do {
$bytes = \bin2hex(\random_bytes(16));
} while (\strpos(\base64_encode($bytes), '+') !== false);
$xsrfToken = CryptoUtil::createSignedString($bytes);
WCF::getSession()->register('__SECURITY_TOKEN', $xsrfToken);
\header(
'set-cookie: XSRF-TOKEN=' . \rawurlencode($xsrfToken) . '; path=/' . $cookieDomain . (RouteHandler::secureConnection() ? '; secure' : '') . $sameSite,
false
);
// 4) Adjust the SECURITY_TOKEN.
$container = new GroupFormElementContainer();
$container->setLabel('Set Cookies'); // TODO
$container->setDescription('Sets cookies');
$label = new LabelFormElement($container);
$label->setLabel('Set Cookies');
$label->setDescription(
<<<EOT
<script>(function() {
var oldToken = SECURITY_TOKEN;
SECURITY_TOKEN = encodeURIComponent("{$xsrfToken}");
var oldExecute = WCF.ACP.Package.Installation.prototype._executeStep;
WCF.ACP.Package.Installation.prototype._executeStep = function (step, node, additionalData) {
var request = this._proxy._ajaxRequest;
request.setOption('url', request.getOption('url').replace(oldToken, SECURITY_TOKEN));
return oldExecute.call(this, step, node, additionalData);
}
})();
</script>
EOT
);
$container->appendChild($label);
$document = new FormDocument("cookies_set");
$document->appendContainer($container);
return $document;