mirror of
https://github.com/Lastorder-DC/rhymix.git
synced 2026-01-04 01:01:41 +09:00
- 최근 브라우저에서 지원하는 헤더를 사용하여 더 정확하게 체크 - Sec-Fetch-Site, Origin 헤더를 지원하지 않는 경우 기존처럼 Referer 체크 - CSRF 토큰은 더이상 기본 방법보다 보안이 더 뛰어나다고 말하기 힘듬
214 lines
8 KiB
PHP
214 lines
8 KiB
PHP
<?php
|
|
|
|
class SecurityTest extends \Codeception\Test\Unit
|
|
{
|
|
public function testSanitize()
|
|
{
|
|
// Escape
|
|
$this->assertEquals('foo<bar>', Rhymix\Framework\Security::sanitize('foo<bar>', 'escape'));
|
|
|
|
// Strip
|
|
$this->assertEquals('foobar', Rhymix\Framework\Security::sanitize('foo<p>bar</p>', 'strip'));
|
|
|
|
// HTML (more thorough tests in HTMLFilterTest)
|
|
$this->assertEquals('<p>safe</p>', Rhymix\Framework\Security::sanitize('<p>safe<script></script></p>', 'html'));
|
|
|
|
// Filename (more thorough tests in FilenameFilterTest)
|
|
$this->assertEquals('foo(bar).xls', Rhymix\Framework\Security::sanitize('foo<bar>.xls', 'filename'));
|
|
}
|
|
|
|
public function testEncryption()
|
|
{
|
|
$plaintext = Rhymix\Framework\Security::getRandom();
|
|
config('crypto.encryption_key', Rhymix\Framework\Security::getRandom());
|
|
|
|
// Encryption with default key.
|
|
$encrypted = Rhymix\Framework\Security::encrypt($plaintext);
|
|
$this->assertNotEquals(false, $encrypted);
|
|
$decrypted = Rhymix\Framework\Security::decrypt($encrypted);
|
|
$this->assertEquals($plaintext, $decrypted);
|
|
|
|
// Encryption with custom key.
|
|
$key = Rhymix\Framework\Security::getRandom();
|
|
$encrypted = Rhymix\Framework\Security::encrypt($plaintext, $key);
|
|
$this->assertNotEquals(false, $encrypted);
|
|
$decrypted = Rhymix\Framework\Security::decrypt($encrypted, $key);
|
|
$this->assertEquals($plaintext, $decrypted);
|
|
|
|
// Test invalid ciphertext.
|
|
$decrypted = Rhymix\Framework\Security::decrypt('1234' . substr($encrypted, 4));
|
|
$this->assertEquals(false, $decrypted);
|
|
$decrypted = Rhymix\Framework\Security::decrypt(substr($encrypted, strlen($encrypted) - 4) . 'abcd');
|
|
$this->assertEquals(false, $decrypted);
|
|
$decrypted = Rhymix\Framework\Security::decrypt($plaintext);
|
|
$this->assertEquals(false, $decrypted);
|
|
}
|
|
|
|
public function testSignature()
|
|
{
|
|
$plaintext = Rhymix\Framework\Security::getRandom();
|
|
config('crypto.authentication_key', Rhymix\Framework\Security::getRandom());
|
|
|
|
$signature = Rhymix\Framework\Security::createSignature($plaintext);
|
|
$this->assertRegexp('/^[a-zA-Z0-9-_]{40}$/', $signature);
|
|
$this->assertEquals(true, Rhymix\Framework\Security::verifySignature($plaintext, $signature));
|
|
$this->assertEquals(false, Rhymix\Framework\Security::verifySignature($plaintext, $signature . 'x'));
|
|
$this->assertEquals(false, Rhymix\Framework\Security::verifySignature($plaintext, 'x' . $signature));
|
|
}
|
|
|
|
public function testGetRandom()
|
|
{
|
|
$this->assertRegExp('/^[0-9a-zA-Z]{32}$/', Rhymix\Framework\Security::getRandom());
|
|
$this->assertRegExp('/^[0-9a-zA-Z]{256}$/', Rhymix\Framework\Security::getRandom(256));
|
|
$this->assertRegExp('/^[0-9a-zA-Z]{16}$/', Rhymix\Framework\Security::getRandom(16, 'alnum'));
|
|
$this->assertRegExp('/^[0-9a-f]{16}$/', Rhymix\Framework\Security::getRandom(16, 'hex'));
|
|
$this->assertRegExp('/^[\x21-\x7e]{16}$/', Rhymix\Framework\Security::getRandom(16, 'printable'));
|
|
}
|
|
|
|
public function testGetRandomNumber()
|
|
{
|
|
for ($i = 0; $i < 10; $i++)
|
|
{
|
|
$min = mt_rand(0, 10000);
|
|
$max = $min + mt_rand(0, 10000);
|
|
$random = Rhymix\Framework\Security::getRandomNumber($min, $max);
|
|
$this->assertTrue($random >= $min && $random <= $max);
|
|
}
|
|
}
|
|
|
|
public function testGetRandomUUID()
|
|
{
|
|
$regex = '/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/';
|
|
for ($i = 0; $i < 10; $i++)
|
|
{
|
|
$this->assertRegExp($regex, Rhymix\Framework\Security::getRandomUUID());
|
|
}
|
|
for ($i = 0; $i < 10; $i++)
|
|
{
|
|
$this->assertRegExp($regex, Rhymix\Framework\Security::getRandomUUID(4));
|
|
}
|
|
|
|
$regex = '/^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/';
|
|
for ($i = 0; $i < 10; $i++)
|
|
{
|
|
$this->assertRegExp($regex, Rhymix\Framework\Security::getRandomUUID(7));
|
|
}
|
|
}
|
|
|
|
public function testCompareStrings()
|
|
{
|
|
$this->assertTrue(Rhymix\Framework\Security::compareStrings('foobar', 'foobar'));
|
|
$this->assertFalse(Rhymix\Framework\Security::compareStrings('foobar', 'foobar*'));
|
|
$this->assertFalse(Rhymix\Framework\Security::compareStrings('foo', 'bar'));
|
|
}
|
|
|
|
public function testCheckCSRF()
|
|
{
|
|
$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());
|
|
|
|
$_SERVER['REQUEST_METHOD'] = 'POST';
|
|
$_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());
|
|
|
|
$_SERVER['HTTP_REFERER'] = 'http://www.foobar.com/';
|
|
$_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());
|
|
|
|
$_SERVER['HTTP_X_CSRF_TOKEN'] = 'invalid value';
|
|
$this->assertFalse(Rhymix\Framework\Security::checkCSRF());
|
|
|
|
$_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_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);
|
|
}
|
|
|
|
public function testCheckXXE()
|
|
{
|
|
$xml = '<methodCall></methodCall>';
|
|
$this->assertTrue(Rhymix\Framework\Security::checkXXE($xml));
|
|
|
|
$xml = '<?xml version="1.0" encoding="UTF-8"?><methodCall></methodCall>';
|
|
$this->assertTrue(Rhymix\Framework\Security::checkXXE($xml));
|
|
|
|
$xml = '<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE foo><methodCall attr="value"></methodCall>';
|
|
$this->assertTrue(Rhymix\Framework\Security::checkXXE($xml));
|
|
|
|
$xml = '<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE foo><whatever></whatever>';
|
|
$this->assertFalse(Rhymix\Framework\Security::checkXXE($xml));
|
|
|
|
$xml = '<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE foo>';
|
|
$this->assertFalse(Rhymix\Framework\Security::checkXXE($xml));
|
|
|
|
$xml = '<?xml version="1.0" encoding="UTF-8"?><!ENTITY xxe SYSTEM "http://www.attacker.com/text.txt"><methodCall></methodCall>';
|
|
$this->assertFalse(Rhymix\Framework\Security::checkXXE($xml));
|
|
|
|
$xml = '<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE foo [<!ELEMENT foo ANY><!ENTITY xxe SYSTEM "file:///etc/passwd" >]><fault></fault>';
|
|
$this->assertFalse(Rhymix\Framework\Security::checkXXE($xml));
|
|
}
|
|
}
|