Hello, this post is about how I could take-over any account of Kolesa’s websites using Single Sign-On. There was an insecure JSONP call which could break the security of the entire SSO mechanism.
JSONP is a method for sending JSON data to other domain.
In this authentication model since a domain can not set an authentication cookie
for the others, an authentication token
should be transferred between the authentication server
and other domains. Considering the orange box in the image above, each site should save a cookie after verifying the authentication token
. In addition, authentication server
also saves its cookie, so after a couple of HTTP requests I found the authentication cookie name for each Kolesa website:
The JSONP call is used for further authentications. If a user has already logged-in in any of three websites, a JSONP call is made to authenticate the user in. The reason for this action is the ease of implementation. Since the origins of domains are different, the Kolesa websites should have implemented the Cross Origin Resource Sharing
to transfer the authentication, but they’ve decided to use JSONP to avoid CORS setup.
The point is, once a user is logged in for examplekosela.kz
, they have a ccid
cookie in id.kolesa.kz
, an authentication token to transfer the authentication, and a ssid
cookie in kosela.kz
. After that, if the user wants to log-in in the other websites, it happens by just a click, since id.kosela.kz
has authentication cookie, it immediately generates authentication token
and the user will have the corresponded authentication cookie
on the website.
Based on the picture above, phase 4 shows how the JSONP call is made and how the authentication token
can be turned into authentication cookie
in a domain. The cause of JSONP call:
If the user has already been authenticated by id.kolesa.kz
, the following response is expected:
HTTP/1.1 200 OK
Server: openresty/1.13.6.2
Date: Mon, 19 Aug 2019 16:43:26 GMT
Content-Type: text/javascript;charset=UTF-8
Connection: close
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Backend-Server: auth-be3.alaps.kz.prod.bash.kz
X-Bug-Bounty: Please report bugs and vulnerabilities to [email protected]
Content-Security-Policy: frame-ancestors 'self' http://webvisor.com https://webvisor.com
Strict-Transport-Security: max-age=31536000
Content-Length: 627window.xdm = {
sess: {
is_authenticated: 1,
token: 'xG3ROFWcb7pnXSnMr8MkaBvH01pLlCHqn0sPt0PVL6BBWYdQPdvA31tBi6dLB5njv5jhMW3y/cGBMRB9LC/69zv867wweaDhkxX6arGVzYDy2q+J52nkOQJ+62rR9wLPYJGyEpNGWeOBSp12vugXZUPq2RA6FMptbNkGQpJFjAclXSzduj7wJJgAUONMj3mkkElM1nWmIllrl5zDEz6s7077E4ibx//BvnfZ9AIC/9b2PB+QzVKOnSzzcr9wSXqta9TEDHvjopqbUd4UE2xSMRSj/zxPQlCba5632hcIXnzZB3A8fvahvf2Hm5ssuC+cwuKU8pAdE/qcGQSJKdhpYXxntGkQiLdEAliyCq+fahS4itb6HlFH/+H20RsZA+cjyaF7ntnW5tYY31vxJXovrR3oinaj9YDSzoCZYMDYPJMdk+HuZhRuxxEl8abuNlGD0aCt2GCPV7GY0J9Ma7AcPw=='
}
};(function ($) {
"use strict";$.xdm = window.xdm;
}(jQuery));
As it’s been seen there is an object named sess
containing the two properties named is_authenticated
and token
. This object is responsible to transfer authentication. At this moment the user has authentication token
but not authentication cookie
of the current website, so the second call is made:
The JavaScript code:
The question is, an arbitrary origin can extract the authentication token
? of course, it can because the JSONP call bypasses the Same Origin Policy.
The vulnerability found, account takeover by a single click :)
The scenario is simple:
authentication token
by the user to our websiteThe exploit code (client-side + server-side call):
Here is the video POC: