Added verification of a token generated outside the engine

https://forkbb.ru/post/211#p211
This commit is contained in:
Visman 2023-07-31 23:54:16 +07:00
parent 68abe1e665
commit 8f2886d210
2 changed files with 26 additions and 9 deletions

View file

@ -20,8 +20,11 @@ class Csrf
protected ?string $error = null; protected ?string $error = null;
protected int $hashExpiration = 3600; protected int $hashExpiration = 3600;
public function __construct(protected Secury $secury, #[SensitiveParameter] protected string $key) public function __construct(
{ protected Secury $secury,
#[SensitiveParameter] protected string $key,
#[SensitiveParameter] protected mixed $externalSalt // сюда и Container может попасть O_o
) {
} }
/** /**
@ -35,12 +38,24 @@ class Csrf
/** /**
* Возвращает csrf токен * Возвращает csrf токен
*/ */
public function create(string $marker, array $args = [], int|string $time = null): string public function create(string $marker, array $args = [], int|string $time = null, string $type = 's'): string
{ {
$marker = $this->argsToStr($marker, $args); $marker = $this->argsToStr($marker, $args);
$time = $time ?: \time(); $time = $time ?: \time();
return $this->secury->hmac($marker, $time . $this->key) . 's' . $time; switch ($type) {
case 's':
return $this->secury->hmac($marker, $time . $this->key) . 's' . $time;
case 'x':
if (
\is_string($this->externalSalt)
&& isset($this->externalSalt[9])
) {
return \hash_hmac('sha1', $marker, $time . $this->externalSalt) . 'x' . $time;
}
default:
return 'n';
}
} }
/** /**
@ -85,17 +100,18 @@ class Csrf
if ( if (
\is_string($token) \is_string($token)
&& \preg_match('%(e|s)(\d+)$%D', $token, $matches) && \preg_match('%(e|s|x)(\d+)$%D', $token, $matches)
) { ) {
switch ($matches[1]) { switch ($matches[1]) {
// токен // токен
case 's': case 's':
case 'x':
if ($matches[2] + ($lifetime ?? self::TOKEN_LIFETIME) < $now) { if ($matches[2] + ($lifetime ?? self::TOKEN_LIFETIME) < $now) {
// просрочен // просрочен
$this->error = 'Expired token'; $this->error = 'Expired token';
} elseif ( } elseif (
$matches[2] + 0 <= $now $matches[2] + 0 <= $now
&& \hash_equals($this->create($marker, $args, $matches[2]), $token) && \hash_equals($this->create($marker, $args, $matches[2], $matches[1]), $token)
) { ) {
$this->error = null; $this->error = null;
$result = true; $result = true;

View file

@ -181,9 +181,10 @@ return [
'attachments' => \ForkBB\Models\Attachment\Attachments::class, 'attachments' => \ForkBB\Models\Attachment\Attachments::class,
'Csrf' => [ 'Csrf' => [
'class' => \ForkBB\Core\Csrf::class, 'class' => \ForkBB\Core\Csrf::class,
'Secury' => '@Secury', 'Secury' => '@Secury',
'key' => '%user.password%%user.ip%%user.id%%BASE_URL%', 'key' => '%user.password%%user.ip%%user.id%%BASE_URL%',
'extSalt' => '',
], ],
'Online' => \ForkBB\Models\Online\Online::class, 'Online' => \ForkBB\Models\Online\Online::class,
'Cookie' => [ 'Cookie' => [