mirror of
https://github.com/PrivateBin/PrivateBin.git
synced 2026-07-25 08:54:00 +00:00
Under strict_types on PHP 8, malformed JSON API v2 payloads triggered
uncaught TypeErrors (HTTP 500) instead of the standard JSON error
response {"status":1,"message":"Invalid data."}:
- a non-numeric `v` reached `$data['v'] + 0` in Request::getData()
- a scalar `meta` reached `count($message['meta'])` in FormatV2::isValid()
- non-array adata[0] / non-string ct fields reached base64_decode(),
strlen() and count() with the wrong types
Validate the types before the numeric coercion and before the
string/count operations, so all such inputs are rejected cleanly with
"Invalid data." instead of a fatal error. Both crashes are remotely
triggerable without authentication (availability only, no data exposure).
Adds FormatV2Test coverage for the malformed-type inputs.
Fixes #1883
112 lines
4.5 KiB
PHP
112 lines
4.5 KiB
PHP
<?php declare(strict_types=1);
|
|
|
|
use PHPUnit\Framework\TestCase;
|
|
use PrivateBin\FormatV2;
|
|
|
|
class FormatV2Test extends TestCase
|
|
{
|
|
public function testFormatV2ValidatorValidatesCorrectly()
|
|
{
|
|
$paste = Helper::getPastePost();
|
|
$comment = Helper::getCommentPost();
|
|
$this->assertTrue(FormatV2::isValid($paste), 'valid format');
|
|
$this->assertTrue(FormatV2::isValid($comment, true), 'valid format');
|
|
|
|
$paste['adata'][0][0] = '$';
|
|
$this->assertFalse(FormatV2::isValid($paste), 'invalid base64 encoding of iv');
|
|
|
|
$paste = Helper::getPastePost();
|
|
$paste['adata'][0][1] = '$';
|
|
$this->assertFalse(FormatV2::isValid($paste), 'invalid base64 encoding of salt');
|
|
|
|
$paste = Helper::getPastePost();
|
|
$paste['ct'] = '$';
|
|
$this->assertFalse(FormatV2::isValid($paste), 'invalid base64 encoding of ct');
|
|
|
|
$paste = Helper::getPastePost();
|
|
$paste['ct'] = 'bm9kYXRhbm9kYXRhbm9kYXRhbm9kYXRhbm9kYXRhCg==';
|
|
$this->assertFalse(FormatV2::isValid($paste), 'low ct entropy');
|
|
|
|
$paste = Helper::getPastePost();
|
|
$paste['adata'][0][0] = 'MTIzNDU2Nzg5MDEyMzQ1Njc4OTA=';
|
|
$this->assertFalse(FormatV2::isValid($paste), 'iv too long');
|
|
|
|
$paste = Helper::getPastePost();
|
|
$paste['adata'][0][1] = 'MTIzNDU2Nzg5MDEyMzQ1Njc4OTA=';
|
|
$this->assertFalse(FormatV2::isValid($paste), 'salt too long');
|
|
|
|
$paste = Helper::getPastePost();
|
|
$paste['foo'] = 'bar';
|
|
$this->assertFalse(FormatV2::isValid($paste), 'invalid additional key');
|
|
unset($paste['meta']);
|
|
$this->assertFalse(FormatV2::isValid($paste), 'invalid missing key');
|
|
|
|
$paste = Helper::getPastePost();
|
|
$paste['v'] = 0.9;
|
|
$this->assertFalse(FormatV2::isValid($paste), 'unsupported version');
|
|
|
|
$paste = Helper::getPastePost();
|
|
$paste['adata'][0][2] = 1000;
|
|
$this->assertFalse(FormatV2::isValid($paste), 'not enough iterations');
|
|
|
|
$paste = Helper::getPastePost();
|
|
$paste['adata'][0][3] = 127;
|
|
$this->assertFalse(FormatV2::isValid($paste), 'invalid key size');
|
|
|
|
$paste = Helper::getPastePost();
|
|
$paste['adata'][0][4] = 63;
|
|
$this->assertFalse(FormatV2::isValid($paste), 'invalid tag length');
|
|
|
|
$paste = Helper::getPastePost();
|
|
$paste['adata'][0][5] = '!#@';
|
|
$this->assertFalse(FormatV2::isValid($paste), 'invalid algorithm');
|
|
|
|
$paste = Helper::getPastePost();
|
|
$paste['adata'][0][6] = '!#@';
|
|
$this->assertFalse(FormatV2::isValid($paste), 'invalid mode');
|
|
|
|
$paste = Helper::getPastePost();
|
|
$paste['adata'][0][7] = '!#@';
|
|
$this->assertFalse(FormatV2::isValid($paste), 'invalid compression');
|
|
|
|
$paste = Helper::getPaste();
|
|
$this->assertFalse(FormatV2::isValid($paste), 'invalid meta key');
|
|
}
|
|
|
|
public function testFormatV2ValidatorRejectsMalformedTypes()
|
|
{
|
|
// malformed input must yield "false" (Invalid data) rather than a
|
|
// fatal type error under strict_types
|
|
$paste = Helper::getPastePost();
|
|
$paste['v'] = 'abc';
|
|
$this->assertFalse(FormatV2::isValid($paste), 'non-numeric version');
|
|
|
|
$paste = Helper::getPastePost();
|
|
$paste['v'] = array();
|
|
$this->assertFalse(FormatV2::isValid($paste), 'array version');
|
|
|
|
$paste = Helper::getPastePost();
|
|
$paste['ct'] = array('not', 'a', 'string');
|
|
$this->assertFalse(FormatV2::isValid($paste), 'non-string ciphertext');
|
|
|
|
$paste = Helper::getPastePost();
|
|
$paste['meta'] = 'not-an-array';
|
|
$this->assertFalse(FormatV2::isValid($paste), 'non-array meta');
|
|
|
|
$paste = Helper::getPastePost();
|
|
$paste['adata'][0] = 'not-an-array';
|
|
$this->assertFalse(FormatV2::isValid($paste), 'non-array cipher parameters');
|
|
|
|
$paste = Helper::getPastePost();
|
|
$paste['adata'][0] = array();
|
|
$this->assertFalse(FormatV2::isValid($paste), 'empty cipher parameters');
|
|
|
|
$paste = Helper::getPastePost();
|
|
$paste['adata'][0][0] = array();
|
|
$this->assertFalse(FormatV2::isValid($paste), 'non-string iv');
|
|
|
|
$comment = Helper::getCommentPost();
|
|
$comment['ct'] = 42;
|
|
$this->assertFalse(FormatV2::isValid($comment, true), 'non-string comment ciphertext');
|
|
}
|
|
}
|