BugForge Write-Up 3/14/2026
- icanhaspii
- Mar 15
- 5 min read
BugForge Daily Challenge 3/14/2026 - OtterGram

Hint: GraphQL.

Note:
If there is an admin account active for a lab, the credentials are admin:admin123
Also, my write-up is basically me just following along with the @PawPawHacks/Tom Fieber video walkthrough.
I launched Caido.
I checked to see if there was an admin login using the set/known creds, but there was not.
I created a user account, and once logged in, the app appeared to behave a lot like InstaGram. I could "like" messages, etc. so I poked around a bit, trying to see everything I could do with the app in order to generate some traffic to view via the proxy. I "liked" a few posts, and created a couple of comments:

I wanted to take a closer look at the "Profile" options, so I clicked into that by hitting the button that looks like the bust of a person:

The Profile has the ability to "Edit Profile" and also to view "Your Analytics":

Over in my Caido proxy window, from going into my "Profile", I now see a line with "POST /graphql" traffic, and so I clicked on that to view the GraphQL "Request" and "Response" panes:

In that "Request" pane, there should be a "query" at the bottom with some values. @PawPawHacks/Tom Fieber explains in his walkthrough, that In GraphQL, "Query" tends to be used to get data, and "Mutation" is used to add, update, delete, etc.
{"query":"\n query {\n analytics(userId: 4) {\n userId\n username\n totalPosts\n totalLikesReceived\n totalCommentsReceived\n totalLikesGiven\n totalCommentsMade\n }\n }\n "}
Next, we will be using the "GraphQL Analyzer" plugin for Caido. If you don’t already have this feature, you will need to install it as a PlugIn. I believe the free version of Caido allows up to 3 Plugins, any more than that you will need to get the paid version of Caido. To get the "GraphQL Analyzer" PlugIn for Caido, perform the following steps:
a) Select “PlugIns” from the lower left-hand side of Caido (under their logo).
b) At the top Menu Bar, choose “Official”.
c) Type "GraphQL Analyzer" (without quotes) into the Search Bar.
d) Look for “JWT Analyzer” by Amr Elsagaei.
e) At the bottom of the screen, you may need to select the Disclaimer (at your own discretion).
f) Then hit the “Install” button:

Now you should be able to utilize the "GraphQL Analyzer" for Caido. You might need to hit the Plus (+) button to have it populate next to “Pretty” and “Raw”...and then hit off-white X to close (which also saves):

So now, back over in our Caido proxy, we are again at the "POST /graphql" line of traffic. In the "Request" window, choose the "GraphQL" button/view that's from our "GraphQL" Plugin. Once in that window, select the tiny "Send to Scanner" button and you will be taken to a "Schema Explorer" window:

Once in the "Schema Explorer" window, hit the drop-down (>) to view the API data types:

Next, select the "Queries" drop-down and you should see that we have two queries, "analytics" and "user". What we saw in our original request was the "analytics", so let's select the "user" and then hit the tiny, "Copy to Clipboard" button in the upper right-hand corner.
query User($id: Int!) {
user(id: $id) {
id
username
password
full name
bio
role
}
}

Now, back over in the Caido proxy window at our original "POST /graphql" traffic, highlight that line, then right-click and select "Send to Replay -> Default Collection":

Over in the "Replay" tab, I hit the "Send" button so that we have a baseline of what the traffic "Response" looks like:

Next, in the "Request" pane of the "Replay" tab, highlight everything after the query colon, except the first and last curly braces, and then hit "Delete":
{"query":"\n query {\n analytics(userId: 4) {\n userId\n username\n totalPosts\n totalLikesReceived\n totalCommentsReceived\n totalLikesGiven\n totalCommentsMade\n }\n }\n "}

Next, you're going to want the Caido "Convert Tools" plugin, but that tool was "locked" for me, even after installing it, so it might be for paid customers only, or there might be a way to use the Caido "Match & Replace" feature instead, I'm not sure, but we can also do this conversion another way. To "escape" the JSON blob, go to: https://www.freeformatter.com/json-escape.html and paste in what we had copied to our clipboard earlier.
Now, hit the "Escape JSON" button and you should see the "Escaped" JSON in the window below. Copy that to your clipboard:

{
"query":"query User($id: Int!) {\r\n user(id: $id) {\r\n id\r\n username\r\n email\r\n password\r\n full_name\r\n bio\r\n role\r\n }\r\n"}
Next, back in the "Request" pane of the Caido "Replay" tab, paste-in the contents of your clipboard (the "escaped" JSON).
Now, hit the red "Send" button, but you should see an error: "message": "Syntax Error: Expected Name, found .",

To circumvent that error, we can add:
{
"query":"query User($id: Int!) {\r\n user(id: $id) {\r\n id\r\n username\r\n email\r\n password\r\n full_name\r\n bio\r\n role\r\n }\r\n}",
"variables":{
"id":1
}}

Now, hit the red "Send" button again, and we should see we get back some juicy data, including password hashes:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Content-Length: 226
Content-Type: application/json; charset=utf-8
Date: Sat, 10 Jan 2026 17:24:50 GMT
Etag: W/"e2-tTDrymA39/8wRhSGqzc8ZstzrLU"
X-Powered-By: Express
Connection: close
{
"data": {
"user": {
"id": 1,
"username": "otter_lover",
"email": "otter@example.com",
"password": "$2a$10$F8GpOwW3ZS/ImilDBpCETea0Unah6tYtIjonFCLXzG7VTFB2AFgKG",
"full_name": "Otter Enthusiast",
"bio": "I love otters! 🦦",
"role": "user"
}
}
}
Next, let's increment our variable id number (that we just added over in the "Request" window, from 1 to 2.
Now...drumroll please...because once we hit that red "Send" button one last time, we should get the "admin" data that includes the "password", which contains the flag!!! W00t!

bug{********************************}
Endnote:
To do the above in Burp, you would use the following tool: “InQL GraphQL Scanner for Burp”. PortSwigger states: “You can install BApps directly within Burp, via the BApp Store feature in the Burp Extender tool. You can also download them from here, for offline installation into Burp. You can view the source code for all BApp Store extensions on our GitHub page.”
https://portswigger.net/bappstore/296e9a0730384be4b2fffef7b4e19b1f.
The following steps are how I installed “InQL GraphQL Scanner for Burp”:
I found this by going into the Burp "Extensions" tab and once in there, selecting the "BApp Store".
Next, I searched for "inql" (without the quotes).
Then, once I highlighted that line, I had an option in the right-hand window to hit the "Install" button.
Once installed, I went back to my Proxy traffic and now, if I highlight the "POST /graphql" line, I see a "GraphQL" tab.
Next, go back to the "Pretty" tab in the Burp "Request" window, and right-click and select, "Send to Repeater".
Now, over in your "Repeater" tab, right-click anywhere inside your "Request" window, and at the top, select "GraphQL -> Set Introspection Query" and now you should see all sorts of information about the data being sent.
Next, hit the red "Send" button, and we get a bunch of data returned over in the "Response" pane.
Now, right-click anywhere inside the "Response" window, and at the top, select "GraphQL -> Save GraphQL queries to sitemap".
Now, over in the "Target" tab, you should see a drop-down menu for graphql. Right-click and select, "Send to Repeater".
Now, over in the "Repeater" tab, hit the red "Send" key, and we get "User not found" as there's no user with id:0.
If we manually change the user number to id:2, and now hit the red "Send" button, we get the "admin" data that includes the "password", which contains the flag!!! "password":"bug{********************************}",
##### End of Report #####


