Use Origin header before Referer to check CSRF

OWASP에서는 Referer 헤더보다 Origin 헤더를 먼저 체크하는 것을 권장합니다.
Referer가 비어 있는 경우에도 Origin 헤더에는 유용한 정보가 들어 있을 수 있기 때문입니다.

https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html
This commit is contained in:
Kijin Sung 2021-02-23 16:51:46 +09:00
parent 6a568e8e79
commit e423cba24d
2 changed files with 16 additions and 2 deletions

View file

@ -350,8 +350,11 @@ class Security
trigger_error('CSRF token missing in POST request: ' . (\Context::get('act') ?: '(no act)'), \E_USER_WARNING);
}
$referer = strval($referer ?: $_SERVER['HTTP_REFERER']);
if ($referer !== '' && (!config('security.check_csrf_token') || !$is_logged))
if (!$referer)
{
$referer = strval(($_SERVER['HTTP_ORIGIN'] ?? '') ?: ($_SERVER['HTTP_REFERER'] ?? ''));
}
if ($referer !== '' && $referer !== 'null' && (!config('security.check_csrf_token') || !$is_logged))
{
return URL::isInternalURL($referer);
}

View file

@ -138,6 +138,17 @@ class SecurityTest extends \Codeception\TestCase\Test
$_SERVER['HTTP_X_CSRF_TOKEN'] = 'invalid value';
$this->assertFalse(Rhymix\Framework\Security::checkCSRF());
$_SERVER['HTTP_ORIGIN'] = 'http://www.rhymix.org';
$_SERVER['HTTP_REFERER'] = 'http://www.foobar.com';
$_SERVER['HTTP_X_CSRF_TOKEN'] = '';
$this->assertTrue(Rhymix\Framework\Security::checkCSRF());
$_SERVER['HTTP_REFERER'] = '';
$this->assertTrue(Rhymix\Framework\Security::checkCSRF());
$_SERVER['HTTP_ORIGIN'] = 'http://www.foobar.com';
$this->assertFalse(Rhymix\Framework\Security::checkCSRF());
$_SERVER['HTTP_ORIGIN'] = 'null';
$this->assertFalse(Rhymix\Framework\Security::checkCSRF());
$_SERVER['HTTP_REFERER'] = '';
$_SERVER['HTTP_X_CSRF_TOKEN'] = '';
$this->assertTrue(Rhymix\Framework\Security::checkCSRF('http://www.rhymix.org/'));