From d703fa6a3a75f7c3b433e8caf618bfb0a9a0ba63 Mon Sep 17 00:00:00 2001 From: Yassine Guedidi Date: Tue, 18 Mar 2025 23:38:48 +0100 Subject: [PATCH] Protect generate_token with a CSRF token --- .../static/themes/material/css/various.scss | 15 ++++ .../Controller/ConfigController.php | 11 +-- .../Resources/views/Config/index.html.twig | 88 +++++++++++-------- .../Controller/ConfigControllerTest.php | 21 +---- 4 files changed, 72 insertions(+), 63 deletions(-) diff --git a/app/Resources/static/themes/material/css/various.scss b/app/Resources/static/themes/material/css/various.scss index ad0703afa..94bb95bd0 100644 --- a/app/Resources/static/themes/material/css/various.scss +++ b/app/Resources/static/themes/material/css/various.scss @@ -38,3 +38,18 @@ nav .input-field input { .tab { flex: 1; } + +.btn-link { + background: none; + border: 0; + padding: 0; + color: $blue-accent-color; + + &:focus { + background: none; + } +} + +.inline-block { + display: inline-block; +} diff --git a/src/Wallabag/CoreBundle/Controller/ConfigController.php b/src/Wallabag/CoreBundle/Controller/ConfigController.php index 4709a4d2e..24e9c07e4 100644 --- a/src/Wallabag/CoreBundle/Controller/ConfigController.php +++ b/src/Wallabag/CoreBundle/Controller/ConfigController.php @@ -16,6 +16,7 @@ use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; +use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; use Symfony\Component\Validator\Constraints\Locale as LocaleConstraint; @@ -429,22 +430,22 @@ class ConfigController extends AbstractController } /** - * @Route("/generate-token", name="generate_token") + * @Route("/generate-token", name="generate_token", methods={"POST"}) * * @return RedirectResponse|JsonResponse */ public function generateTokenAction(Request $request) { + if (!$this->isCsrfTokenValid('generate-token', $request->request->get('token'))) { + throw new BadRequestHttpException('Bad CSRF token.'); + } + $config = $this->getConfig(); $config->setFeedToken(Utils::generateToken()); $this->entityManager->persist($config); $this->entityManager->flush(); - if ($request->isXmlHttpRequest()) { - return new JsonResponse(['token' => $config->getFeedToken()]); - } - $this->addFlash( 'notice', 'flashes.config.notice.feed_token_updated' diff --git a/src/Wallabag/CoreBundle/Resources/views/Config/index.html.twig b/src/Wallabag/CoreBundle/Resources/views/Config/index.html.twig index d52aa4c51..981c53fe4 100644 --- a/src/Wallabag/CoreBundle/Resources/views/Config/index.html.twig +++ b/src/Wallabag/CoreBundle/Resources/views/Config/index.html.twig @@ -123,48 +123,58 @@
+
+
+ {{ 'config.form_feed.description'|trans }} +
+
+ +
+
+
{{ 'config.form_feed.token_label'|trans }}
+
+ {% if feed.token %} + {{ feed.token }} + {% else %} + {{ 'config.form_feed.no_token'|trans }} + {% endif %} + + {% if feed.token %} + – +
+ + + +
+ – {{ 'config.form_feed.token_revoke'|trans }} + {% else %} + – +
+ + + +
+ {% endif %} +
+
+
+ {% if feed.token %} + + {% endif %} + {{ form_start(form.feed) }} {{ form_errors(form.feed) }} -
-
- {{ 'config.form_feed.description'|trans }} -
-
- -
-
-
{{ 'config.form_feed.token_label'|trans }}
-
- {% if feed.token %} - {{ feed.token }} - {% else %} - {{ 'config.form_feed.no_token'|trans }} - {% endif %} - - {% if feed.token %} - – {{ 'config.form_feed.token_reset'|trans }} - – {{ 'config.form_feed.token_revoke'|trans }} - {% else %} - – {{ 'config.form_feed.token_create'|trans }} - {% endif %} -
-
-
- {% if feed.token %} - - {% endif %} -
{{ form_label(form.feed.feed_limit) }} diff --git a/tests/Wallabag/CoreBundle/Controller/ConfigControllerTest.php b/tests/Wallabag/CoreBundle/Controller/ConfigControllerTest.php index 6c049e1dc..7dd5cdf1b 100644 --- a/tests/Wallabag/CoreBundle/Controller/ConfigControllerTest.php +++ b/tests/Wallabag/CoreBundle/Controller/ConfigControllerTest.php @@ -328,7 +328,8 @@ class ConfigControllerTest extends WallabagCoreTestCase $this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(['_text'])); $this->assertStringContainsString('config.form_feed.no_token', $body[0]); - $client->request('GET', '/generate-token'); + $client->submit($crawler->selectButton('config.form_feed.token_create')->form()); + $this->assertSame(302, $client->getResponse()->getStatusCode()); $crawler = $client->followRedirect(); @@ -337,24 +338,6 @@ class ConfigControllerTest extends WallabagCoreTestCase $this->assertStringContainsString('config.form_feed.token_reset', $body[0]); } - public function testGenerateTokenAjax() - { - $this->logInAs('admin'); - $client = $this->getTestClient(); - - $client->request( - 'GET', - '/generate-token', - [], - [], - ['HTTP_X-Requested-With' => 'XMLHttpRequest'] - ); - - $this->assertSame(200, $client->getResponse()->getStatusCode()); - $content = json_decode($client->getResponse()->getContent(), true); - $this->assertArrayHasKey('token', $content); - } - public function testRevokeTokenAjax() { $this->logInAs('admin');