Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show some serious content for more exploit attempts #471

Merged
merged 3 commits into from
Jan 15, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/disallowed-calls.neon
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ parameters:
allowIn:
- src/Application/ServerEnv.php
- tests/Application/ServerEnvTest.phpt
- tests/EasterEgg/FourOhFourButFoundTest.phpt
disallowedClasses:
-
class:
Expand Down
29 changes: 15 additions & 14 deletions app/src/EasterEgg/FourOhFourButFound.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,47 +3,48 @@

namespace MichalSpacekCz\EasterEgg;

use MichalSpacekCz\Application\ServerEnv;
use MichalSpacekCz\Http\Robots\Robots;
use MichalSpacekCz\Http\Robots\RobotsRule;
use Nette\Application\Responses\TextResponse;
use Nette\Application\UI\Presenter;
use Nette\Http\IRequest;

readonly class FourOhFourButFound
{

private const array TEMPLATES = [
'?%ad' => __DIR__ . '/templates/phpCve20244577.html',
'/etc/passwd' => __DIR__ . '/templates/etcPasswd.html',
];


public function __construct(
private IRequest $httpRequest,
private readonly Robots $robots,
private Robots $robots,
) {
}


public function sendItMaybe(Presenter $presenter): void
{
$url = $this->httpRequest->getUrl();
$url = ServerEnv::tryGetString('REQUEST_URI');
if ($url === null) {
return;
}
foreach (self::TEMPLATES as $request => $template) {
if (str_contains($url->getPath(), $request)) {
$this->sendIt($presenter, $template);
} else {
$query = $url->getQuery();
if ($query && str_contains(urldecode($query), $request)) {
$this->sendIt($presenter, $template);
}
if (str_contains($url, $request) || str_contains(urldecode($url), $request)) {
$this->robots->setHeader([RobotsRule::NoIndex, RobotsRule::NoFollow]);
$presenter->sendResponse(new TextResponse(file_get_contents($template)));
}
}
}


private function sendIt(Presenter $presenter, string $template): never
/**
* @return list<string>
*/
public function getRequestSubstrings(): array
{
$this->robots->setHeader([RobotsRule::NoIndex, RobotsRule::NoFollow]);
$presenter->sendResponse(new TextResponse(file_get_contents($template)));
return array_keys(self::TEMPLATES);
}

}
12 changes: 12 additions & 0 deletions app/src/EasterEgg/templates/phpCve20244577.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Prase error</title>
</head>
<body>
<br>
<b>Parse error</b>: syntax error, unexpected token &quot;&lt;?php&quot;, expecting &quot;&lt;?gif87a&quot; or &quot;&lt;?gif89a&quot; in <b>php://input</b> on line <b>-1</b>°C<br>
</body>
</html>
6 changes: 5 additions & 1 deletion app/src/Form/FormValidators.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
namespace MichalSpacekCz\Form;

use Contributte\Translation\Translator;
use MichalSpacekCz\EasterEgg\FourOhFourButFound;
use Nette\Forms\Controls\TextInput;
use Nette\Forms\Form;

Expand All @@ -12,13 +13,16 @@

public function __construct(
private Translator $translator,
private FourOhFourButFound $fourOhFourButFound,
) {
}


public function addValidateSlugRules(TextInput $input): void
{
$input->addRule(Form::Pattern, $this->translator->translate('messages.forms.validateSlugParamsError'), '[a-z0-9.,_-]+');
$input
->addRule(Form::Pattern, $this->translator->translate('messages.forms.validateSlugParamsError'), '[a-z0-9.,_-]+')
->addRule(Form::IsNotIn, $this->translator->translate('messages.forms.validateSlugParamsEasterEgg'), $this->fourOhFourButFound->getRequestSubstrings());
}

}
13 changes: 13 additions & 0 deletions app/src/Www/Presenters/BasePresenter.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use MichalSpacekCz\Application\Locale\LocaleLinkGenerator;
use MichalSpacekCz\Css\CriticalCss;
use MichalSpacekCz\Css\CriticalCssFactory;
use MichalSpacekCz\EasterEgg\FourOhFourButFound;
use MichalSpacekCz\Form\ThemeFormFactory;
use MichalSpacekCz\Form\UiForm;
use MichalSpacekCz\User\Manager;
Expand Down Expand Up @@ -38,6 +39,8 @@ abstract class BasePresenter extends Presenter

private ComponentParameters $componentParameters;

private FourOhFourButFound $fourOhFourButFound;


/**
* @internal
Expand Down Expand Up @@ -93,6 +96,15 @@ public function injectComponentParameters(ComponentParameters $componentParamete
}


/**
* @internal
*/
public function injectFourOhFourButFound(FourOhFourButFound $fourOhFourButFound): void
{
$this->fourOhFourButFound = $fourOhFourButFound;
}


#[Override]
protected function startup(): void
{
Expand All @@ -101,6 +113,7 @@ protected function startup(): void
if ($this->authenticator->isForbidden() && $this->getRequest()?->getMethod() !== Request::FORWARD) {
$this->forward(':Www:Forbidden:', ['message' => 'messages.forbidden.spam']);
}
$this->fourOhFourButFound->sendItMaybe($this);
}


Expand Down
3 changes: 0 additions & 3 deletions app/src/Www/Presenters/ErrorPresenter.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
use MichalSpacekCz\Application\Exceptions\ParameterNotStringException;
use MichalSpacekCz\Application\Locale\LocaleLink;
use MichalSpacekCz\Application\Locale\LocaleLinkGenerator;
use MichalSpacekCz\EasterEgg\FourOhFourButFound;
use MichalSpacekCz\ShouldNotHappenException;
use Nette\Application\BadRequestException;
use Nette\Application\UI\InvalidLinkException;
Expand All @@ -32,7 +31,6 @@ class ErrorPresenter extends BaseErrorPresenter

public function __construct(
private readonly LocaleLinkGenerator $localeLinkGenerator,
private readonly FourOhFourButFound $fourOhFourButFound,
private readonly AppRequest $appRequest,
private readonly Translator $translator,
) {
Expand Down Expand Up @@ -70,7 +68,6 @@ protected function getLocaleLinksGeneratorParams(): array

public function actionDefault(BadRequestException $exception): void
{
$this->fourOhFourButFound->sendItMaybe($this);
$code = (in_array($exception->getCode(), $this->statuses) ? $exception->getCode() : IResponse::S400_BadRequest);
$this->template->errorCode = $code;
$this->template->pageTitle = $this->translator->translate("messages.title.error{$code}");
Expand Down
1 change: 1 addition & 0 deletions app/src/lang/messages.cs_CZ.neon
Original file line number Diff line number Diff line change
Expand Up @@ -398,3 +398,4 @@ httpHeaders:
headerNotSent: "hlavička neposlána"
forms:
validateSlugParamsError: "%label musí odpovídat formátu %d"
validateSlugParamsEasterEgg: "%label nemůže být '%value', protože to spustí Easter egg"
1 change: 1 addition & 0 deletions app/src/lang/messages.en_US.neon
Original file line number Diff line number Diff line change
Expand Up @@ -398,3 +398,4 @@ httpHeaders:
headerNotSent: "header not sent"
forms:
validateSlugParamsError: "%label must match %d"
validateSlugParamsEasterEgg: "%label can't be '%value', because that's used by an Easter egg"
16 changes: 5 additions & 11 deletions app/tests/EasterEgg/FourOhFourButFoundTest.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,8 @@ namespace MichalSpacekCz\EasterEgg;

use MichalSpacekCz\Test\Application\ApplicationPresenter;
use MichalSpacekCz\Test\Application\UiPresenterMock;
use MichalSpacekCz\Test\Http\Request;
use MichalSpacekCz\Test\TestCaseRunner;
use Nette\Application\Responses\TextResponse;
use Nette\Http\UrlScript;
use Tester\Assert;
use Tester\TestCase;

Expand All @@ -22,7 +20,6 @@ class FourOhFourButFoundTest extends TestCase

public function __construct(
private readonly FourOhFourButFound $fourOhFourButFound,
private readonly Request $request,
private readonly ApplicationPresenter $applicationPresenter,
) {
}
Expand All @@ -42,6 +39,8 @@ class FourOhFourButFoundTest extends TestCase
['/etc/foo?file=..%2F..%2F..%2Fetc%2Fpasswd', 'rick:x:1337:1337:Astley'],
['/etc/foo?file=../../../etc/passwd&foo/bar', 'rick:x:1337:1337:Astley'],
['/etc/foo?file=..%2F..%2F..%2Fetc%2Fpasswd&foo/bar', 'rick:x:1337:1337:Astley'],
['/?%adfoo', 'Parse error'],
['/?%ad=/etc/passwd&bar', 'Parse error'],
];
}

Expand All @@ -50,7 +49,7 @@ class FourOhFourButFoundTest extends TestCase
public function testSendItMaybe(string $url, ?string $contains): void
{
$presenter = new UiPresenterMock();
$this->request->setUrl(new UrlScript($url));
$_SERVER['REQUEST_URI'] = $url;
if ($contains === null) {
Assert::false($this->applicationPresenter->expectSendResponse(function () use ($presenter): void {
$this->fourOhFourButFound->sendItMaybe($presenter);
Expand All @@ -60,13 +59,8 @@ class FourOhFourButFoundTest extends TestCase
$this->fourOhFourButFound->sendItMaybe($presenter);
}));
$response = $presenter->getResponse();
if (!$response instanceof TextResponse) {
Assert::fail('Response is of a wrong type ' . get_debug_type($response));
} elseif (!is_string($response->getSource())) {
Assert::fail('Source should be a string but is ' . get_debug_type($response->getSource()));
} else {
Assert::contains($contains, $response->getSource());
}
assert($response instanceof TextResponse && is_string($response->getSource()));
Assert::contains($contains, $response->getSource());
}
}

Expand Down
Loading