LinkedIn Cookie Vuln.
LinkedIn is a business-oriented social networking site. Founded in December 2002 and launched in May 2003, it is mainly used for professional networking. As of 22 March 2011, LinkedIn reports more than 100 million registered users, spanning more than 200 countries and territories worldwide.
There exists multiple vulnerabilities in LinkedIn in which it handles the cookies and transmits them over SSL. This vulnerability if exploited, can result in hijacking of user accounts, and/or modifying the user information without the consent of the profile owner.
Executive Summary
Name: LinkedIn SSL Cookie Vulnerability (SESSION and AUTH TOKEN)
Severity: High
Host(s): https://www.linkedin.com and http://www.linkedin.com
Author/Contact Person: Rishi Narang ( Twitter: @rnarang | Mail: rishi[at]wtfuzz.com | LinkedIn: http://in.linkedin.com/in/rishinarang )
PS: I received some comments recently through different mediums & channels, so, if you need any details or clarifications please contact me through Twitter and/or Mail address as mentioned above.
Background Information
LinkedIn can be accessed over HTTPS and HTTP connections. The sign-in pageif accessed on HTTPS, redirects you to HTTP on successful authentication. By default the welcome page stores the following important cookies (highlighting only the SESSION and AUTH TOKEN in scope),

After successful login (over HTTPS or HTTP), the value of cookies should change, specifically, the JSESSIONID and AUTH_TOKEN. The SESSIONID remains the same no matter what or if the browser exits, the server sends a new SESSIONID. Now, lets see how leo_auth_token changes after successfully authentication and login …

JSESSIONID
Ideally this cookie is used for tracking session and thus it has an ID generated to track that session in the application and server logs. As per information available online, JSESSIONID cookie is created/sent when session is created. Session is created when your code calls request.getSession() or request.getSession(true) for the first time. If you just want get session, but not create it if it doesn’t exists, use request.getSession(false) — this will return you a session or null. In this case, new session is not created, and JSESSIONID cookie is not sent. This also means that session isn’t necessarily created on first request; you and your code is in control when the session is created.
Example: JSESSIONID="ajax:2960939797451683300" . And, the syntax for this session id is –> ajax:<19 digit code>
LEO_AUTH_TOKEN
There is not much information available on this cookie in my knowledge, but I could relate some sections as following.
Example: leo_auth_token="LIM:118607520:a:1305884679:b42ee51919add89581a0b49ebe1e420dbb93a468" (Only highlighted key reference available below)
- 118607520: This is the User ID. It can also be verified when viewing someone’s profile. It traverses in the traffic unencrypted and is also available in GET requests.
- 1305884679:
This is ‘perhaps’ (guess analysis) the user login counter (global). I am not sure if it resets or its just progressive but, surely with every login it increments by 1. Special thanks to Julio for clarification that this is a Unix Timestamp of the time user logs in. (Refer: http://www.onlineconversion.com/unix_time.htm). This Unix Timestamp will also decide the expiry date of the cookie. (1 year from this time which is too much for an attacker) - b42ee51919add89581a0b49ebe1e420dbb93a468: This is a approx. 40 character long hexadecimal string. It can be smaller or larger and is not fixed in length. I am still working if this can be decrypted or can be related/tied to some part of the session.
In general these two (2) cookies are enough to verify a session, and both the cookies have to be defined in "quotes" and here is a sample POST request (used in LinkedIn status update) for reference,
POST http://www.linkedin.com/share?submitPost= HTTP/1.1
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Cookie: leo_auth_token="LIM:118607520:a:1305884679:b42ee51919add89581a0b49ebe1e420dbb93a468";JSESSIONID="ajax:2960939797451683300"ajax=true&postText=TEST_STATUS&postVisibility=EVERYONE&csrfToken=ajax:2960939797451683300
This request results in changing the User Status on the profile page. So, what and where is the vulnerability here?
Vulnerability Information
There are two (2) vulnerabilities in reference to the cookies (communication channel and session lock) as explained below,
1. SSL cookie without secure flag set
It means that all the cookies including the JSESSIONID and LEO_AUTH_TOKEN are available in plain text over unencrypted channel of communication. These cookies appear to contain session tokens, which may increase the risk associated with the authentication procedure. One should review the contents of the cookies to determine their function and the need for encryption.If the secure flag is set on a cookie, then browsers will not submit the cookie in any requests that use an unencrypted HTTP connection, thereby preventing the cookie from being trivially intercepted by an attacker monitoring network traffic. If the secure flag is not set, then the cookie will be transmitted in clear-text if the user visits any HTTP URLs within the cookie’s scope.
Impact
An attacker may be able to perform an MITM attack, and thus capture these cookies from an established LinkedIn session. Even if the domain which issued the cookie does not host any content that is accessed over HTTP, an attacker may be able to use links of the form https://www.linkedin.com to perform the same attack.
Workaround
The secure flag should be set on all cookies that are used for transmitting sensitive data when accessing content over HTTPS. If cookies are used to transmit session tokens, then areas of the application that are accessed over HTTPS should employ their own session handling mechanism, and the session tokens used should never be transmitted over unencrypted communications.
2. Cookie Expiration & Session Handling
It means that the cookie for an authenticated session is available even after the session has been terminated or way beyond the date of expiry (instead compared to session logout, it is valid for 1 year). There are examples where cookies are accessible to hijack authenticated sessions. And these cookies are months old (literally). As a result, in just 15 minutes, I was successfully able to access multiple active accounts that belong to individuals from different global locations. They would have login/logged out many a times in these months but their cookie was still valid.
Even though the cookie expiry date is mentioned still the cookies are valid. Why does LinkedIn keeps the cookie active even if the user has "logged out" and closed the session? Worse, when the same has been done a hundred times!
Impact
As a result of valid cookies, an attacker can sniff the cookies from clear-text session (explained above), and then use it to authenticate its own session. He can then compromise and modify the information available at the user profile page.
Workaround
The expiry date/time should be locked with either a fixed ‘period’, or user’s session logout or IP etc. In absence of a fixed and reasonable expiration time period (1 year is not reasonable/acceptable), a cookie is active even after months and year of its authentication. Define expiration as the end of session or till the JSESSIONID is valid.
Curious case of JSESSIONID
As I mentioned about the JSESSIONID above, ideally the session should be mapped with this ID, and if tampered with, should disconnect the session. At least, I would believe it to work this way! But now, even if you change the JSESSIONID to ajax:0000000000000000000 (ajax followed by 19 digits) the session is still valid and the server continues accepting requests with this JSESSIONID.
Even if it has nothing to do with session but only tracking, tinkering with SESSION id surely will dangle the tracking at the server end.
LinkedIn Status Update Bash Script (Download Here)
Here is a small script to update the status at the LinkedIn profile page through command-line. It takes the input as "LIM:XXXX" cookie value and new status update.
#!/bin/bash
clear
echo ""
echo " =================================================="
echo " # LinkedIN Status Update Script #"
echo " # —————————– #"
echo " # Author: Rishi Narang (rishi@wtfuzz.com) #"
echo " # — WWW.WTFUZZ.COM – #"
echo " # #"
echo " =================================================="
echo ""echo -en " – Auth Cookie (Format – LIM:XXXX): "
read LIMecho -en " – New Status: "
read UPDATEcurl -s -b "leo_auth_token=\"${LIM}\";JSESSIONID=\"ajax:0000000000000000000\"" -d\
"ajax=true&postText=$UPDATE&postVisibility=EVERYONE&csrfToken=ajax%3A0000000000000000000"\
http://www.linkedin.com/share?submitPost= -o linKIN.tmpecho ""
OUT=`cat linKIN.tmp | grep "SUCCESS" | wc -l`
DUP=`cat linKIN.tmp | grep "DUPLICATE" | wc -l`if [ $OUT -eq 1 ]
then
echo -e "MSG: Status updated successfully!\n"elif [ $DUP -eq 1 ]
then
echo -e "ERROR: Duplicate Status! Please enter a new status.\n"
exit
else
echo -e "ERROR: Please try again later.\n"
fi
rm -rf linKIN.tmp
echo ""#EOD


Hi!
This is a great article, bue let me comment you one thing.
In the LEO_AUTH_TOKEN, the second part is a Unix timestamp of the time the user log in:
1305884679 -> Fri, 20 May 2011 09:44:39 GMT
You can see it here:
http://www.onlineconversion.com/unix_time.htm
Best regards!
Thanks a lot Julio. I appreciate your input and will correct it. That’s the reason it was being incremented :)
Cheers!
just some input,
this behaviour is not new per linkedin.
also i didn’t tried updating a status however adding a friend or responding to message will always push you back to the authentication prompt not sure if it could als obe circumvated……..
Hello, I just checked my cookies on Safari, and the Linkedin cookie in question Leo_auth_token expires June 11, 2011, however, there is one cookie “bcookie” a linkedin cookie that expires in 2078- perhaps you can tell me if that cookie is an issue. May 23, 2011 date comment date
Hi Cheryl,
Please login/logout from your linkedin session, and then check back the new cookies. May be you are checking the old session that is already available. Or do one thing .. Check the leo_auth_token and NOT the s_leo_auth_token. There you will find something like LIM:xxxx:a:xxxxxxxxxx:[long string of hex chars]. Take the italicized number (the long number perhaps 10 digits just after “a”) and verify it against http://www.onlineconversion.com/unix_time.htm. This is the time the cookie registered in your browser. Check it and see what time does it show.
Cheers!
3rd String looks like MD5 to me
Nevermind, I didn’t see string size.
For the last argument, you may be interested in this link which gives a large sample of hashed values: http://www.insidepro.com/hashes.php
you are so smart or you think so.
everyone in this world knows about this kind of vulnerability in every possible social site.
are you new to this world?
========
Very good analysis and findings…..
ok now, y did u block my comment?
Hi Rishi,
nice observation. however besides updating status are you able to do anything else with the cookies….
So what’s so special about this discovery ? Every cookie based web-app is vulnerable to this flaw. I can’t believe someone of your caliber didn’t get that the 10-digit string was timestamp in Unix format. Sucks !
@Praveen – Glad someone from LinkedIn responded. Okay, so you are insecure because others are insecure. That’s a nice answer to say you are proactive for privacy and security. So, your point is to find a unique vulnerability which is not there in competitive portals. I never mentioned that your vulnerability is alienated. Its very much belonging to the social sites issues. Appreciate your comments but still don’t wanna flame anything here ..
Still, for your reference, a small example is – your “other social site” is not redirecting me from my chosen “HTTPS” to “HTTP” without my consent. Maybe you should try fixing it before welcoming me to this world! When I start my session on HTTPS, authenticate it then why LinkedIn redirects me to HTTP when I click any menu-tabs.
Then, “other social site” has usually set the auth cookie expiry to “End of Session” rather than “1 year”.
I expected LinkedIn to lead the social networking competition rather than following the lame practices of “other social sites”. I personally have high hopes and expectations from LinkedIn like other Senior Execs, rather than teenagers oriented “other social sites”. Other sites are already in much of a trouble with privacy issues etc.
Take it with a positive attitude for better security, or keep following others’ flaws on the foot prints of their software engineers …
Thats really a good article and the explanation was very brief that even a fresher can understand what exactly happening over backend in LinkedIn. Thanks for the share – keep it up
Hats off to Rishi Narang for the findings and big kick to Praveen.
Not long back, image script vulnerability in orkut was discovered. Which was big security threat back then. Someone needs to discover the threats and deserves the appreciation.
i think linkedin should hire him as a consultant
Hi Rishi -
I’m overwhelmed by the LinkedIn security issues, but forced to address the issue because I’m sure someone has accessed my account. Could you once again repeat the simplest way for me to confirm my suspicions , and safeguard my account?
Thank you for your help and patience! I am still learning about internet security and have a loooooong way to go.
Hi Rishi, Thank you, it makes some sense. I had always suspected that some people know what I am doing on Linkedin, like what is sent in my inbox, and who I am trying to get connected. Even lately got connected with someone I never invited or accepted the invitation. I am an ordinary user of Linkedin and don’t have your kind of expertise. I had set the browser only to accept the cookies for the session, can this help?
I think this has been patched. Isnt’t it?
Regards,
Kirtar