GHSA-56w8-8ppj-2p4f: Bot protection bypass in Anubis
Published on , 684 words, 3 minutes to read
Update your copy of Anubis, but it's very minor
Hey all. I screwed up with part of how I made Anubis, and as a result I have both fixed it and am filing this CVE to explain what went wrong and how it was fixed. This is GHSA-56w8-8ppj-2p4f.
This requires a sophisticated attacker to target a server running Anubis. I suspect that the only instances of this in the wild were the ones done by the reporter as a proof of concept and in my testing.
Vulnerability details
These details have been copied from GHSA-56w8-8ppj-2p4f.
CVSS score: 2.3 (CVSS:4.0/AV:N/AC:H/AT:N/PR:L/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N)
Weakness: CWE-807: Reliance on Untrusted Inputs in a Security Decision
Vulnerable version: anything older than v1.11.0-37-gd98d70a
Patched version: v1.11.0-37-gd98d70a and newer
Context
Anubis is a tool that allows administrators to protect bots against AI scrapers through bot-checking heuristics and a proof-of-work challenge to discourage scraping from multiple IP addresses. For more information about Anubis, see Anubis' README.md.
Impact
A sophisticated attacker (or scraper runner) that is targeting a website that uses Anubis can easily bypass the bot protection mechanisms.
This requires a targeted attack.
Patches
Pull the most recent Docker image in order to be sure you have upgraded past commit e09d0226a628f04b1d80fd83bee777894a45cd02.
Workarounds
There are no known workarounds at this time. Users must upgrade to fix this issue.
Details
Anubis works by having a client request a challenge value with a given difficulty, then the client performs proof-of-work to create a sha-256 hash matching that difficulty. Before commit e09d0226a628f04b1d80fd83bee777894a45cd02, the client sent the difficulty it used back to the server and the server used that untrusted value to make an allow/deny decision.
This has been fixed by using the difficulty value set by the administrator in Anubis' configuration flags when making said allow/deny decisions.
GReeTZ
Thank you Coral Pink for reporting this issue.
The Techaro security issue reporting policy
At Techaro, we believe in total honesty in how we handle security issues. We try our best to not make vulnerable code, but inevitably we will mess up and do it by accident. When we do, we will be: transparent, honest, high-signal, and handle the situation like professional adults. We will value the time of security researchers.
At times, we will fail at this mission. The real thing we are measuring is not the number of times that it happens, but how we react when it does happen. This is why we are openly and honestly reporting this issue.
When things do fail, we will create regression tests to ensure that those failures do not repeat themselves. The testing for Anubis is currently private, but in the interest of transparency here is the test that we added to that repo to handle this regression:
func TestFakeChallengeDifficulty(t *testing.T) {
cli, err := anubis.New(*testServerURL)
if err != nil {
t.Fatal(err)
}
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
chall, err := cli.MakeChallenge(ctx)
if err != nil {
t.Fatal(err)
}
nonce := 42069
response, err := sha256sum(fmt.Sprintf("%s%d", chall.Challenge, nonce))
if err != nil {
t.Fatal(err)
}
if err := cli.PassChallenge(ctx, anubis.PassChallengeRequest{
Response: response,
Nonce: nonce,
Redir: "https://xeiaso.net",
ElapsedTime: 420,
Difficulty: 0,
}); err != nil {
sce, ok := err.(*anubis.StatusCodeErr)
if !ok {
t.Fatal(err)
}
if sce.Got != http.StatusForbidden {
t.Fatalf("wrong status code, should have forbidden auth bypas: want: %d, got: %d", sce.Want, sce.Got)
}
}
return
}
Thank you for following the development of Anubis.
Facts and circumstances may have changed since publication. Please contact me before jumping to conclusions if something seems wrong or unclear.
Tags: