address csrf vulnerability

improved discord embed support
This commit is contained in:
Sergio Brighenti 2021-07-31 12:37:06 +02:00
parent bff37d6926
commit 84020830ca
3 changed files with 57 additions and 10 deletions

View file

@ -41,12 +41,15 @@ class MediaController extends Controller
$filesystem = $this->storage;
if (isBot($request->getHeaderLine('User-Agent'))) {
$userAgent = $request->getHeaderLine('User-Agent');
$mime = $filesystem->getMimetype($media->storage_path);
if (isBot($userAgent) && (!isDiscord($userAgent) || (isDiscord($userAgent) && !isDisplayableImage($mime)))) {
return $this->streamMedia($request, $response, $filesystem, $media);
}
try {
$media->mimetype = $filesystem->getMimetype($media->storage_path);
$media->mimetype = $mime;
$size = $filesystem->getSize($media->storage_path);
$type = explode('/', $media->mimetype)[0];
@ -114,7 +117,7 @@ class MediaController extends Controller
{
$media = $this->getMedia($userCode, $mediaCode, false);
if (!$media || !$media->published && $this->session->get('user_id') !== $media->user_id && !$this->session->get('admin', false)) {
if (!$media || (!$media->published && $this->session->get('user_id') !== $media->user_id && !$this->session->get('admin', false))) {
throw new HttpNotFoundException($request);
}
@ -122,8 +125,7 @@ class MediaController extends Controller
throw new HttpBadRequestException($request);
}
// If contains html, return it as text/plain
if (strpos($this->storage->getMimetype($media->storage_path), 'text/htm') !== false) {
if (must_be_escaped($this->storage->getMimetype($media->storage_path))) {
$response = $this->streamMedia($request, $response, $this->storage, $media);
return $response->withHeader('Content-Type', 'text/plain');
}
@ -146,7 +148,7 @@ class MediaController extends Controller
{
$media = $this->getMedia($userCode, $mediaCode, false);
if (!$media || !$media->published && $this->session->get('user_id') !== $media->user_id && !$this->session->get('admin', false)) {
if (!$media || (!$media->published && $this->session->get('user_id') !== $media->user_id && !$this->session->get('admin', false))) {
throw new HttpNotFoundException($request);
}

View file

@ -26,7 +26,7 @@ class Session
$params = session_get_cookie_params();
session_set_cookie_params(
$params['lifetime'],
$params['path'].'; SameSite=Lax',
$params['path'].'; SameSite=Strict',
$params['domain'],
$params['secure'],
$params['httponly']
@ -38,7 +38,7 @@ class Session
'save_path' => $path,
'cookie_httponly' => true,
'gc_probability' => 25,
'cookie_samesite' => 'Lax', // works only for php >= 7.3
'cookie_samesite' => 'Strict', // works only for php >= 7.3
]);
if (!$started) {

View file

@ -67,8 +67,6 @@ if (!function_exists('isDisplayableImage')) {
'image/x-icon',
'image/jpeg',
'image/png',
'image/svg',
'image/svg+xml',
'image/tiff',
'image/webp',
]);
@ -345,6 +343,29 @@ if (!function_exists('isBot')) {
}
}
if (!function_exists('isDiscord')) {
/**
* @param string $userAgent
*
* @return bool
*/
function isDiscord(string $userAgent): bool
{
$bots = [
'discord',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:38.0) Gecko/20100101 Firefox/38.0' // discord image bot
];
foreach ($bots as $bot) {
if (stripos($userAgent, $bot) !== false) {
return true;
}
}
return false;
}
}
if (!function_exists('mime2font')) {
/**
* Convert get the icon from the file mimetype.
@ -495,3 +516,27 @@ if (!function_exists('platform_mail')) {
return $mailbox.'@'.str_ireplace('www.', '', parse_url(resolve('config')['base_url'], PHP_URL_HOST));
}
}
if (!function_exists('must_be_escaped')) {
/**
* Return the system no-reply mail.
*
* @param $mime
* @return bool
*/
function must_be_escaped($mime): bool
{
$mimes = [
'text/htm',
'image/svg'
];
foreach ($mimes as $m) {
if (stripos($mime, $m) !== false) {
return true;
}
}
return false;
}
}