Improving cookie security via SameSite and least privilege access
In the recent LikeCoin progress update, we released an update on improving like.co cookie security. In this article, we will briefly talk about the technical details.
This cookie security issue was found by Xfers penetration testing team. They also worked with us on suggesting possible fixes and mitigation. Many thanks!
To perform Liker ID settings changes and start LIKE pay transaction on a web browser, you would need to sign in on like.co. After a successful sign in, we then store your user session information in your browser as a cookie. Our website will then read this cookie, and recognize that you are a logged in user every time you open our site. However, this cookie is not only recognized in https://like.co, but also in other *.like.co domain, like https://button.like.co which hosts our LikeCoin button widget.
This allows LikeCoin button to also recognize logged in users, and allows them to instantly like, super like or bookmark a LikeCoin button content without extra popup or sign in steps. Note that LikeCoin button is usually embedded as iframe in external websites, like blogs, Medium articles, or personal WordPress websites.
What was the issue?
Since we wanted the LikeCoin button iframe to recognize logged in users, our cookie needs to work inside the external website where the button iframe is placed in. That means we would need to live as a third-party cookie in external sites. For this to work, we explicitly set our cookie’s SameSite attribute as
None . Otherwise browser security feature will block our cookie from being detected in an
iframe outside of
This however opens up a possibility of Cross Site Request Forgery(CSRF) attack. In a CSRF attack, an attacker can host a malicious site with a hidden form that targets like.co. When a user is tricked into submitting the form, browser would submit the request to like.co. Since browser normally attaches a cookie to request that matches its domain, the like.co user session cookie would be attached to this form, performing unwanted changes to Liker ID.
You can also read more about CSRF here.
CSRF attack is a common issue in API. However, there are many ways to mitigate the risk. One of the most recent ones is the SameSite option for cookies. In the recent version of Google Chrome browser, SameSite is set to
Lax by default to protect users against CSRF attacks and improve user privacy.
What is this SameSite option and what does it do? It tells the browser when to send cookie when making web requests. For example, when SameSite option is not set or set to
None, for every
<img> tag, or
<form> that triggers a web request that targets like.co, the user session cookie would be included into the request automatically by the browser. On contrary, when SameSite is set to
Lax, like.co cookie would only be sent when we are actually browsing like.co, or clicking through a link that goes into like.co. This effectively reduce the risk of CSRF to minimal.
However, in our case, we do want to allow cookie to be accessible from the LikeCoin button iframe, which is often embedded inside a third party external website. In this case, setting
SameSite=Lax would prevent our iframe from accessing user session cookie. We then would have to pop up a window every time a user likes an article, which is not really ideal user experience.
So we applied another principle in security, which is least privilege access. Previously, we are using the same cookie for like.co and button.like.co. In our main site, users often need to perform high privilege actions, like modify their user profile and email. However in the button domain, users only want to be able to perform action doable in the button widget, i.e. like, super like, or bookmark.
Our solution to the problem is to split up the cookies, we now continue to use the fully powered cookie in the main like.co site. This cookie allow the following operations, which is basically everything:
and is sent with the
SameSite=Lax attribute set to prevent CSRF attack.
We then created a separated cookie for button.like.co, which has a reduced set of access privilege. This cookie only allows the follow permissions that are required for button functionalities:
In this cookie,
SameSite is set to
None to allow access from LikeCoin button iframe in this less powerful cookie.
We can do this easily because all our APIs have an OAuth2.0 scope definition, part of our company’s open by default culture.
We will continue to work on improving our security while maintaining the best user experience possible.
Thanks Xfers for performing this penetration testing for us. They have spent much time on discussing and analyzing the scope and the testing plan. And they explained in detailed for every issue they have found and discussed different possible solutions with us. Read more about Xfers here.