So, the website is dependent on nginx, node.js with express.
Example of "/report" endpoint |
One can observe the following endpoints:
/login - GET
In-Short: You type username - and server generates JwT token for you.
Server will also save your current username connected with your
cookie aka JwT token.
If we type - “admin” as the username - the server will do
nothing and login fails.
Ideas:
Vuln in JwT token generation? - would we will be able to
generate our own tokens? Somehow? Does it vulnerable?
Vuln in json GET args validation? If we give a JSON in the GET
arguments instead of string - as the username - can we generate a token for
admin somehow? Maybe kinda due to some inconsistency?
Seems not because validating the type as a string.
But it’s seems like its worth noting this scenario
where we give weird types in the arguments
instead of wanted kinda real one.
/upload - POST
In-Short: Upload files to the server side.
Ideas:
HTML Uploading? Upload HTML file and give the link to the admin of course :)
Not working as Content-Type is constant,
inside the “/files/” endpoint, they always return “Content-Type”
which is one of “.jpg”/”.js”/”.txt”/.. And not “.html”
Upload file and override others? like traversal upload
and override some other kinda server files maybe?
Nope - filename is generated by md5’ing
of some timestamp and the given filename as well.
/report - GET
In-Short: report links to admin OR show links if you’re the admin.
For the admin user - it returns list of URL’s for the admin to look over.
For normal user - it returns an endpoint to upload a link
for the admin to review.
Ideas:
XSS in URL string? aka put /report " onclick=javascript:something
- well it doesn’t works and seems like kinda filtered.
“javascript:” scheme inside reporting URL? starting point -
yep this can kinda work - didn’t tried that though - as it seem like :)
Path-Traversal Vulnerability:
Inside “/files” endpoint - we can get other server files which are accessible.
This endpoint calls - “sendFile” function - which can be given “relative-path”.
They don’t santize our variables - “file”/”user” or token - so cool cool.
They only check that it ends with valid mime type - aka “.jpg” / “.js”
Because how the express.js works,
we can inject url-encoded strings inside the path after “/files/:file…”
We can end it with some
Payload example:
“/files/%2f..%2f..%2f..%2fa.html/user/token.jpg”
Nginx Configuration:
The nginx caching mechanism added, seemed like the most interesting one in here:
What? They added caching for “.jpg” URL’s…
How? Inside nginx configuration - directive of
location ~* ^.(jp[e]g|png)$ { /* ADD_RETURNED_FILE_TO_CACHE }
They used cache key as “$request_method$request_uri” variable.
So… Ideas? Can we inject into cache something secret… and then maybe kinda read it??
Where is The Flag?:
In-Short: shown in "/report" for the admin username only (after JwT validation).
So, if we have admin Cookie / JwT token somehow - we will win absolutely!!!
Hmmm... And what about the Nginx cache? Yes yes, If we can make the admin
click /report and the server will cache it we are winning!
As node.js express endpoint works whenever the starting substring matches -
we can win using the following payload:
Payload link example: /report/a.jpg
The Full-Attack:
Send admin a link to report page &
make it seems like jpg so it will be cached by nginx.
/report/a.jpg seemed to work
Query this page as another user - as nginx already cached this html page before -
we get the previously shown /report HTML file that have been shown to the admin!!!