From 6562d3cf287a663ea2c3dce3eb630300c9354a9f Mon Sep 17 00:00:00 2001 From: Gerrie Crafford Date: Fri, 2 Feb 2024 09:58:48 +0200 Subject: [PATCH] Increase max webhook length and add backend length check --- canarytokens/constants.py | 2 ++ canarytokens/queries.py | 9 ++++++++- frontend/app.py | 3 +++ templates/generate_new.html | 2 +- tests/units/test_frontend.py | 14 +++++++++++++- 5 files changed, 27 insertions(+), 3 deletions(-) diff --git a/canarytokens/constants.py b/canarytokens/constants.py index 22dc8d6f2..fb07e7eb9 100644 --- a/canarytokens/constants.py +++ b/canarytokens/constants.py @@ -30,3 +30,5 @@ MAILGUN_IGNORE_ERRORS = [ "to parameter is not a valid address. please check documentation" ] + +MAX_WEBHOOK_URL_LENGTH = 1024 diff --git a/canarytokens/queries.py b/canarytokens/queries.py index 4873b2665..970720696 100644 --- a/canarytokens/queries.py +++ b/canarytokens/queries.py @@ -14,7 +14,7 @@ from twisted.logger import Logger from canarytokens import canarydrop as cand -from canarytokens import models, tokens +from canarytokens import models, tokens, constants from canarytokens.exceptions import CanarydropAuthFailure, NoCanarydropFound from canarytokens.redismanager import ( # KEY_BITCOIN_ACCOUNT,; KEY_BITCOIN_ACCOUNTS,; KEY_CANARY_NXDOMAINS,; KEY_CANARYTOKEN_ALERT_COUNT,; KEY_CLONEDSITE_TOKEN,; KEY_CLONEDSITE_TOKENS,; KEY_IMGUR_TOKEN,; KEY_IMGUR_TOKENS,; KEY_KUBECONFIG_CERTS,; KEY_KUBECONFIG_HITS,; KEY_KUBECONFIG_SERVEREP,; KEY_LINKEDIN_ACCOUNT,; KEY_LINKEDIN_ACCOUNTS,; KEY_USER_ACCOUNT, DB, @@ -797,11 +797,18 @@ def add_canary_google_api_key(key: str) -> int: # return key +class WebhookTooLongError(Exception): + pass + + def validate_webhook(url, token_type: models.TokenTypes): """Tests if a webhook is valid by sending a test payload Arguments: url -- Webhook url """ + if len(url) > constants.MAX_WEBHOOK_URL_LENGTH: + raise WebhookTooLongError() + slack = "https://hooks.slack.com" googlechat_hook_base_url = "https://chat.googleapis.com" discord = "https://discord.com/api/webhooks" diff --git a/frontend/app.py b/frontend/app.py index 752aa8814..dd97de660 100644 --- a/frontend/app.py +++ b/frontend/app.py @@ -147,6 +147,7 @@ remove_canary_domain, save_canarydrop, validate_webhook, + WebhookTooLongError, ) from canarytokens.redismanager import DB from canarytokens.settings import FrontendSettings, SwitchboardSettings @@ -347,6 +348,8 @@ async def generate(request: Request) -> AnyTokenResponse: # noqa: C901 # gen i validate_webhook( token_request_details.webhook_url, token_request_details.token_type ) + except WebhookTooLongError: + return response_error(3, "Webhook URL too long. Use a shorter webhook URL.") except requests.exceptions.HTTPError: return response_error( 3, "Invalid webhook supplied. Confirm you can POST to this URL." diff --git a/templates/generate_new.html b/templates/generate_new.html index f8e89da17..725c3d210 100644 --- a/templates/generate_new.html +++ b/templates/generate_new.html @@ -1041,7 +1041,7 @@

Your log4shell token is active!

if (endpoints.val().length == 0) { return endpoints.addClass('error-outline').removeClass('success-outline'); } - if (endpoints.val().length > 255) { + if (endpoints.val().length > 1024) { return endpoints.addClass('error-outline').removeClass('success-outline'); } endpoints_components = endpoints.val().split(' '); diff --git a/tests/units/test_frontend.py b/tests/units/test_frontend.py index 88c959727..dec79cbd2 100644 --- a/tests/units/test_frontend.py +++ b/tests/units/test_frontend.py @@ -7,7 +7,7 @@ from fastapi.testclient import TestClient from pydantic import HttpUrl -from canarytokens import canarydrop, models, queries +from canarytokens import canarydrop, models, queries, constants from canarytokens.models import ( AnyDownloadRequest, AnyTokenRequest, @@ -91,6 +91,18 @@ def test_generate_dns_token(test_client: TestClient) -> None: assert resp.status_code == 200 +def test_reject_webhook_too_long(test_client: TestClient) -> None: + url_suffix = "a" * constants.MAX_WEBHOOK_URL_LENGTH + dns_request_token = models.DNSTokenRequest( + token_type=TokenTypes.DNS, + email="test@test.com", + webhook_url=f"https://slack.com/api/{url_suffix}", + memo="test stuff break stuff fix stuff test stuff", + ) + resp = test_client.post("/generate", json=json.loads(dns_request_token.json())) + assert resp.status_code == 400 + + def test_generate_log4shell_token(test_client: TestClient) -> None: log4shell_request_token = models.Log4ShellTokenRequest( email="test@test.com",