diff --git a/docs/docs/CHANGELOG.md b/docs/docs/CHANGELOG.md index 8bd209b..453d41a 100644 --- a/docs/docs/CHANGELOG.md +++ b/docs/docs/CHANGELOG.md @@ -15,7 +15,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add a "proof of React" challenge to prove that the client is able to run a simple JSX app. - Added possibility to disable HTTP keep-alive to support backends not properly - handling it + handling it. +- Add a server-side check for the meta-refresh challenge that makes sure clients have waited for at least 95% of the time that they should. - Added a missing link to the Caddy installation environment in the installation documentation. - Downstream consumers can change the default [log/slog#Logger](https://pkg.go.dev/log/slog#Logger) instance that Anubis uses by setting `opts.Logger` to your slog instance of choice ([#864](https://github.com/TecharoHQ/anubis/issues/864)). - The [Thoth client](https://anubis.techaro.lol/docs/admin/thoth) is now public in the repo instead of being an internal package. diff --git a/lib/challenge/metarefresh/metarefresh.go b/lib/challenge/metarefresh/metarefresh.go index 7655a9d..5564ae2 100644 --- a/lib/challenge/metarefresh/metarefresh.go +++ b/lib/challenge/metarefresh/metarefresh.go @@ -5,6 +5,7 @@ import ( "fmt" "log/slog" "net/http" + "time" "github.com/TecharoHQ/anubis" "github.com/TecharoHQ/anubis/lib/challenge" @@ -42,6 +43,12 @@ func (i *Impl) Issue(r *http.Request, lg *slog.Logger, in *challenge.IssueInput) } func (i *Impl) Validate(r *http.Request, lg *slog.Logger, in *challenge.ValidateInput) error { + wantTime := in.Challenge.IssuedAt.Add(time.Duration(in.Rule.Challenge.Difficulty) * 950 * time.Millisecond) + + if time.Now().Before(wantTime) { + return challenge.NewError("validate", "insufficent time", fmt.Errorf("%w: wanted user to wait until at least %s", challenge.ErrFailed, wantTime.Format(time.RFC3339))) + } + gotChallenge := r.FormValue("challenge") if subtle.ConstantTimeCompare([]byte(in.Challenge.RandomData), []byte(gotChallenge)) != 1 {