Refactor checkCSRF() to use Sec-Fetch-Site and Origin headers

- 최근 브라우저에서 지원하는 헤더를 사용하여 더 정확하게 체크
- Sec-Fetch-Site, Origin 헤더를 지원하지 않는 경우 기존처럼 Referer 체크
- CSRF 토큰은 더이상 기본 방법보다 보안이 더 뛰어나다고 말하기 힘듬
This commit is contained in:
Kijin Sung 2025-10-22 22:53:45 +09:00
parent f536f0f382
commit e2124ed1c0
4 changed files with 97 additions and 39 deletions

View file

@ -106,10 +106,13 @@ class SecurityTest extends \Codeception\Test\Unit
{
$error_reporting = error_reporting(0);
config('security.check_csrf_token', true);
$_SERVER['REQUEST_METHOD'] = 'GET';
$_SERVER['HTTP_REFERER'] = '';
$_SERVER['HTTP_X_CSRF_TOKEN'] = '';
$this->assertFalse(Rhymix\Framework\Security::checkCSRF());
$_SERVER['HTTP_X_CSRF_TOKEN'] = Rhymix\Framework\Session::createToken();
$this->assertTrue(Rhymix\Framework\Security::checkCSRF());
@ -117,6 +120,7 @@ class SecurityTest extends \Codeception\Test\Unit
$_SERVER['HTTP_REFERER'] = '';
$_SERVER['HTTP_X_CSRF_TOKEN'] = '';
$this->assertFalse(Rhymix\Framework\Security::checkCSRF());
$_SERVER['HTTP_X_CSRF_TOKEN'] = Rhymix\Framework\Session::createToken();
$this->assertTrue(Rhymix\Framework\Security::checkCSRF());
@ -124,27 +128,63 @@ class SecurityTest extends \Codeception\Test\Unit
$_SERVER['HTTP_X_CSRF_TOKEN'] = '';
$this->assertFalse(Rhymix\Framework\Security::checkCSRF());
$_SERVER['HTTP_REFERER'] = 'http://www.rhymix.org/foo/bar';
$_SERVER['HTTP_X_CSRF_TOKEN'] = '';
$_SERVER['HTTP_X_CSRF_TOKEN'] = Rhymix\Framework\Session::createToken();
$this->assertTrue(Rhymix\Framework\Security::checkCSRF());
$_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';
$_SERVER['HTTP_X_CSRF_TOKEN'] = '0';
$this->assertFalse(Rhymix\Framework\Security::checkCSRF());
config('security.check_csrf_token', false);
unset($_SERVER['HTTP_X_CSRF_TOKEN']);
$_SERVER['HTTP_REFERER'] = 'https://www.rhymix.org/foo/bar';
$this->assertTrue(Rhymix\Framework\Security::checkCSRF());
$_SERVER['HTTP_ORIGIN'] = 'https://www.rhymix.org';
$_SERVER['HTTP_REFERER'] = 'https://www.foobar.com';
$this->assertTrue(Rhymix\Framework\Security::checkCSRF());
$_SERVER['HTTP_ORIGIN'] = 'https://www.foobar.com';
$this->assertFalse(Rhymix\Framework\Security::checkCSRF());
$_SERVER['HTTP_SEC_FETCH_SITE'] = 'same-origin';
$this->assertTrue(Rhymix\Framework\Security::checkCSRF());
$_SERVER['HTTP_SEC_FETCH_SITE'] = 'none';
$this->assertTrue(Rhymix\Framework\Security::checkCSRF());
$_SERVER['HTTP_SEC_FETCH_SITE'] = 'invalid value';
$this->assertFalse(Rhymix\Framework\Security::checkCSRF());
unset($_SERVER['HTTP_SEC_FETCH_SITE']);
$_SERVER['HTTP_ORIGIN'] = '';
$_SERVER['HTTP_REFERER'] = '';
$this->assertFalse(Rhymix\Framework\Security::checkCSRF());
$_SERVER['HTTP_ORIGIN'] = 'null';
$_SERVER['HTTP_REFERER'] = '';
$this->assertFalse(Rhymix\Framework\Security::checkCSRF());
$_SERVER['HTTP_REFERER'] = '';
$_SERVER['HTTP_X_CSRF_TOKEN'] = '';
$this->assertTrue(Rhymix\Framework\Security::checkCSRF('http://www.rhymix.org/'));
$_SERVER['HTTP_ORIGIN'] = 'null';
$_SERVER['HTTP_REFERER'] = 'https://www.rhymix.org';
$this->assertTrue(Rhymix\Framework\Security::checkCSRF());
$_SERVER['HTTP_ORIGIN'] = '';
$_SERVER['HTTP_REFERER'] = 'null';
$this->assertFalse(Rhymix\Framework\Security::checkCSRF());
$_SERVER['HTTP_ORIGIN'] = '';
$_SERVER['HTTP_REFERER'] = '';
$this->assertTrue(Rhymix\Framework\Security::checkCSRF('https://www.rhymix.org/'));
$_SERVER['HTTP_SEC_FETCH_SITE'] = 'cross-site';
$this->assertFalse(Rhymix\Framework\Security::checkCSRF('https://www.rhymix.org/'));
unset($_SERVER['HTTP_SEC_FETCH_SITE']);
error_reporting($error_reporting);
}