Add layer-7 DOS mitigations to router.php#9
Open
splitbrain wants to merge 2 commits into
Open
Conversation
Recent abuse posted directly to lib/router.php in rapid succession. The
endpoint was wide open: no method check, no size cap, no proof the caller
ever loaded the page. This adds stateless mitigations bound to data the
request is already touching, with one tiny shared secret in data/.secret.
- POST-only enforcement on save and savecomment; $_REQUEST replaced with
explicit $_POST / $_GET so query-string smuggling cannot reach writes.
- Hard size limits on content (512 KB), comment (4 KB), user (64 bytes).
- HMAC-signed action tokens with 30 min TTL:
- save: token bound to scope 'save', emitted as <meta> in index.php
(index.html renamed to index.php), read by script.js at startup.
- savecomment: token bound to the paste's uid, returned alongside
comments by do=loadcomments and verified against the posted uid so
a comment token cannot be replayed against a different paste.
- Per-paste comment cooldown: reject savecomment when the .comments
file's mtime is less than COMMENT_DELAY (3s) ago. Uses filesystem
state that already exists; no extra bookkeeping.
- Shared token helpers and tunables live in lib/lib.php so index.php
can issue tokens without invoking the router dispatcher.
https://claude.ai/code/session_016Kh8s3xrcng9Dgd9Uui6PY
- declare(strict_types=1) in every PHP file. - Replace lib.php's procedural helpers with a final Token utility class (lib/Token.php) using a private constructor and static issue/verify. Class constant Token::TTL replaces the bare TOKEN_TTL global. - PasteManager: final class with constructor property promotion and a readonly $savedir, union return types (false|string, false|array), parameter type hints everywhere, named-arg friendly file_put_contents, and json-decoded comments filtered through is_array() to skip junk. - PasteManager::mkuid now uses random_bytes; drop the hardcoded salt and the dead call to the undefined gen_uuid(). Also generate a new uid on each collision retry (the original loop kept the same uid). - router.php: match() dispatch, never-returning fail() helper, per-case handler functions with typed signatures, $_GET vs $_POST chosen by REQUEST_METHOD, and HTTP error codes propagated via fail() so the status line and json body stay consistent. - index.php: htmlspecialchars() on the embedded save token (token is hex+digits today but defence in depth costs nothing) and short-echo. https://claude.ai/code/session_016Kh8s3xrcng9Dgd9Uui6PY
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Recent abuse posted directly to lib/router.php in rapid succession. The
endpoint was wide open: no method check, no size cap, no proof the caller
ever loaded the page. This adds stateless mitigations bound to data the
request is already touching, with one tiny shared secret in data/.secret.
explicit $_POST / $_GET so query-string smuggling cannot reach writes.
(index.html renamed to index.php), read by script.js at startup.
comments by do=loadcomments and verified against the posted uid so
a comment token cannot be replayed against a different paste.
file's mtime is less than COMMENT_DELAY (3s) ago. Uses filesystem
state that already exists; no extra bookkeeping.
can issue tokens without invoking the router dispatcher.
https://claude.ai/code/session_016Kh8s3xrcng9Dgd9Uui6PY