mirror of
https://github.com/getgrav/grav.git
synced 2026-03-01 18:11:25 +01:00
Merge branch 'release/1.6.29'
This commit is contained in:
@@ -27,6 +27,9 @@ RewriteEngine On
|
||||
# If you experience problems on your site block out the operations listed below
|
||||
# This attempts to block the most common type of exploit `attempts` to Grav
|
||||
#
|
||||
# Block out any script trying to use twig tags in URL.
|
||||
RewriteCond %{REQUEST_URI} ({{|}}|{%|%}) [OR]
|
||||
RewriteCond %{QUERY_STRING} ({{|}}|{%25|%25}) [OR]
|
||||
# Block out any script trying to base64_encode data within the URL.
|
||||
RewriteCond %{QUERY_STRING} base64_encode[^(]*\([^)]*\) [OR]
|
||||
# Block out any script that includes a <script> tag in URL.
|
||||
|
||||
23
CHANGELOG.md
23
CHANGELOG.md
@@ -1,3 +1,26 @@
|
||||
# v1.6.29
|
||||
## 12/02/2020
|
||||
|
||||
1. [](#new)
|
||||
* Added basic support for `user/config/versions.yaml`
|
||||
1. [](#improved)
|
||||
* Updated bundled JQuery to latest version `3.5.1`
|
||||
* Forward a `sid` to GPM when downloading a premium package via CLI
|
||||
* Better handling of missing repository index [grav-plugin-admin#1916](https://github.com/getgrav/grav-plugin-admin/issues/1916)
|
||||
* Set `grav_cli` as referrer when using `Response` from CLI
|
||||
* Add option for timeout in `self-upgrade` command [#3013](https://github.com/getgrav/grav/pull/3013)
|
||||
* Allow to set SameSite from system.yaml [#3063](https://github.com/getgrav/grav/pull/3063)
|
||||
* Update media.yaml with some MS Office mimetypes [#3070](https://github.com/getgrav/grav/pull/3070)
|
||||
1. [](#bugfix)
|
||||
* Fixed hardcoded system folder in blueprints, config and language streams
|
||||
* Added `.htaccess` rule to block attempts to use Twig in the request URL
|
||||
* Fix compatibility with Symfony 4.2 and up. [#3048](https://github.com/getgrav/grav/pull/3048)
|
||||
* Fix failing example custom shceduled job. [#3050](https://github.com/getgrav/grav/pull/3050)
|
||||
* Fix for XSS advisory [GHSA-cvmr-6428-87w9](https://github.com/getgrav/grav/security/advisories/GHSA-cvmr-6428-87w9)
|
||||
* Fix uploads_dangerous_extensions checking [#3060](https://github.com/getgrav/grav/pull/3060)
|
||||
* Remove redundant prefixing of `.` to extension [#3060](https://github.com/getgrav/grav/pull/3060)
|
||||
* Check exact extension in checkFilename utility [#3061](https://github.com/getgrav/grav/pull/3061)
|
||||
|
||||
# v1.6.28
|
||||
## 10/07/2020
|
||||
|
||||
|
||||
15
SECURITY.md
Normal file
15
SECURITY.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
We are focusing our security updates on the following versions
|
||||
|
||||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
| 1.7.x | :white_check_mark: |
|
||||
| 1.6.x | :white_check_mark: |
|
||||
| < 1.6 | :x: |
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
Please contact contact@getgrav.org with a detailed explaination of the security issue found and we will work with you to get it resolved as fast as possible.
|
||||
@@ -50,7 +50,7 @@
|
||||
"composer/ca-bundle": "^1.0",
|
||||
"dragonmantank/cron-expression": "^1.2",
|
||||
"phive/twig-extensions-deferred": "^1.0",
|
||||
"willdurand/negotiation": "2.x-dev"
|
||||
"willdurand/negotiation": "^3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"codeception/codeception": "^2.4",
|
||||
|
||||
460
composer.lock
generated
460
composer.lock
generated
File diff suppressed because it is too large
Load Diff
4
system/assets/jquery/jquery-3.x.min.js
vendored
4
system/assets/jquery/jquery-3.x.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -39,12 +39,13 @@ form:
|
||||
.command:
|
||||
type: text
|
||||
label: PLUGIN_ADMIN.COMMAND
|
||||
placeholder: 'cd ~;ls -lah;'
|
||||
placeholder: 'ls'
|
||||
validate:
|
||||
required: true
|
||||
.args:
|
||||
type: text
|
||||
label: PLUGIN_ADMIN.EXTRA_ARGUMENTS
|
||||
placeholder: '-lah'
|
||||
.at:
|
||||
type: cron
|
||||
label: PLUGIN_ADMIN.SCHEDULER_RUNAT
|
||||
|
||||
@@ -1223,6 +1223,12 @@ form:
|
||||
label: PLUGIN_ADMIN.SESSION_PATH
|
||||
help: PLUGIN_ADMIN.SESSION_PATH_HELP
|
||||
|
||||
session.samesite:
|
||||
type: text
|
||||
size: small
|
||||
label: PLUGIN_ADMIN.SESSION_SAMESITE
|
||||
help: PLUGIN_ADMIN.SESSION_SAMESITE_HELP
|
||||
|
||||
session.split:
|
||||
type: toggle
|
||||
label: PLUGIN_ADMIN.SESSION_SPLIT
|
||||
|
||||
@@ -103,7 +103,7 @@ types:
|
||||
docx:
|
||||
type: file
|
||||
thumb: media/thumb-docx.png
|
||||
mime: application/msword
|
||||
mime: application/vnd.openxmlformats-officedocument.wordprocessingml.document
|
||||
xls:
|
||||
type: file
|
||||
thumb: media/thumb-xls.png
|
||||
@@ -111,7 +111,7 @@ types:
|
||||
xlsx:
|
||||
type: file
|
||||
thumb: media/thumb-xlsx.png
|
||||
mime: application/vnd.ms-excel
|
||||
mime: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
|
||||
ppt:
|
||||
type: file
|
||||
thumb: media/thumb-ppt.png
|
||||
@@ -119,7 +119,7 @@ types:
|
||||
pptx:
|
||||
type: file
|
||||
thumb: media/thumb-pptx.png
|
||||
mime: application/vnd.ms-powerpoint
|
||||
mime: application/vnd.openxmlformats-officedocument.presentationml.presentation
|
||||
pps:
|
||||
type: file
|
||||
thumb: media/thumb-pps.png
|
||||
|
||||
@@ -161,6 +161,7 @@ session:
|
||||
uniqueness: path # Should sessions be `path` based or `security.salt` based
|
||||
secure: false # Set session secure. If true, indicates that communication for this cookie must be over an encrypted transmission. Enable this only on sites that run exclusively on HTTPS
|
||||
httponly: true # Set session HTTP only. If true, indicates that cookies should be used only over HTTP, and JavaScript modification is not allowed.
|
||||
samesite: # Set session SameSite. See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite
|
||||
split: true # Sessions should be independent between site and plugins (such as admin)
|
||||
path:
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
// Some standard defines
|
||||
define('GRAV', true);
|
||||
define('GRAV_VERSION', '1.6.28');
|
||||
define('GRAV_VERSION', '1.6.29');
|
||||
define('GRAV_TESTING', false);
|
||||
define('DS', '/');
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ class Backups
|
||||
public function getBackupDownloadUrl($backup, $base_url)
|
||||
{
|
||||
$param_sep = $param_sep = Grav::instance()['config']->get('system.param_sep', ':');
|
||||
$download = urlencode(base64_encode($backup));
|
||||
$download = urlencode(base64_encode(basename($backup)));
|
||||
$url = rtrim(Grav::instance()['uri']->rootUrl(true), '/') . '/' . trim($base_url,
|
||||
'/') . '/task' . $param_sep . 'backup/download' . $param_sep . $download . '/admin-nonce' . $param_sep . Utils::getNonce('admin-form');
|
||||
|
||||
|
||||
@@ -59,13 +59,13 @@ class Setup extends Data
|
||||
'blueprints' => [
|
||||
'type' => 'ReadOnlyStream',
|
||||
'prefixes' => [
|
||||
'' => ['environment://blueprints', 'user://blueprints', 'system/blueprints'],
|
||||
'' => ['environment://blueprints', 'user://blueprints', 'system://blueprints'],
|
||||
]
|
||||
],
|
||||
'config' => [
|
||||
'type' => 'ReadOnlyStream',
|
||||
'prefixes' => [
|
||||
'' => ['environment://config', 'user://config', 'system/config'],
|
||||
'' => ['environment://config', 'user://config', 'system://config'],
|
||||
]
|
||||
],
|
||||
'plugins' => [
|
||||
@@ -89,7 +89,7 @@ class Setup extends Data
|
||||
'languages' => [
|
||||
'type' => 'ReadOnlyStream',
|
||||
'prefixes' => [
|
||||
'' => ['environment://languages', 'user://languages', 'system/languages'],
|
||||
'' => ['environment://languages', 'user://languages', 'system://languages'],
|
||||
]
|
||||
],
|
||||
'cache' => [
|
||||
|
||||
@@ -233,6 +233,11 @@ class GPM extends Iterator
|
||||
public function getUpdatablePlugins()
|
||||
{
|
||||
$items = [];
|
||||
|
||||
if (!$this->repository) {
|
||||
return $items;
|
||||
}
|
||||
|
||||
$repository = $this->repository['plugins'];
|
||||
|
||||
// local cache to speed things up
|
||||
@@ -312,6 +317,11 @@ class GPM extends Iterator
|
||||
public function getUpdatableThemes()
|
||||
{
|
||||
$items = [];
|
||||
|
||||
if (!$this->repository) {
|
||||
return $items;
|
||||
}
|
||||
|
||||
$repository = $this->repository['themes'];
|
||||
|
||||
// local cache to speed things up
|
||||
@@ -359,6 +369,10 @@ class GPM extends Iterator
|
||||
*/
|
||||
public function getReleaseType($package_name)
|
||||
{
|
||||
if (!$this->repository) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$repository = $this->repository['plugins'];
|
||||
if (isset($repository[$package_name])) {
|
||||
return $repository[$package_name]->release_type;
|
||||
@@ -407,7 +421,7 @@ class GPM extends Iterator
|
||||
*/
|
||||
public function getRepositoryPlugin($slug)
|
||||
{
|
||||
return @$this->repository['plugins'][$slug];
|
||||
return $this->repository['plugins'][$slug] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -416,7 +430,7 @@ class GPM extends Iterator
|
||||
*/
|
||||
public function getRepositoryPlugins()
|
||||
{
|
||||
return $this->repository['plugins'];
|
||||
return $this->repository['plugins'] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -426,7 +440,7 @@ class GPM extends Iterator
|
||||
*/
|
||||
public function getRepositoryTheme($slug)
|
||||
{
|
||||
return @$this->repository['themes'][$slug];
|
||||
return $this->repository['themes'][$slug] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -435,7 +449,7 @@ class GPM extends Iterator
|
||||
*/
|
||||
public function getRepositoryThemes()
|
||||
{
|
||||
return $this->repository['themes'];
|
||||
return $this->repository['themes'] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -284,7 +284,8 @@ class Response
|
||||
$options['fopen']['notification'] = ['self', 'progress'];
|
||||
}
|
||||
|
||||
$options['fopen']['header'] = 'Referer: ' . Grav::instance()['uri']->rootUrl(true);
|
||||
$referer = \defined('GRAV_CLI') ? 'grav_cli' : Grav::instance()['uri']->rootUrl(true);
|
||||
$options['fopen']['header'] = 'Referer: ' . $referer;
|
||||
if (isset($options['fopen']['ssl'])) {
|
||||
$ssl = $options['fopen']['ssl'];
|
||||
unset($options['fopen']['ssl']);
|
||||
@@ -367,7 +368,8 @@ class Response
|
||||
*/
|
||||
private static function curlExecFollow($ch, $options, $callback)
|
||||
{
|
||||
curl_setopt_array($ch, [ CURLOPT_REFERER => Grav::instance()['uri']->rootUrl(true) ]);
|
||||
$referer = \defined('GRAV_CLI') ? 'grav_cli' : Grav::instance()['uri']->rootUrl(true);
|
||||
curl_setopt_array($ch, [ CURLOPT_REFERER => $referer ]);
|
||||
|
||||
if ($callback) {
|
||||
curl_setopt_array(
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
|
||||
namespace Grav\Common\Processors;
|
||||
|
||||
use Grav\Framework\File\Formatter\YamlFormatter;
|
||||
use Grav\Framework\File\YamlFile;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
@@ -21,8 +23,27 @@ class ConfigurationProcessor extends ProcessorBase
|
||||
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler) : ResponseInterface
|
||||
{
|
||||
$this->startTimer();
|
||||
$this->container['config']->init();
|
||||
$config = $this->container['config'];
|
||||
$config->init();
|
||||
$this->container['plugins']->setup();
|
||||
|
||||
if ($config->get('versions') === null) {
|
||||
$filename = GRAV_ROOT . '/user/config/versions.yaml';
|
||||
if (!is_file($filename)) {
|
||||
$versions = [
|
||||
'core' => [
|
||||
'grav' => [
|
||||
'version' => GRAV_VERSION,
|
||||
'history' => ['version' => GRAV_VERSION, 'date' => gmdate('Y-m-d H:i:s')]
|
||||
]
|
||||
]
|
||||
];
|
||||
$config->set('versions', $versions);
|
||||
|
||||
$file = new YamlFile($filename, new YamlFormatter(['inline' => 4]));
|
||||
$file->save($versions);
|
||||
}
|
||||
}
|
||||
$this->stopTimer();
|
||||
|
||||
return $handler->handle($request);
|
||||
|
||||
@@ -298,8 +298,8 @@ class Job
|
||||
if (is_callable($this->command)) {
|
||||
$this->output = $this->exec();
|
||||
} else {
|
||||
$args = \is_string($this->args) ? $this->args : implode(' ', $this->args);
|
||||
$command = $this->command . ' ' . $args;
|
||||
$args = \is_string($this->args) ? explode(' ', $this->args) : $this->args;
|
||||
$command = array_merge([$this->command], $args);
|
||||
$process = new Process($command);
|
||||
|
||||
$this->process = $process;
|
||||
|
||||
@@ -246,7 +246,7 @@ class Scheduler
|
||||
*/
|
||||
public function isCrontabSetup()
|
||||
{
|
||||
$process = new Process('crontab -l');
|
||||
$process = new Process(['crontab', '-l']);
|
||||
$process->run();
|
||||
|
||||
if ($process->isSuccessful()) {
|
||||
|
||||
@@ -133,7 +133,7 @@ class Security
|
||||
// Set the patterns we'll test against
|
||||
$patterns = [
|
||||
// Match any attribute starting with "on" or xmlns
|
||||
'on_events' => '#(<[^>]+[[a-z\x00-\x20\"\'\/])(\son|\sxmlns)[a-z].*=>?#iUu',
|
||||
'on_events' => '#(<[^>]+[[a-z\x00-\x20\"\'\/])([\s\/]on|\sxmlns)[a-z].*=>?#iUu',
|
||||
|
||||
// Match javascript:, livescript:, vbscript:, mocha:, feed: and data: protocols
|
||||
'invalid_protocols' => '#(' . implode('|', $invalid_protocols) . '):.*?#iUu',
|
||||
|
||||
@@ -36,6 +36,7 @@ class SessionServiceProvider implements ServiceProviderInterface
|
||||
$cookie_httponly = (bool)$config->get('system.session.httponly', true);
|
||||
$cookie_lifetime = (int)$config->get('system.session.timeout', 1800);
|
||||
$cookie_path = $config->get('system.session.path');
|
||||
$cookie_samesite = $config->get('system.session.samesite');
|
||||
if (null === $cookie_path) {
|
||||
$cookie_path = '/' . trim(Uri::filterPath($uri->rootUrl(false)), '/');
|
||||
}
|
||||
@@ -87,8 +88,14 @@ class SessionServiceProvider implements ServiceProviderInterface
|
||||
'cookie_path' => $cookie_path,
|
||||
'cookie_domain' => $cookie_domain,
|
||||
'cookie_secure' => $cookie_secure,
|
||||
'cookie_httponly' => $cookie_httponly
|
||||
] + (array) $config->get('system.session.options');
|
||||
'cookie_httponly' => $cookie_httponly,
|
||||
];
|
||||
|
||||
if ($cookie_samesite) {
|
||||
$options['cookie_samesite'] = $cookie_samesite;
|
||||
}
|
||||
|
||||
$options += (array) $config->get('system.session.options');
|
||||
|
||||
$session = new Session($options);
|
||||
$session->setAutoStart($enabled);
|
||||
|
||||
@@ -859,11 +859,7 @@ abstract class Utils
|
||||
public static function checkFilename($filename)
|
||||
{
|
||||
$dangerous_extensions = Grav::instance()['config']->get('security.uploads_dangerous_extensions', []);
|
||||
array_walk($dangerous_extensions, function(&$val) {
|
||||
$val = '.' . $val;
|
||||
});
|
||||
|
||||
$extension = '.' . pathinfo($filename, PATHINFO_EXTENSION);
|
||||
$extension = pathinfo($filename, PATHINFO_EXTENSION);
|
||||
|
||||
return !(
|
||||
// Empty filenames are not allowed.
|
||||
@@ -872,8 +868,8 @@ abstract class Utils
|
||||
|| strtr($filename, "\t\v\n\r\0\\/", '_______') !== $filename
|
||||
// Filename should not start or end with dot or space.
|
||||
|| trim($filename, '. ') !== $filename
|
||||
// Filename should not contain .php in it.
|
||||
|| static::contains($extension, $dangerous_extensions)
|
||||
// File extension should not be part of configured dangerous extensions
|
||||
|| in_array($extension, $dangerous_extensions)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -445,7 +445,7 @@ class InstallCommand extends ConsoleCommand
|
||||
} else {
|
||||
$repo_dir = $matches[2];
|
||||
}
|
||||
|
||||
|
||||
$paths = (array) $paths;
|
||||
foreach ($paths as $repo) {
|
||||
$path = rtrim($repo, '/') . '/' . $repo_dir;
|
||||
@@ -570,7 +570,8 @@ class InstallCommand extends ConsoleCommand
|
||||
[
|
||||
'slug' => $package->slug,
|
||||
'filename' => $package->premium['filename'],
|
||||
'license_key' => $license
|
||||
'license_key' => $license,
|
||||
'sid' => md5(GRAV_ROOT)
|
||||
]
|
||||
));
|
||||
|
||||
|
||||
@@ -46,6 +46,9 @@ class SelfupgradeCommand extends ConsoleCommand
|
||||
|
||||
protected $overwrite;
|
||||
|
||||
/** @var int */
|
||||
protected $timeout;
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
@@ -69,6 +72,13 @@ class SelfupgradeCommand extends ConsoleCommand
|
||||
InputOption::VALUE_NONE,
|
||||
'Option to overwrite packages if they already exist'
|
||||
)
|
||||
->addOption(
|
||||
'timeout',
|
||||
't',
|
||||
InputOption::VALUE_OPTIONAL,
|
||||
'Option to set the timeout in seconds when downloading the update (0 for no timeout)',
|
||||
30
|
||||
)
|
||||
->setDescription('Detects and performs an update of Grav itself when available')
|
||||
->setHelp('The <info>update</info> command updates Grav itself when a new version is available');
|
||||
}
|
||||
@@ -78,6 +88,7 @@ class SelfupgradeCommand extends ConsoleCommand
|
||||
$this->upgrader = new Upgrader($this->input->getOption('force'));
|
||||
$this->all_yes = $this->input->getOption('all-yes');
|
||||
$this->overwrite = $this->input->getOption('overwrite');
|
||||
$this->timeout = (int) $this->input->getOption('timeout');
|
||||
|
||||
$this->displayGPMRelease();
|
||||
|
||||
@@ -116,7 +127,6 @@ class SelfupgradeCommand extends ConsoleCommand
|
||||
|
||||
$questionHelper = $this->getHelper('question');
|
||||
|
||||
|
||||
$this->output->writeln("Grav v<cyan>{$remote}</cyan> is now available [release date: {$release}].");
|
||||
$this->output->writeln('You are currently using v<cyan>' . GRAV_VERSION . '</cyan>.');
|
||||
|
||||
@@ -185,7 +195,16 @@ class SelfupgradeCommand extends ConsoleCommand
|
||||
{
|
||||
$tmp_dir = Grav::instance()['locator']->findResource('tmp://', true, true);
|
||||
$this->tmp = $tmp_dir . '/Grav-' . uniqid('', false);
|
||||
$output = Response::get($package['download'], [], [$this, 'progress']);
|
||||
$options = [
|
||||
'curl' => [
|
||||
CURLOPT_TIMEOUT => $this->timeout,
|
||||
],
|
||||
'fopen' => [
|
||||
'timeout' => $this->timeout,
|
||||
],
|
||||
];
|
||||
|
||||
$output = Response::get($package['download'], $options, [$this, 'progress']);
|
||||
|
||||
Folder::create($this->tmp);
|
||||
|
||||
|
||||
@@ -63,9 +63,10 @@ trait ObjectCollectionTrait
|
||||
/**
|
||||
* @param string $property Object property to be fetched.
|
||||
* @param mixed $default Default value if not set.
|
||||
* @param bool $doCreate Not being used.
|
||||
* @return mixed[] Key/Value pairs of the properties.
|
||||
*/
|
||||
public function doGetProperty($property, $default = null)
|
||||
public function &doGetProperty($property, $default = null, $doCreate = false)
|
||||
{
|
||||
$list = [];
|
||||
|
||||
|
||||
@@ -135,6 +135,7 @@ class Session implements SessionInterface
|
||||
'use_strict_mode' => true,
|
||||
'use_cookies' => true,
|
||||
'use_only_cookies' => true,
|
||||
'cookie_samesite' => true,
|
||||
'referer_check' => true,
|
||||
'cache_limiter' => true,
|
||||
'cache_expire' => true,
|
||||
@@ -211,14 +212,19 @@ class Session implements SessionInterface
|
||||
if ($sessionExists) {
|
||||
$params = session_get_cookie_params();
|
||||
|
||||
$cookie_options = array (
|
||||
'expires' => time() + $params['lifetime'],
|
||||
'path' => $params['path'],
|
||||
'domain' => $params['domain'],
|
||||
'secure' => $params['secure'],
|
||||
'httponly' => $params['httponly'],
|
||||
'samesite' => $params['samesite']
|
||||
);
|
||||
|
||||
setcookie(
|
||||
$sessionName,
|
||||
session_id(),
|
||||
time() + $params['lifetime'],
|
||||
$params['path'],
|
||||
$params['domain'],
|
||||
$params['secure'],
|
||||
$params['httponly']
|
||||
$cookie_options
|
||||
);
|
||||
}
|
||||
|
||||
@@ -231,14 +237,20 @@ class Session implements SessionInterface
|
||||
public function invalidate()
|
||||
{
|
||||
$params = session_get_cookie_params();
|
||||
|
||||
$cookie_options = array (
|
||||
'expires' => time() - 42000,
|
||||
'path' => $params['path'],
|
||||
'domain' => $params['domain'],
|
||||
'secure' => $params['secure'],
|
||||
'httponly' => $params['httponly'],
|
||||
'samesite' => $params['samesite']
|
||||
);
|
||||
|
||||
setcookie(
|
||||
session_name(),
|
||||
'',
|
||||
time() - 42000,
|
||||
$params['path'],
|
||||
$params['domain'],
|
||||
$params['secure'],
|
||||
$params['httponly']
|
||||
$cookie_options
|
||||
);
|
||||
|
||||
if ($this->isSessionStarted()) {
|
||||
|
||||
@@ -523,4 +523,20 @@ class UtilsTest extends \Codeception\TestCase\Test
|
||||
$this->assertSame('//foo.com', Utils::url('//foo.com'));
|
||||
$this->assertSame('//foo.com?param=x', Utils::url('//foo.com?param=x'));
|
||||
}
|
||||
|
||||
public function testCheckFilename()
|
||||
{
|
||||
// configure extension for consistent results
|
||||
/** @var \Grav\Common\Config\Config $config */
|
||||
$config = $this->grav['config'];
|
||||
$config->set('security.uploads_dangerous_extensions', ['php', 'html', 'htm', 'exe', 'js']);
|
||||
|
||||
$this->assertFalse(Utils::checkFilename('foo.php'));
|
||||
$this->assertFalse(Utils::checkFilename('bar.js'));
|
||||
|
||||
$this->assertTrue(Utils::checkFilename('foo.json'));
|
||||
$this->assertTrue(Utils::checkFilename('foo.xml'));
|
||||
$this->assertTrue(Utils::checkFilename('foo.yaml'));
|
||||
$this->assertTrue(Utils::checkFilename('foo.yml'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,9 @@ RewriteEngine On
|
||||
# If you experience problems on your site block out the operations listed below
|
||||
# This attempts to block the most common type of exploit `attempts` to Grav
|
||||
#
|
||||
# Block out any script trying to use twig tags in URL.
|
||||
RewriteCond %{REQUEST_URI} ({{|}}|{%|%}) [OR]
|
||||
RewriteCond %{QUERY_STRING} ({{|}}|{%25|%25}) [OR]
|
||||
# Block out any script trying to base64_encode data within the URL.
|
||||
RewriteCond %{QUERY_STRING} base64_encode[^(]*\([^)]*\) [OR]
|
||||
# Block out any script that includes a <script> tag in URL.
|
||||
|
||||
Reference in New Issue
Block a user