As we all know, our session information is stored in the cookies 🍪 . Let’s begin by taking a look at what cookies are stored by facebook. For manipulating cookies i’ll be using EditThisCookie chrome extension, make sure you enable the extension in incognito mode as well.
Open up facebook in incognito window and take a look at the cookies using EditThisCookie. Since we are initially logged out, none of these cookies correspond to session specific data. Now open up a normal chrome window and log in to facebook and you’ll notice that now we have a few more cookies added to the list
The session specific cookies here are c_user and xs
c_user stores the user id and xs stores the session secret, these two cookies as a combination determine the state of user as logged in or not. If you try to delete/edit any of these, you’ll be logged out.
Who sets these cookies?
Log out of facebook, open up chrome dev tools, click on preserve logs and login again. If you take a look at the response headers for the login call in network requests, you’ll notice that in case of a successful login we receive a set-cookie header for c_user as well as for xs, this tells the browser to set this information in the cookies and attach this information to all the future requests. This way once we log in, all the future requests (except the ones requesting public assets) will have the session information. Thats how session state is added to a rather stateless REST architecture.
Also, do note that in the response headers xs is set as a httponly cookie.
Try running document.cookie in the console of a logged in facebook window and you’ll notice that you are able to see c_user but xs cookie is not accessible via the command. If you try to toggle the httponly flag on xs cookie via EditThisCookie and save it, you’ll notice that document.cookie now outputs the xs cookie as well (do remember to toggle it back on 😉).
💡 Adding c_user and xs cookies is all it takes to tell the facebook servers that you are logged in.
Make sure you have a logged in facebook window and one fresh incongnito window with logged out facebook page. In the incongnito window, click on EditThisCookie extension to add two new cookies, name the first one c_user and the second one xs. Copy and paste the values for each from the logged in window, save them and hit refresh. You’ll be logged in.
Can we try Man in the middle attack (MITM) to get the value of c_user and xs cookies?
Since all session specific future requests after a successful login contain the c_user and xs cookie, can we just sit in the middle and intercept the network calls to access these cookies? Well, the answer is no and the reason is pretty straightforward, facebook operates over https which ensures that all the data sent over the network is ssl encrypted, including the headers.
Even if you as an attacker force facebook to work over http, c_user and xs cookies have secure flag switched on which ensures that these cookies will work only over https, this adds to the security.
Let’s try Brute Force 💪
As you might know, facebook has a forgot password page where you can try to reset the password via one time code which is sent to email or mobile. It is a 6 digit code which means we could try forcing our way in by exhausting all 1 million combinations using a script, but this doesn’t work because facebook blocks this action after some 10–20 attempts.
💡What if we try to brute force the xs cookie for a particular c_user
Looking at the image below, when i send a get request without headers, i receive the log in page where jewelButton (used for notifications) does not exist and once i send the c_user and xs in headers, i go to the home page.
The format for xs cookie is as follows [Refer]
c: character including special characters
d: digit [0–9]
After omitting the non mandatory characters, xs cookie looks like dd%3ccccccccccccccc%3A%3Adddddddddd
The timestamp is 10 digits long as compared to the one we see when we run new Date().getTime() which is the time in milliseconds.
As soon as you log in, Facebook validates the request and stores the login time upto seconds precision (in form of a 10 digit timestamp). This timestamp is attached to the xs cookie.
If we were somehow able to apply some heuristics for the login time, we are still left with 15 characters and 2 digits which amount to ~100 * 256¹⁵ combinations (if you know the timestamp precisely!).
You could ideally try to brute force it by jumping proxies but it will take eternity before you hit the correct xs value.
I’ll end this article by hoping that you found it interesting (consider sharing it in that case!), If i have missed something somewhere or you have something to add please do post it in the comment.
Keep reading, keep learning!