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 }}