Comments:"Egor Homakov: Hacking Github with Webkit"
URL:http://homakov.blogspot.com/2013/03/hacking-github-with-webkit.html
TL;DR: Github is vulnerable to cookie tossing. We can fixate _csrf_token value using a Webkit bug and then execute any authorized requests.
Github Pages
Plain HTML pages can served from yourhandle.github.com. These HTML pages may contain Javascript code.
Wait.
Custom JS on your subdomains is a bad idea:
If you have document.domain='site.com' anywhere on the main domain, for example xd_receiver, then you can be easily XSSed from a subdomain Surprise, Javascript code can set cookies for the whole *.site.com zone, including the main website.
Webkit & cookies order
Our browsers send cookies this way:Cookie:_gh_sess=ORIGINAL; _gh_sess=HACKED;
Please have in mind that Original _gh_sess and Dropped _gh_sess are two completely different cookies! They only share same name.
Also there is no way to figure out which one is Domain=github.com and which is Domain=.github.com.
Rack (a common interface for ruby web applications) uses the first one:
It orders them by the creation time (I might be wrong here, but this is how it looks like).
First of all let's have a look at the HACKED cookie.
PROTIP — save it as decoder.rb and decode sessions faster:
ruby decoder.rb
BAh7BzoPc2Vzc2lvbl9pZCIlNWE3OGE0ZmEzZDgwOGJhNDE3ZTljZjI5ZjI1NTg4NGQ6EF9jc3JmX3Rva2VuSSIxU1QvNzR6Z0h1c3Y2Zkx3MlJ1L29rRGxtc2J5OEd3RVpHaHptMFdQM0JTND0GOgZFRg%3D%3D--06e816c13b95428ddaad5eb4315c44f76d39b33b
{:session_id=>"5a78a4fa3d808ba417e9cf29f255884d", :_csrf_token=>"ST/74zgHusv6fLw2Ru/okDlmsby8GwEZGhzm0WP3BS4="}
It will make you a guest user (logged out) but after logging in values will remain the same.
Steps:
let's choose our target. We discussed XSS-privileges problem on twitter a few days ago. Any XSS on github can do anything: e.g. open source or delete a private repo. This is bad and Pagebox technique or Domain-splitting would fix this.We don't need XSS now since we fixated the CSRF token. (CSRF attack is almost as serious as XSS. Main profit of XSS - it can read responses. CSRF is write-only). @charliesome @homakov @github that would be awesome. open-source github.com/github/github :D — Magnus Holm (@judofyr) March 5, 2013 So we would like to open source github/github, thus we need a guy who can technically do this. His name is the Githubber. I send an email to the Githubber. "Hey, check out new HTML5 puzzle! http://blabla.github.com/html5_game" the Githubber opens the game and it executes the following javascript — replaces his _gh_sess with HACKED (session fixation): HACKED session is user_id-less (guest session). It simply contains session_id and _csrf_token, no certain user is specified there. So the Game asks him explictely: please Star us on github (or smth like this) <link>. He may feel confused (a little bit) to be logged out. Anyway, he logs in again. user_id in session belongs to the Githubber, but _csrf_token is still ours! Meanwhile, the Evil game inserts <script src=/done.js> every 1 second. It contains done(false) by default — it means, keep submitting the form to iframe :<form target=irf action="https://github.com/github/github/opensource" method="post"><input name="authenticity_token" value="ST/74zgHusv6fLw2Ru/okDlmsby8GwEZGhzm0WP3BS4="</form> At the same time every 1 second I execute on my machine: git clone git://github.com/github/github.git As soon as the repo is opensourced my clone request will be accepted. Then I change /done.js: "done(true)". This will make Evil game to submit similar form and make github/github private again:<form target=irf action="https://github.com/github/github/privatesource" method="post"><input name="authenticity_token" value="ST/74zgHusv6fLw2Ru/okDlmsby8GwEZGhzm0WP3BS4="</form> the Githubber replies: "Nice game" and doesn't notice anything (github/github was open sourced for a few seconds and I cloned it). Oh, his CSRF token is still ST/74zgHusv6fLw2Ru/okDlmsby8GwEZGhzm0WP3BS4=Forever. (only cookies reset will update it)Fast fix— now github expires Domain=.github.com cookie, if 2 _gh_sess cookies were sent on https://github.com/*.
It kills HACKED just before it becomes older than ORIGINAL.
Proper fix would be using githubpages.com or another separate domain. Blogger uses blogger.com as dashboard and blogspot.com for blogs.
Last time I promised to publish an OAuth security insight
This time I promise to write Webkit (in)security tips in a few weeks. There are some WontFix issues I don't like (related to privacy).
P.S.
I reported the fixation issue privately only because I'm a good guy and was in a good mood.
Responsible disclosure is way more profitable with other websites, when I get a bounty and can afford at least a beer.
Perhaps, tumblr has a similar issue. I didn't bother to check