diff --git a/cgi-bin/form.py b/cgi-bin/form.py index 2b90cf9..ab507d5 100755 --- a/cgi-bin/form.py +++ b/cgi-bin/form.py @@ -4,11 +4,12 @@ import base64 import io import cgi import collections +from collections.abc import Mapping import hmac import mimetypes import os import secrets -from typing import Any, Optional, overload, IO +from typing import Any, Optional, overload import itsdangerous import requests @@ -28,7 +29,7 @@ HONEYPOT_FIELD_NAME = "addressline1" SITE_DIRECTORY = os.environ.get("SITE_DIRECTORY", "") request_uri = os.environ.get("REQUEST_URI", "").lower().rstrip("/") serializer = itsdangerous.URLSafeSerializer("secret key", "salt") - +session = requests.Session() cookies = dict[str, str]() for entry in os.environ.get("HTTP_COOKIE", "").split(";"): @@ -81,6 +82,9 @@ match os.environ.get("REQUEST_METHOD", "").upper(): print(f'') + + print('') + print(f'
') print(line) exit(0) @@ -138,9 +142,22 @@ if not hmac.compare_digest(csrf_token, given_csrf_token): # If the honeypot field was not empty, back off. -if get_form_value(HONEYPOT_FIELD_NAME, ""): - fail("200 OK", f"Invalid value for field: {HONEYPOT_FIELD_NAME}") +if ( + get_form_value(HONEYPOT_FIELD_NAME, "") + or get_form_value(CAPTCHA_FIELD_NAME, + "").lower().strip() != CAPTCHA_FIELD_VALUE +): + fail("200 OK", f"Invalid value for field: {CAPTCHA_FIELD_NAME}") +if not (hcaptcha_token := get_form_value("h-captcha-response", "")): + fail("200 OK", "Empty hCaptcha token") +response = session.post("https://hcaptcha.com/siteverify", data={ + "secret": os.environ.get("HCAPTCHA_SECRET_KEY", ""), + "response": hcaptcha_token, +}) +hcaptcha_data = response.json() +if not isinstance(hcaptcha_data, Mapping) or not hcaptcha_data.get("success", False): + fail("200 OK", "hCaptcha fail") # Extract all the actually provided form data. This is different from form to # form (see the match block below). @@ -214,7 +231,6 @@ form_group = os.environ.get("ZAMMAD_GROUP", "") or form_group ZAMMAD_URL = os.environ.get("ZAMMAD_URL", "").rstrip("/") ZAMMAD_TOKEN = os.environ.get("ZAMMAD_TOKEN", "") -session = requests.Session() session.headers.update(Authorization=f"Token token={ZAMMAD_TOKEN}") try: diff --git a/sites/angestoepselt/httpd.conf b/sites/angestoepselt/httpd.conf index 02b6bf0..939938f 100644 --- a/sites/angestoepselt/httpd.conf +++ b/sites/angestoepselt/httpd.conf @@ -11,7 +11,7 @@ server.document-root = "@site@" index-file.names = ( "index.html" ) setenv.set-response-header += ( - "Content-Security-Policy" => "default-src 'self'; script-src 'self' 'unsafe-inline'; frame-ancestors 'none'", + "Content-Security-Policy" => "default-src 'self'; script-src 'self' 'unsafe-inline' https://hcaptcha.com https://*.hcaptcha.com; frame-src 'self' https://hcaptcha.com https://*.hcaptcha.com; style-src 'self' https://hcaptcha.com, https://*.hcaptcha.com; connect-src 'self' https://hcaptcha.com https://*.hcaptcha.com; frame-ancestors 'none'", ) url.redirect = ( @@ -61,6 +61,8 @@ $HTTP["url"] =~ "^/cgi-bin/" { "SITE_DIRECTORY" => "@site@", "ZAMMAD_URL" => env.ZAMMAD_URL, "ZAMMAD_TOKEN" => env.ZAMMAD_TOKEN, - "ZAMMAD_GROUP" => env.ZAMMAD_GROUP + "ZAMMAD_GROUP" => env.ZAMMAD_GROUP, + "HCAPTCHA_SITE_KEY" => env.HCAPTCHA_SITE_KEY, + "HCAPTCHA_SECRET_KEY" => env.HCAPTCHA_SECRET_KEY, ) }