Osanda Malith wrote up this clever article on how he bypassed 3rd-degree profiles on LinkedIn. Learn more about Osanda and the exploit below.
- Check our his profile: https://bugcrowd.com/Osanda_Malith/
- Blog: http://osandamalith.wordpress.com/
- Twitter: @OsandaMalith
I was in the middle of submitting an assignment to my college when I got an email from Linkedin displaying the people who viewed my profile. When I logged in I saw a random profile who was a 3rd-degree relation. I really wanted to view the profile, and at the very same time I was viewing Olivia Maree’s LinkedIn profile - she is a manager at Bugcrowd and a good friend of mine. I always keep an eye on the URLs ;) so after viewing both profiles and analyzing the web application carefully that morning I got some tricky ideas in my head.
I will explain from the beginning so that you can understand the process well. Let’s start fuzzing.
GET /profile/view?id=283222986&authType=name&authToken=HM8p&trk=prof-sb-browse_map-name HTTP/1.1
She is already connected in my profile so after having a look at the GET request the “authType” parameter has a value of “name” and the token parameter is “authToken”, it has a value of “HM8p”. This is her profile.
LinkedIn has option to export the profiles as PDF files. Next let’s have a look at how the web application accepts the Export to PDF option.
GET /profile/pdf?id=283222986&locale=en_US&authType=name&authToken=HM8p&pdfFileName=OliviaMaree&disablePdfCompression=true&trk=pdf_pro_full HTTP/1.1
After passing this GET request to the application we can download the profile in PDF format. But notice the “authType” and “authToken” parameters carefully. Their values are same in both GET requests we sent. The token “HM8p” is generated for the value “name” in the parameter “authType”.
I think now you can understand that the token is same for all the requests made to the application and this token should be valid for the “authType” parameter. This analysis is for the profiles that are already connected to my account. Now let’s have a look at the other profile whose position is at the 3rd-degree. As I am a free user I have no rights to view this profile, the full name and of course can't connect to them. I need to upgrade my account for all of these to be done.
Let’s have a look at how the application handles the GET request.
GET /profile/view?id=1589xyzz&authType=OUT_OF_NETWORK&authToken=MNn5&locale=en_US&srchid=2898459041388819694727&srchindex=24&srchtotal=176605&trk=vsrp_people_res_name&trkInfo=VSRPsearchId%3A2898459041388819694727%2CVSRPtargetId%3A15899350%2CVSRPcmpt%3Aprimary HTTP/1.1
This time the parameter “authType” has a value of “OUT_OF_NETWORK” and token corresponding to that is “MNn5”.
I noticed that 3rd-degree profiles too had the option Export to PDF. But this will let us view an incomplete PDF with only the Summary. Too bad right? L Let’s have a look at that GET request.
GET /profile/pdf?id=1589xyzz&locale=en_US&authType=OUT_OF_NETWORK&authToken=MNn5&pdfFileName=LaurenS%2E&disablePdfCompression=true&trk=pdf_pro_full HTTP/1.1
Yes my guessing is right. The token generated is same for the value in the “authType” in every request we make. This is the incomplete PDF for free users.
Now let’s fuzz the request and see. I did many tests based on the request on the Export PDF and with the original but finally this is what I came up with it. I thought maybe changing the “authType” parameter to the value “name” I know that this is incorrect as we don’t know the exact token for the value “name”, but let’s give it a try. ;) I used “name” because it is the default value passed for profiles already connected in my account.
GET /profile/view?id=1589xyzz&authType=name&authToken=MNn5&locale=en_US&srchid=2898459041388819694727&srchindex=24&srchtotal=176605&trk=vsrp_people_res_name&trkInfo=VSRPsearchId%3A2898459041388819694727%2CVSRPtargetId%3A15899350%2CVSRPcmpt%3Aprimary HTTP/1.1
The page loaded fine no big change to be seen but to my surprise I saw that the token had changed in the Export-PDF request. Let’s have a closer look.
GET http://www.linkedin.com/profile/pdf?id=1589xyzz&locale=en_US&authType=name&authToken=4ZoF&pdfFileName=LaurenS%2E&disablePdfCompression=true&trk=pdf_pro_full HTTP/1.1
GET /profile/view?id=1589xyzz&authType=name&authToken=4ZoF&locale=en_US&srchid=2898459041388819694727&srchindex=24&srchtotal=176605&trk=vsrp_people_res_name&trkInfo=VSRPsearchId%3A2898459041388819694727%2CVSRPtargetId%3A15899350%2CVSRPcmpt%3Aprimary HTTP/1.1
As we got a valid token for “name” W00t! we have her full name, full profile and can connect to her profile.
For greater clarity watch this proof of concept video I made. I made it very simple excluding the fuzzing parts.
After researching this I reported this issue directly to LinkedIn Security using their PGP key. Now the issue is patched and I am getting a small token of appreciation ;) Thank you very much guys. I'm glad I've been able to responsibly report this to you. This is one of the best logical bugs I've ever researched.
And as of this month I'm happy to say that I have reported vulnerabilities or security issues in more than 40 organizations with responsible disclosure policies. I really respect those guys for having a responsible disclosure policy. Some people don't care about security because they don't like to admit their weaknesses. But a vulnerability is a vulnerability no matter the size of the risk. Thank you all for humbly responding to my reports and fixing them in a timely manner. I am still young and I've got many things to explore and learn. I’m happy to have achieved as much as I have at this age. In every bug I've found there is a story to share. I hope to increase my knowledge further in the field of computer security.
Lastly, I would really like dedicate this to my friends who have been there with me since I started: my buds Hood3dRob1n, Gerardo Salazar, Billie Kei, Matt Andreko, Kasp3r, Alan Marecc and all my friends (some don't like to mention their names) who've cared for me. Without you guys my life wouldn't be so bright. Also I dedicate this to my recent friends Muhammed Gazzaly, Ajay Negi, Fraph Core, Yap Ahmad Ashraff, and Jay Turla. I hope we can meet someday. Some things are hard to explain.
Thanks for the insightful bug post Osanda! Curious about learning more about Bugcrowd? Check out our how-it-works page.