Always wear a condom

 
In what way do you interact with private information of your users? I mean to information like their full name, email address, living address, phone number or any other kind of information that may be important to them, or information they’d rather keep private.

Today’s case-study talks just about that. Parental advisory: Parental advisory: Explicit content. Just kidding.

We will talk about the way private objects (and I’ll explain my interpretation of the term ‘objects’ later on) should be handled, and then we will see 2 neat examples from vulnerabilities I have found on Facebook (and were fixed, of course).

OK, so you’re mature enough to ask your users to trust you with their email address, home address and phone number. If you are smart, you’ll know that this type of information should be transmitted on the wire via HTTPS, but you’ll remember that sometimes it is also a good practice to encrypt it by yourself.

So your users info is properly transmitted and saved in the database, you assume that your DB is immune to SQL injections or other leakage incidents, and you are thinking of cracking a beer and starting another episode of How I Met Your Mother.
Awesome! But first, I’d like to introduce you to another enemy: The IDOR.

Insecure Direct Object References are your information’s second-worst enemy (after SQLi, of course). Attacker who is able to access other users private objects (such as email address, phone number, etc) could basically expose all of the private data from the server, without “talking” with the DB directly or run arbitrary code on the server.

This is the time to explain my definition to “private objects”. User objects are not just the user’s phone number, email address, name, gender, sexual-orientation or favorite side of the bed. They are also objects that the user creates or own, like the items in the user’s cart, a group that the user is managing or a paint that a user has drew.

The best way to handle private objects is to define them as private and treat them with the appropriate honor.

If you know that only a certain user (or users) should be able to access a certain object, make sure that only those users IDs (or other unique-identifier) are able to access and mess with that object.

How will you do so?

Using a Private Object Manager (POM) of course.
The idea is simple: A one-and-only mechanism that will fetch or change information about private objects only if an accepted identifier has been provided. 
For example: A class that will return the email address of the user ID ‘212’ only if the ID of the user who requested that information is ‘212’).

Sounds obvious, right?
Before posting this case-study I had a little chat with some colleague about the idea of creating a unique mechanism that will handle all the requests to private objects.

He said that this is useless

“Because when a request is being made regarding a certain object, it is the job of the session manager to make sure that the currently active session is messing around with an object it has access to.”

But he was wrong. Very wrong.

Everyone knows Facebook events and groups. Everyone is part of a certain group on Facebook, or got an invitation to a certain event.
Like any other feature of Facebook (and especially after Cambridge Analytica data scandal), groups and events has different privacy levels. They can be public — and then every use will be able to see the event/group name and entire content, private — and then every user will be able to see the event/group name but not their content or secret— and then only users who were invited to join the group or participate an event will be able to see their name and content. Regular Facebook search does not discovers the existence of such groups/events.

Almost every object on Facebook has an ID — usually a long number that represents that object in Facebook’s huge Database, and so do groups and events.

So How can one determine the name or the content of a secret group or event?

I’ve spent a lot of time on the modern Facebook platform trying to fetch information from secret groups and events I cannot actually see, only by their ID.
But I couldn’t find any lead to disclose private information from secret objects. On Facebook’s modern platform. Modern.

And that’s when I started to think

Facebook has many versions to its web platform (and even to its mobile one).
Do they use the same Private Object Manager to access “sensitive” objects like a secret group or event?

No.

Immediately after I’ve started to test the mbasic version of Facebook, I realized that things there work a little different. Ok, a lot different.

I have found 2 vulnerabilities which allowed the name of a secret group or event to be disclosed to any user, regardless the fact that he is not invited or in the group/event. The first vulnerability is here by presented, but the second one is yet to be fully patched (in progress these days):

Always wear a condom

Seriously, these vulnerabilities would have been prevented if Facebook would have implemented a single Private Object Manager to any of its version.
The idea of hoping that a session manager will prevent an insecure access to an object is ridiculous, simply because some objects are so wildly used (like groups on Facebook with millions of members), that the linkage of a user session to that object is high inefficient (and wrong).

Having a one and only filtering mechanism, a condom, to access the most important objects or details, is considered a best practice.

Cheers!

And The King Goes Down


Tokens are great. Well, sometimes.

Today’s case-study will discuss the importance of a Token Manager software.
Well, every site which allows login normally will use a token on each of the ‘critical’ actions it allows users to do. Facebook, for example, automatically adds a token at the end of any link a user provide, and even their own links! This mechanism is called ‘Linkshim’ and it is the primary reason why you never hear about Facebook open redirects, CSRFs or clickjacking (yeah yeah I know they simply not allowing iframes to access them, I’ll write a whole case-study about that in the near future).
Facebook’s method is pretty simple – if a link is being added to the page – add a token at the end of it. The token, of course, should allow only for the same logged-in user to access the URL, and there should be a token count to restrict the number of times a token should be used (hint- only once).

But what happens when tokens are being managed in a wrong approach?

A very famous security company, which still hasn’t allowed us to publish it’s name, allowed users to create a team. When a user creates a team, he is the owner of the team – he has the ‘highest’ role, and he basically controls the whole team actions and options – he can change the team’s name, invite new people to the team, change roles of people in the team and so on.

The team offers the following roles: Owner, Administrator and some other minor non-important roles. Only the owner and administrators of the team are able to invite new users to the team. An invitation can be sent only to person who is not on the team and does not have an account on the company’s web. When the receiver will open the mail he will be redirected to a registration page of the company, and then will be added to the team with the role the Owner/Admin set.

When I first looked at the team options I noticed that after the owner or an admin invites other people to the team via email, he can resend the invitation in case the invited user missed it or deleted it by accident. The resend options was a link at the side of each invitation. Clicking the link created a POST request to a certain ‘Invitation manager’ page, and passed it the invitation ID.

That’s where I started thinking. Why passing the invitation ID as is? Why not obfuscate it or at least use a token for some sort of validation?

Well, that’s where the gold is, baby. Past invitation IDs were not deleted. That means that invitations that were approved were still present on the database, and still accessible.

By changing the passed invitation ID parameter to the ‘first’ invitation ID of the Owner – It was possible to resend an invitation to him.
At first I laughed and said ‘Oh well, how much damage could it make besides spam the owner a bit?’. But I was wrong. Very wrong.

When the system detected that an invitation to the owner was sent, it removed the owner from his role. But further more – remember that I said that sending an invitation sends the receiver a registration page according to his email address? The system also wiped the owner’s account – his private details, and most important – his credentials. This caused the whole account of the owner to be blocked. A classic DoS.

So how can we prevent unwanted actions to be performed on our server? That’s kind of easy.
First, lets attach an authenticity token to each action. The authenticity token must be generated specifically and individually to each specific user.
Second, like milk and cheese – lets attach an expiration date for the token. 2 Minutes expiration date is the fair time to allow our token to be used by the user.
And last, lets delete used tokens from the accessible tokens mechanism. A token should be used only once. If a user has got a problem with that – generate a few tokens for him.

For conclusion,
This case-study presented a severe security issue that was discovered in the code of some very famous security company.
The security issue could have been prevented by following three simple principals – 1) Attaching a token to each action that is being performed by a user. 2) Setting a rational extirpation time for each token. 3) And most importantly – correctly managing the tokens and deleting used ones.

Opening Open Redirects

A few years ago, when FogMarks was not even a tiny idea or a vision in my head, I used to do casual programming jobs on Fiverr.

One of the jobs/gigs I was asked to do is to cause a user in site x.com to be redirected to Facebook.com and then, without an action from his side, to be redirected to a y.com site. I didn’t realize back then why would someone want that kind of thing. Why not just simply redirect the user directly to y.com?
I asked the person why would he want to do such a thing. His answer changed the way I (and after that, FogMarks) treated and took care of Open Redirects. He answered that by forcing a user request to originate from a Facebook URL, the ads engines on y.com are paying much, much more, because a popular site like Facebook has redirected the user to y.com.

Until this answer I treated open redirects as simple security issues, that can’t cause too much damage. I knew that innocent user could get a misleading link like: “www.innocent.com?redirect_out=bad.com”, but I believed that anyone with a tiny bit of common sense will detect such things. Those kind of attacks were mostly used by Phishing web sites to try and simulate that an evil page is actually hosted by the innocent domain (and in this case- of innocent.com).

After this long introduction, I want to introduce today’s topic — a simple solution to open redirects. Facebook did it in their Linkshim system, but I want to introduce a much simpler solution that any of you can use.

Side Note: Who should not adopt this solution? Websites who want their domain to be present on the Referrer header.

Well, the regular ways I have seen to prevent open redirects are creating a token (like YouTube’s and Facebook’s l.php page), forbidding URLs that don’t not contain the host of the website and allowing a user to be redirected only from a POST request.

While creating an exit token is a considered a good practice, handling and taking care of this whole system is pretty much of a headache. You have more values to store in the DB, you should check for expiration times, IP addresses and much more.

Another approach is to forbid redirection to URLs that don’t not contain the host of the website. It is simply wrong. Websites should allow other users to be redirected to another websites, not only to pages within themselves.

Allowing user to be redirected only after an action she initiated (like a click on a button), isn’t always that convenient — to you or to the user.

The Golden Solution

Honestly, the first thing you’ll about to say is: “What? Is this guy crazy?”. But the next thing will be: “Okay, I should give that a try”.

Well, a lot of websites today offers a free URL shortening services. In addition to that — they offer a free modular & convenient API.
Why don’t we use them?!

Instead of carefully creating an exit token, forbidding outside redirects or requiring them to be initiated POSTly (yes, I have invented this verb!), simply translate any outside URL to a shortened URL that a certain URL-Shortening service provides. If you don’t want third party services to store your information, you can build one of your’e own using an open source system.
Allow redirection only to the domain of the shortened URL.
That way you won’t have to worry about open redirects — they will never occur directly from your domain.

Lets say you have a page called ‘redirect_out.php’ with an r GET parameter that a user can control:

www.my.com/redirect_out.php?r=http://bad.com

Normally, you should also include a token in this request, and a mechanism to validate its origin and expiration time.
I say- accept the bad.com URL from the user, and automatically translate it to a shorte.nd/XxXxX URL. Then always allow redirection to shorte.nd. A lot of the shortening services follow security guidelines and will deny redirection to ‘bad websites’, better than you will. Trust me.

If you want to strengthen up this method even more, you can add a whitelist to the shortening service, and configure it to direct requests only to a host which is in the whitelist.

Extra: Benefits of using a well known shortening service

As mentioned before, this solution was offered only to developers who don’t want their domain to be shown up as the referrer. If your’e worried about direct Phishing attacks, it’s a different scenario.

By using a well known shortening service which manages a black or a white list of known “good or bad” domains you’ll earn twice:

  • Your’e domain will not be the ‘one to blame’ who redirected users to ‘bad’ websites (yes, Google knows and checks that too), although you should really care about it too.
  • You’ll increase the phishing protection level of your web. Your users will be able to be redirected to ‘bad’ web sites, but the shortening service will deny it, or at least warn those users (and optionally you too).

Wrap up

This idea may sound a bit bizarre at the beginning, but it requires zero development time (when choosing to use a commercial service). The main idea here is to acknowledge that unwanted redirection of a user from one site to another can occur, and the best way to prevent the worst thing that could happen (that the user will arrive to bad.com) will be to rely on a mechanism to

Let me know your opinion on that.

How Private Is Your Private Email Address?


After reading some blog posts about Mozilla’s Addons websites, I was fascinated from this python-based platform and decided to focus on it.
The XSS vector led basically to nowhere. The folks at Mozilla did excellent job curing and properly sanitizing every user input.

This led me to change my direction and search for the most fun vulnerabilities – logic flaws.

The logic
Most people don’t know, but the fastest way to track logic-based security issues is to get into the mind of the author and to try and think from his point of view. That’s it. Look at a JS function — would you write the same code? What would you have changed? Why?

Mozilla’s Addons site has a collections feature, where users can create a custom collection of their favorite addons. That’s pretty cool, since users can invite other users to a role on their collection. How, do you ask? By email address of course!

A user types in the email address of another user, an AJAX request is being made to an ‘address resolver’ and the ID of the user who owns this email address returns.

When the user press ‘Save Changes’, the just-arrived ID is being passed to the server and the being translated again to the email address, next to the user’s username. Pretty weird.

So, If the logic, for some reason, is to translate an email to an ID and then the ID to the email, we can simply interrupt this process in the middle of it, and replace the generated ID with the ID of another user.

The following video presents a proof of concept of this vulnerability, that exposed the email address of any of addons.mozilla.org users.

Final Thoughts
It is a bad practice to do the same operation twice. If you need something to be fetched from the server, fetch it one time and store it locally (HTML5 localStorage, cookie, etc.). This simple logic flaw jeopardized hundreds of thousands of users until it was patched by Mozilla.

The patch, as you guessed, was to send the email address to the server, instead of sending the ID.

Facebook Invitees Email Address Disclosure

Prologue

When Facebook was just a tiny company with only a few members, it needed a way to get more members.

Today, when you want more visitors to your site, you advertise on Facebook, because everybody is there.

Back then, the main advertising options were manually post advertisements on popular websites (using Google, for instance), or getting your members invite their friends using their email account.

Facebook’s Past Invitation System

When a user joined Facebook at its early days, there was literally nothing to see. Therefore, Facebook asked their members to invite their friends using an email invitation that was created by the registered user.

The user supplied his friends email addresses, and they received an email from Facebook saying that ‘Mister X is now on Facebook, you should join too!’.

Fun Part

As I came across this feature of Facebook I immediately started to analyze it.

I thought it would be nice to try and fool people that a user Y invited them to join, although the one who did it was the user X.

As I kept inviting people over and over again I have noticed something interesting: each invitation to a specific email address contained an invitation ID: ent_cp_id.

When clicking on Invite to Facebook a small windows pops up and shows the full email address of the invitee.

I wrote down the ent_cp_id of some email I would like to invite, and invited him once.

At this point I thought: “OK, I have invited this user, the ent_cp_id of him should not be accessible anymore”. But I was wrong. The ent_cp_id of it was still there. In fact, by simply re transmitting the HTTP request I could invite the same user again.

But the most interesting part of this vulnerability is the fact that any user could have seen the email address that was behind an ent_cp_id.

That means that anyone who was ever invited to Facebook via email was vulnerable to email address disclosure, because that invitation was never deleted and it was accessible to any user. All an attacker had to do next was to randomly guess ent_cp_ids. As I said, old ent_cp_ids aren’t deleted, so the success rate is very high.

Conclusion

When you are dealing with sensitive information like email address you should always limit the number of times that an action could be done. In addition, it is recommended to wipe any id that might be linked to that sensitive information, or at least hash-protect it.

Facebook quickly solved this issue and awarded a kind bounty.

Arbitrary File Upload From A Different Angle


Today we will discuss about arbitrary file uploads, a less common vulnerability, but one of the most powerful out there.

Less common? Why?

Because any platform with sane developers will validate the content type and the file extension of any file they interact with.
But today I want to introduce you with a new validation attitude that I now advise everyone to use – validate the content itself.
If you are expecting an image to be uploaded – expect the content to be suited as a content of an image. If you are expecting an html file – sanitize it and make sure no script tags exist. There are plenty of libraries and tools to do that.

With that being said, a lot of companies and developers I have came across with said to me: “Why should we make all that effort when we can just host the uploaded files on a CDN (Content Delivery Network)?”.
Well, today’s story is just about that.

Freelancer.com was my first interaction with this new attack vector. They allow images to be uploaded as profile and cover pictures, DOC and DOCX files to be uploaded as resumes and far more.

But they also have a nice feature where users can write articles and publish them for others to read.
This form supports images uploads, and those images, as you can imagine, are being uploaded to a CDN (https://cdn.f-cdn.com/).
f-cdn.com is of course the official CDN of Freelancer INC.

The developers here probably assumed that since images are being uploaded to a CDN, no sanitation and content validation should be done – The form does not support HTML – so XSS cannot be done, and the CDN does not allows php files (or any other like it) to be accessed – just download them.

Well, this attitude allowed me to be able to upload a .exe file to the official CDN of Freelancer INC.

Can you imagine a scenario where a hacker will host malicious viruses on the CDN of an official company? I hope you do.
Far more, there is no size limit – any size of a file can be hosted on the CDN (although it may take time to upload it and the connection may be refused eventually).

So remember – using CDNs is not always the best option. Yes, XSSes will not affect users (because of a different domains) and yes, shells and RCEs will not endanger your server directly. But mis-validating the type of files that your CDN hosts might cause your company to a great lost.
Keep that in mind.