OperatorResolvers missing @Authorized decorator
LiveOverflow opened this issue · 1 comments
Describe the bug
The OperatorResolvers
are missing @Authorized()
decorators, which allows anybody to query operator names without authentication.
To Reproduce
Send this POST request to the /graphql
endpoint of RedEye:
POST /api/graphql HTTP/1.1
Host: localhost:4000
content-type: application/json
Content-Length: 67
{"query":"query test { globalOperators { __typename id name } }"
}
The response will leak the registered operator names. Example response:
{"data":{"globalOperators":[{"__typename":"GlobalOperator","id":"dev","name":"dev"},{"__typename":"GlobalOperator","id":"analyst01","name":"analyst01"},{"__typename":"GlobalOperator","id":"john.doe","name":"john.doe"},{"__typename":"GlobalOperator","id":"dev2","name":"dev2"}]}}
The mutation also is lacking the @Authorized
decorator, thus allows creating global operators without authentication:
{
"query": "mutation createGlobalOperator($username: String!) { createGlobalOperator(username: $username) { id name } }",
"variables": {
"username": "john.doe"
}
}
To fix, simply add the @Authorized
decorator to all queries.
Background Info
We created this CodeQL query live on stream to find the resolvers without the authorized decorator:
import javascript
from Decorator d1
where
d1.getAChildExpr().(CallExpr).getCalleeName()
in ["Mutation", "Query"]
and
not d1.getParent().getAChild().(Decorator).getAChildExpr().(CallExpr).getCalleeName() in ["Authorized"]
select d1, "is not authorized"
We only found these affected files, the progress resolver is uninteresting. And the issue with the operator resolver is mentioned above.
- RedEye/applications/server/src/store/progress-resolvers.ts
- RedEye/applications/server/src/store/operator-resolvers.ts
This is awesome; thank you for digging into this and writing such a detailed ticket!! The query’s name is a bit confusing on our part; the globalOperators query and mutation are only called on the login page. A single password protects the RedEye server, and populating the user field with operators from campaigns is a great way to match RedEye users with operators using the tool. We should rename that to globalUsers instead, as it’s just a list of usernames to log in with and pre-populated based on campaign data. We could make this secure and still be available for populating the login page!
I’ll need to create an alternate Authorized
decorator, which checks if a password arg is correct. The current Authorized
decorator checks for the cookie set after login.
I’ll look into this Monday and hopefully have a quick fix; thank you again for the excellent ticket!