Brandon T. Elliott
CTF Writeup: picoCTF 2023 - "Java Code Analysis!?!"
The CTF
picoCTF 2023 took place from March, 14th, 2023 to March 28th, 2023.
The Challenge
This web exploitation challenge began with the following description:
Downloading the source code gave us bookshelf-pico.zip
which we could unzip in order to analyze.
We were also provided the credentials user:user
for logging into the website, which after logging in, we were presented with the following:
The Flag Book
The book of interest is the flag
book which appears to require the Admin
role in order to read it.
My initial thought was to capture a request with Burp Suite in order to get a better understanding of how the authorization is being handled.
The Bearer
In our captured Burp Suite request on line 7, we see that the website is using bearer tokens for authorization:
A recursive grep of the unzipped source code using grep -r token
gives us our next lead:
It appears that the website is generating and using JWT tokens, which means that we could potentially be able to create our own JWT token in order to change our authorization level to that of the Admin
role.
We need to take a look at the JwtService.java
source code next.
JwtService
The JwtService source code seems straightforward enough, and we quickly spot line 27 which is where the SECRET_KEY
is being generated:
This is something that we will need to know in order to encode our own JWT tokens, therefore we need to take a look at the source code for the SecretGenerator
class next.
Not So Random
In this source code, it appears that it first attempts to read the key from a local file server_secret.txt
, but if the file doesn’t exist, then it instead uses a hardcoded “random” string of 1234
instead.
We can likely make a safe assumption here that we won’t be able to access this file and that it also won’t exist on the server, so we can continue under the premise that the SECRET_KEY
is going to be 1234
.
Now, we can use this to attempt to encode our own JWT token, but first we should decode the one we already have.
JWT Decode
We can use the website jwt.io in order to decode and encode JWT tokens.
Copying and pasting our current bearer token from the Burp Suite request we captured earlier, we can see the payload of the JWT token.
The Modified Payload
We already know from the error message that we need the role to be Admin
.
However, we likely will need to also modify the userId
and email
fields as well, which we don’t currently know.
A recursive grep of the source code for the word admin
shows a comment within Role.java
which may be good enough…
Inspecting the Role.java
source code gives us a hint that the higher the value, the more the privilege:
We will infer based on this comment and increment the userId
field to 2
.
In our recursive grep, we also see a line .setEmail("admin")
so we will go ahead and set the email
field to admin
just in case this is needed as well.
We also already know from earlier that we should be able to use 1234
as the SECRET_KEY
.
With all of this information, we can now encode a new JWT token using jwt.io again.
JWT Encode
With our new JWT token, we should be able to replace this easily by inspecting the page and navigating to the Storage
section, then Local Storage
:
Now we just need to copy and paste our newly created JWT token into the auth-token
section and also replace token-payload
with our new payload details.
With this in place, all that’s left to do now is refresh the page and read…