Brute-forcing a stay-logged-in cookie

3 min read Easy PortSwigger
Authentication
Contents

On this page

The lab

here is how portswigger describes it

This lab allows users to stay logged in even after they close their browser session. The cookie used to provide this functionality is vulnerable to brute-forcing.

To solve the lab, brute-force Carlos's cookie to gain access to his My account page.

the last few labs attacked the login form directly. this one goes after the thing that lets you skip the login form, the remember me cookie, and the weakness is that the cookie is built from ingredients we can reproduce ourselves.

a stay logged in feature needs to recognise you after your session is gone, so it hands your browser a cookie that proves who you are. the safe way to do that is to make the cookie an unguessable random token that the server stores and looks up. the unsafe way, which this lab uses, is to build the cookie out of your own account details using a known recipe.

once we work out that recipe, the cookie stops being a secret. if the cookie is just your username and a hash of your password wrapped up in a predictable way, then anyone who can guess a password can construct the matching cookie for that account without ever logging in. so the attack is not really brute forcing a cookie at all, it is brute forcing passwords offline and assembling the cookie each guess would produce, then seeing which assembled cookie the server accepts.

we log in as wiener with the stay logged in option ticked, which sets a stay-logged-in cookie. examining it, the value is Base64 encoded, and decoding it gives:

wiener:51dc30ddc473d43a6011e9ebba6ca770

so it is our username, a colon, and a thirty two character hex string. that length and character set is the signature of an MD5 hash, and since the plaintext half is clearly our username, a fair guess is that the second half is an MD5 hash of our password. we confirm it by running MD5 over our own password peter and matching the result. that pins down the recipe:

base64(username + ':' + md5(password))

every piece of that is something we control or can compute, which is exactly what makes it brute forceable.

we log out, find the most recent GET /my-account?id=wiener request, highlight the stay-logged-in cookie value, and send it to intruder so that cookie is our single insertion point.

rather than feeding raw cookie strings, we let intruder build each cookie for us from a password using payload processing rules. we start with our own password as a single payload to prove the chain, and add these rules in order, applied to each payload before the request goes out:

  • hash the payload with MD5
  • add the prefix wiener:
  • Base64 encode the whole thing

that reproduces the recipe exactly, so intruder turns a plain password into the precise cookie the server would have issued for it.

we need a way to tell a working cookie from a failing one. the account page only shows the update email button when you are properly authenticated, so that button's presence is a clean success signal.

in the settings we add a grep match rule for the string Update email, so any response that is a genuinely logged in account page gets flagged in the results. we run this first pass against our own account and confirm the flagged row lines up with the cookie built from our real password, which proves the whole processing chain works end to end.

Step 4 - point the attack at carlos and solve#

now we repeat the attack with three changes so it targets the victim instead of us:

  • swap our single password for the candidate password wordlist
  • change the id parameter in the url from wiener to carlos
  • change the add prefix rule to carlos: so the cookie is built for his account

with those in place, intruder works through the password list, hashing each one, wrapping it as carlos: plus the hash, Base64 encoding it, and sending it as the cookie. almost every attempt comes back as a logged out page, but one response carries the Update email string, meaning the cookie we forged from that password is the real one for carlos.

that flagged request is a valid stay logged in cookie for carlos, so loading it lands us straight on his account page with no password ever entered.

with this, the lab is solved!