From b6537eaf501445e597a36522c024dc9645edbb8e Mon Sep 17 00:00:00 2001
From: WeebDataHoarder <57538841+WeebDataHoarder@users.noreply.github.com>
Date: Wed, 2 Apr 2025 11:41:29 +0200
Subject: [PATCH] Add resource-load challenge
---
lib/state.go | 22 ++++++++++++++++++++++
policy.yml | 16 ++++++++++++----
templates/challenge-anubis.gohtml | 3 +++
templates/challenge-forgejo-dark.gohtml | 3 +++
4 files changed, 40 insertions(+), 4 deletions(-)
diff --git a/lib/state.go b/lib/state.go
index f8b9e9e..98297c1 100644
--- a/lib/state.go
+++ b/lib/state.go
@@ -23,6 +23,7 @@ import (
"github.com/tetratelabs/wazero/api"
"github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1"
"github.com/yl2chen/cidranger"
+ "html/template"
"io"
"io/fs"
"log/slog"
@@ -281,6 +282,27 @@ func NewState(p policy.Policy, settings StateSettings) (state *State, err error)
_ = state.challengePage(w, http.StatusTeapot, "", nil)
+ return ChallengeResultStop
+ }
+ case "resource-load":
+ c.Challenge = func(w http.ResponseWriter, r *http.Request, key []byte, expiry time.Time) ChallengeResult {
+ redirectUri := new(url.URL)
+ redirectUri.Path = c.Path + "/verify-challenge"
+
+ values := make(url.Values)
+ values.Set("result", hex.EncodeToString(key))
+
+ redirectUri.RawQuery = values.Encode()
+
+ // self redirect!
+ w.Header().Set("Refresh", "2; url="+r.URL.String())
+
+ _ = state.challengePage(w, http.StatusTeapot, "", map[string]any{
+ "Tags": []template.HTML{
+ template.HTML(fmt.Sprintf("", redirectUri.String())),
+ },
+ })
+
return ChallengeResultStop
}
case "js":
diff --git a/policy.yml b/policy.yml
index 6d8c9bb..b2508e6 100644
--- a/policy.yml
+++ b/policy.yml
@@ -100,11 +100,11 @@ challenges:
asset: runtime.wasm
probability: 0.02
- # Challenges with a cookie, self redirect
+ # Challenges with a cookie, self redirect (non-JS, requires HTTP parsing)
self-cookie:
mode: "cookie"
- # Challenges with a redirect via header
+ # Challenges with a redirect via header (non-JS, requires HTTP parsing and logic)
self-header-refresh:
mode: "header-refresh"
runtime:
@@ -112,7 +112,7 @@ challenges:
mode: "key"
probability: 0.1
- # Challenges with a redirect via meta
+ # Challenges with a redirect via meta (non-JS, requires HTML parsing and logic)
self-meta-refresh:
mode: "meta-refresh"
runtime:
@@ -120,6 +120,14 @@ challenges:
mode: "key"
probability: 0.1
+ # Challenges with loading a random CSS or image document (non-JS, requires HTML parsing and logic)
+ self-resource-load:
+ mode: "resource-load"
+ runtime:
+ # verifies that result = key
+ mode: "key"
+ probability: 0.1
+
http-cookie-check:
mode: http
url: http://gitea:3000/user/stopwatches
@@ -298,7 +306,7 @@ rules:
- name: standard-browser
action: challenge
- challenges: [http-cookie-check, self-meta-refresh, js-pow-sha256]
+ challenges: [http-cookie-check, self-resource-load, self-meta-refresh, js-pow-sha256]
conditions:
- 'userAgent.startsWith("Mozilla/") || userAgent.startsWith("Opera/")'
diff --git a/templates/challenge-anubis.gohtml b/templates/challenge-anubis.gohtml
index e290c05..3b536a5 100644
--- a/templates/challenge-anubis.gohtml
+++ b/templates/challenge-anubis.gohtml
@@ -11,6 +11,9 @@
{{end}}
{{ end }}
+ {{ range .Tags }}
+ {{ . }}
+ {{ end }}