-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathfetchmetadata.php
88 lines (76 loc) · 2.02 KB
/
fetchmetadata.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
<?php
/**
* FetchMetadata Plugin
*
* @copyright Copyright (C) 2020 Tobias Zulauf All rights reserved.
* @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License Version 2 or Later
*/
defined('_JEXEC') or die;
use Joomla\CMS\Application\CMSApplication;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Plugin\CMSPlugin;
use Joomla\CMS\Response\JsonResponse;
/**
* Plugin class for Fetch Metadata
*
* @since 1.0
*/
class PlgSystemFetchMetadata extends CMSPlugin
{
/**
* Application object.
*
* @var CMSApplication
* @since 1.0
*/
protected $app;
/**
* Reject cross-origin requests to protect from CSRF, XSSI, and other bugs
*
* @return void
*
* @since 1.0
*/
public function onAfterInitialise()
{
$headers = array_change_key_case(getallheaders(), CASE_LOWER);
// Allow requests from browsers which don't send Fetch Metadata
if (!isset($headers['sec-fetch-site']))
{
return;
}
// Allow same-site and browser initiated requests
if (in_array($headers['sec-fetch-site'], ['same-origin', 'same-site', 'none']))
{
return;
}
// Allow simple top-level navigation from anywhere, <object> and <embed> send navigation requests, which we disallow.
if ($headers['sec-fetch-mode'] === 'navigate'
&& $this->app->input->server->get('REQUEST_METHOD', '', 'cmd') === 'GET'
&& !in_array($headers['sec-fetch-dest'], ['object', 'embed']))
{
return;
}
// Opt out endpoints that are meant to serve cross-site traffic (Optional)
$requestUri = $this->app->input->server->get('REQUEST_URI', '', 'string');
foreach ($this->params->get('cors_endpoints', []) as $corsEndpoint)
{
if (empty($corsEndpoint->rule))
{
continue;
}
if (preg_match($corsEndpoint->rule, $requestUri))
{
return;
}
if ($requestUri === $corsEndpoint->rule)
{
return;
}
}
// Reject all other requests that are cross-site and not navigational
$this->app->enqueueMessage(Text::_('JINVALID_TOKEN'), 'error');
echo new JsonResponse;
$this->app->close();
}
}