Skip to content

[Security] Hardcoded JWT Secret Allows Arbitrary Token Forgery and Full Admin Takeover #1622

Description

@geo-chen

Summary

Crawlab's authentication service hardcodes the HMAC-SHA256 JWT signing secret as the string "crawlab" with no mechanism to override it via configuration. Any network-accessible attacker can craft a valid JWT for any existing user, including the built-in administrator, and gain full administrative access to the platform without any prior credentials.

Details

The JWT signing secret is set at initialization in core/user/service_v2.go (and the parallel core/user/service.go):

// core/user/service_v2.go, line 190
svc = &ServiceV2{
    modelSvc:         service.NewModelServiceV2[models.UserV2](),
    jwtSecret:        "crawlab",
    jwtSigningMethod: jwt.SigningMethodHS256,
}

Although a SetJwtSecret method and a WithJwtSecret option helper exist, neither is ever called from any call site in the codebase. The jwtSecret field therefore always retains the value "crawlab".

Token verification in checkToken simply calls jwt.Parse with a Keyfunc that returns []byte(svc.jwtSecret). Because the secret is public knowledge, any attacker can compute a valid HMAC-SHA256 signature over a crafted payload and produce a token that passes all server-side checks.

The administrator's MongoDB ObjectID can be obtained in two ways: (a) it is encoded in the base64 payload of any JWT already visible to the attacker (e.g., from network logs or a shared session), or (b) the default credentials admin / admin can be used to log in on a fresh installation and obtain the ID from the response or from the /users list endpoint.

Router initialization at core/controllers/router_v2.go passes all user-management routes through AuthorizationMiddlewareV2, which calls userSvc.CheckToken. Because the forged token passes CheckToken, the forged session is indistinguishable from a legitimately issued one.

PoC

(available on request)

Impact

An unauthenticated attacker with network access to a Crawlab instance can forge a valid JWT for the built-in administrator account. Combined with the platform's ability to run arbitrary spider scripts on all worker nodes, this results in full remote code execution across the entire Crawlab cluster. Every deployment of Crawlab using the default configuration is affected regardless of whether the default password has been changed, because the JWT secret is not configurable.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions