Step by Step Exploiting SQLI in Oculus
0 net
AI Summary
Step-by-step exploitation of multiple SQL injection vulnerabilities in Oculus' website, demonstrating blind SQL injection techniques with whitespace and comma filtering bypass to extract admin session credentials. The attacker chained five SQL injections together, using creative MySQL syntax (comment blocks, OFFSET instead of comma-based LIMIT) to gain administrator access without prepared statements.
Tags
Entities
Oculus
Facebook
Josip Franjković
Jon
Bitquark
developer.oculusvr.com
CompanyAction.php
Burp
sqlmap
Josip Franjković - archived security blog: Step-by-step: exploiting SQL injection(s) in Oculus' website. Friday, 5 September 2014 Step-by-step: exploiting SQL injection(s) in Oculus' website. Hello, Some time ago Jon of Bitquark tweeted that he found a SQL injection and RCE in one of Facebook's acquisitions. You can find Jon's blog about the RCE vulnerability here . I guessed it was Oculus' website and started looking for more SQL injections and other vulnerabilities, resulting in a total of 5 SQL injections and a couple smaller vulnerabilities. Of those 5 injections, two were duplicate. I am not going to write about all 5 of them, but the one I have exploited to gain administrator user: SQL injection in developer.oculusvr.com/core/CompanyAction.php A POST parameter "Domain" was vulnerable to SQL injection, but there were few problems that made exploitation harder. Problem one: Syntax error was needed to differentiate true from false. The usual 'and'a'='a did not work and I needed to get syntax error for false. Lets build the basic true/false check: Domain='and (select 1 union select case when (1)=1 then 1 else 2 end) and '@test.com So, when 1=1 then the subquery looks like (select 1 union select 1) which is a valid query. Now, for 2=1 the subquery would be (select 1 union select 2) and it is an error, because subquery returns more than one row. We have the basic idea for true/false responses now. Problem two: No whitespaces. Oculus' domain filter required domain not to have whitespaces. Lets change the query to bypass this. I have decided to go with combination of comments /**/ and parenthesis. So: Domain='and(select(1)union(select(case/**/when(1)=1/**/then/**/1/**/else/**/2/**/end)))and'@test.com Great, this works too! Problem three: No commas. This one is a bit tricky. For blind injection we generally need LIMIT, substr() and other functions that need a comma. Well, they actually do not. After going through MySQL docs I saw comma-less syntax is possible for both LIMIT and substr(): LIMIT 0,1 is same as LIMIT 1 OFFSET 0 substr('Hello',1,1) can be used as substr('Hello' from 1 for 1). Here is the query to get database column name - character by character: 'and(select(1)union(select(case/**/when((select/**/ascii(substr(column_name/**/from/**/1/**/for/**/1))/**/from/**/information_schema.columns/**/where/**/table_name/**/like/**/'xxxxxxxxxxxxxxx'/**/limit/**/1/**/offset/**/0))=97/**/then(1)else(2)end)))and'@test.com I have guessed the table name, and parts of column names for sessions table using LIKE and a bit of luck. Problem four: it is blind injection, therefore slow. I did not use sqlmap for this, but I did help myself with Burp's Intruder. Since the goal was admin's PHPSESSID and it is [0-9][a-z], I simply set Intruder to bruteforce using that character set until it finds a true response, and then manually took out the characters and assembled a PHPSESSID. It was still slow, but okay - around 10 minutes on average to get the whole 26 characters long string. It would be faster but I actually needed to do another request to see if response is true/false - you'd first get 302 redirected, then see the response. Because of this I had to use one thread only and a small delay between requests, around 0.3 seconds. Using the PHPSESSID I logged in to admin panel. Jon's way to get command execution still worked, the panel was also vulnerable to more SQL injections. I have started reporting all those, but was asked to log out - which I did. I have also tried to get RCE using file-uploads, but as far as I know it did not work. That is all folks, thanks for reading :-). I would like to thank Jon of Bitquark for sharing knowledge, Oculus for not using prepared statements, and Facebook for running the bounty program. The vulnerabilities were fixed in a few days. Oh yeah, most of this stuff I learned with/from a CTF team - you can find their blog here and their security challenges here . Posted by Josip Franjković at 01:16 Email This BlogThis! Share to X Share to Facebook Share to Pinterest No comments: Post a Comment Note: only a member of this blog may post a comment. Newer Post Older Post Home Subscribe to: Post Comments (Atom) About me I enjoy breaking websites. Contact: josip[dot]franjkovic[at]gmail[dot]com You can follow me on Twitter ! New blog: josipfranjkovic.com Blog Archive ► 2016 (1) ► July (1) ► 2015 (2) ► July (1) ► April (1) ▼ 2014 (2) ► December (1) ▼ September (1) Step-by-step: exploiting SQL injection(s) in Oculu... ► 2013 (4) ► November (1) ► July (2) ► January (1)