Thursday, August 4, 2016

Posted by Paulos Yibelo
1 comment | 3:36 AM
A few weeks ago, I found a stored cross site scripting bug in Instagram that was tricky to craft a real exploit from. In Instagram Developers, you can create your own OAuth applications to be granted by the user and use the API. the vulnerable parameter is the "url" POST parameter, where you provide your site's address and the user could navigate to see who the developer is.

The parameter was properly sanitized, & even sent thru Linkshim to validate its not a malicious link. but here is the best part, Linkshim only validates if the link is malicious from a list of database files it have and if it doesn't exisit in the db, it will just put the url in a hyperlink reference.

And I assume because of this Facebook assumed when a link is sent thru linkshim, a link would get out. and they are right, and they are validating everything right. except for the scheme.

So worked but since schemes weren't validated, so did javascript:// At this point, it will seem like we got a working exploit. but there are different limitation factors here. the first one being there are lots of character limitations to write a payload. because characters are properly HTML entitied, we can't use quotes & other key elements. and because linkshim is there, the payload needed to be a valid & safe-uri, but with our payload.

Crafting an alert was easy, we just put javascript://`Hello!`

The above payload can generate an alert that says "Hello" in any modern browser thanks to ECMAScript6. notice there aren't any braces or quotes in there, and I added a newline (%0A), to make the alert not a javascript comment because linkshim would require us to follow standard scheme protocols (xxx://y)

Going Beyond Alert

This part is just an extension to prove exploitability. because of Session cookies, this wont be as simple as stealing cookies then saying game over. also because of the limitation factors I wrote above, crafting a normal payload isn't an option. 

So I had to use DOM manipulation techniques to get the Authorization button when clicked, authorizing our malicious application to be used on behalf of the user with all the scopes available (comments+likes+basic+public_content+follower_list+relationships)

The pre-final payload I crafted looks like: 


As you can see we didn't use any quotes but only the allowed characters, and when visited, that will
authorize the malicious application in-to the users account. :) so the final payload would look something like:


Here is a video poc:

Report Timeline

July 24, 2016 - Inital Report
July 26, 2016 - Triage
July 30, 2016 - Patch!

Wednesday, June 22, 2016

Posted by Paulos Yibelo
No comments | 3:53 PM
This is going to a very short post about a redirect_uri bypass technique I found in Moves.

Moves is a company owned by Facebook and one of the acquisitions in scope for the bug bounty program they are running.

I have written about an XSS bug caused in this same parameter entitled "Moves OAuth XSS" and this will cover a not so common redirect_uri bypass method. & after the xss I, "...continue testing" (quoting GLaDOS from Portal)

Anyway, there are a lot of ways to bypass redirect_uri's in OAuth, it all depends on what server side check we are facing and what limitation factors there are. for instance, in Facebook's case, if you set your applications allowed callback to it will allow that+ anything following it. so is considered perfectly valid. some other sites like Coinbase & Uber implement it differently. and addition of any queries, directories or domains will be considered invalid so scenarios that worked on Facebook will be invalid.

That leaves some OAuth clients heavily misconfigured and sometimes causes serious issues like OAuth bypasses possible.

However, there are sometimes confusions on the server handling these urls (often since dealing with url encoded values) and some bypasses are possible. 
Consider a site that configured its allowed callback url to

Possible bypasses to tamper with sub-directories:

  4. (double encoded)
  6. (for servers ignoring nonprintable CRLF chracters)   
 In moves case, I used the 5th example. it basically confuses the parser and thus let it assume /new/path/ is the allowed subdir.

PoC app: (obviously patched)

That application, although configured to redirect to it will redirect to 

Attack Scenario:

Consider an open redirect in like
If the developer set the callback to he will expect the OAuth provider won't accept other paths. (so open redirect is low priority here)

However, using the bypass, we create our malicious path like:

We encode the characters so it will be considered as a path and not tamper with the parser. 
the %23 (#) is added at the end to not let the other path following (../moves/callback) matter.

that will redirect to (my precious) and we just get our stolen code via document.hash and game over!

Here is a video poc

Report Timeline

Apr 29 - Inital Report
May 6 - Triage
May 9 - Patch

Monday, June 6, 2016

Posted by Paulos Yibelo
2 comments | 5:26 PM

Since a couple months back, I & a friend have been working on an interesting project called Zerorose. basically its a web vulnerability scanner, but not in a sense you are probably thinking of. we scan your system vulnerabilities from our site.


Zerorose is a project that tries to use a couple of machine learning algorithms to analyze known vulnerabilities in the visitors system. It does this by identifying plugins, browser, OS, common misconfigurations and similar key identifiers, and checking if any of them are known to be vulnerable for any issues, if they are or infected with malwares, if they still have support, if their compatibility/installation can cause other issues or best practice bypasses. we try to make Exploitkits, adwares and other malicious infections like ransomwares doesn’t happen.

 “An exploit kit is a software kit designed to run on web servers, with the purpose of identifying software vulnerabilities in client machines communicating with it, and discovering and exploiting vulnerabilities to upload and execute malicious code on the client. One of the earlier kits was MPack, in 2006. Exploit kits are often designed to be modular and easy to use, enabling the addition of new vulnerabilities and the removal of existing ones.

Do you have a cool video so that I can show my friends?


In short: we identify exploitable vulnerabilities (hopfully) before the bad guys do. so you can roam the internet free without automatic client side exploits triggering out of infected, shady sites, malvertising campaigns and that porn site you sometimes visit.

False Positives

Although we try to deliver reliable and actionable information, it is possible for the system to assume and identify non-existent issues because of a number of factors. This could be because you using a modified user agent, using modified plugins or the names of plugins, addons or scripts you using matching a known malware. if that is the case, you can click on "Report" at the right side of the report and it will try to evaluate (of course, with manual check) & learn from its mistakes.

How are you different from exploit kits?

You may have heard of Blackhole, Crime, Angler or other exploit kits. What they are doing is not much different from us, except maybe: we are helping you patch instead exploit them & we are cooler in many ways. ;))

Can I trust zerorose?

Of course. *promises*

Are you the only one doing this?

As far as we are aware, yes. Us and exploit kits.

Why not open source?

We figured it’s quite easier to visit our website than download/run it in your host everytime you want to scan something, and that data will soon be outdated. That and we don’t want to share our codez.

Why is it free?

Honestly, we have no idea. I know its a bit suspicious why we went this far to build this but it was mostly done just because we care. =))

Do you accept donations?

Yes, we welcome any kind of help being we are a small team doing this in a part time. please click here to do that.
I hope you find this interesting & it helped you.

Friday, December 25, 2015

Posted by Paulos Yibelo
5 comments | 10:33 AM

Its been a while since I have blogged. I have since became a twitter person. mostly reading peoples findings.

Anyway, this is going to be a short post about causing an XSS on Moves. As many of you might know, Moves (moves-app) is a part of Facebook's Bug Bounty program.


OAuth - for those of you who dont know, is an open standard for authorization. OAuth provides client applications a 'secure delegated access' to server resources on behalf of a resource owner. It specifies a process for resource owners to authorize third-party access to their server resources without sharing their credentials.

Many big sites like Facebook, Google, Twitter and Dropbox use it to share specific access from a user to third-parties.
In developers can create their Moves application(s) by using OAuth 2.0. meaning, by simply creating an application with redirect_uri, the thirdparty can get access to Moves profiles with the provided scope (location, access, read/write...).

The part that caused the XSS is the redirect_uri, they have blacklisted certain schemes from being added. forexample, I can't add "javascript://", "data:" and other protocols to the redirection url for the application I am creating.

If you notice carefully, those aren't the only dangerous schemes when it comes to script execution. for example, using "vbscript://" was possible. but due to the unlikely conditions that the user have to use an older version of Internet Explorer to get that executed, that was almost a dead end.

Bypassing Filter

As you might know, blacklisting may not be the right solution when it comes to XSS.

Things we know,:
it will expect either http or http(s)
schemes need to contain protocols. (://)

using dAta:// and jAvaScRipT:// worked with http(s?):// following them. because the regex wasn't checking for case sensitivity/i.

so redirect_uri=jaVaScrIpt://alert(0);//http:// is an ideal payload. because http will be treated as a comment.

However, there are no known payloads that will execute a script after using the data:// scheme like that, an ideal payload would be something like data:text/html;<script>alert(0)</script> but that wasn't possible.

Next is javascript, using javascript://alert(0) is also not an option, considering javascript will treat parts following it as a comment. turns out we can use newlines and breaks to cause script execution. so javascript://%0Aalert(0)//http:// works fine and causes that alert() we all love to see.

<a href="javascript://%0Aalert(0)//http://">Click</a>

works fine. but only in the <a>nchor context. but not in the redirection.
so Location: javascript:anything() actually doesn't work (just became aware of this because @filedescriptor mentioned it, I had no clue)

However, data:// schemes work fine. so data:// is our ideal payload. but turns out the :// isn't actually mandatory, because the http:// following in the comments can help within.

Ideal solution: daTa:text/html:base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K#http://

Errors. Errors eveywhere. Solution: URL encoding.

Simply by encoding the URL it is possible to get a working payload,

Final solution: daTa:text/html%3Bbase64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K%23



UPDATE: Abdellah mentioned this can be exploited automatically using a well known OAuth misconfig. simply changing the "scope" to unknown, an error will be triggered that will force an error redirection to the redirect_uri (which in this case is the malicious paylaod). so this should work fine:'texist&redirect_uri=daTa:text/html%3Bbase64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K%23http://
or, moves will exploit its ownself for us, with no user-interaction whatsoever. here is the secrete:

If no user-interaction is occured, moves will redirect to the redirect_uri in 9 seconds. and we simply set our malicious script as a redirect_uri and send that user to that page, even if he doesn't do anything, the exploit will trigger it self in 9 seconds. awesome!

simply by embedding the authorization url in an iframe or img tag, any moves user should be exploitable. here is a video demonstrating it:



24 November 2015 - Initial Discovery
2 December 2015 - Report
8 December 2015 - More data sent.
9 December 2015 - Escalated by Facebook
10 December 2015- Patch
10 December 2015 - Fix Confirmation

Saturday, May 30, 2015

Posted by Paulos Yibelo
6 comments | 8:05 PM

I am writing this blog post because both the teams that handled this bug were quite amazing. (Vulnerable 3rd party and Offensive Security) They acknowledged, fixed and rewarded my report in <1hr of my submission. (both of them) This, for someone with experience with responsible disclosure is unbelievable.

So it starts out like this, Offensive-Security's Exploit-db announced they just launched their new appearance. I checked it out, it’s quite beautiful, less darker and all… a white-hat’s place. It looked less like Inj3ctor and more like exploit-db. 

I noticed they are running wordpress, with a number of plugins. But they obviously were all updated and running latest version. I had to find a 0day. So I downloaded their new caching plugin for page performance, WP-ROCKET. (which by the way handled the bug quite well, and even acknowledged my report in multiple ways, Thank you!)

The code looked good, I found no SQLi, no XSS. But then, a very silly page seems to appear with a silly code.
/wp-content/wprocketfolder/inc/front/process.php line 44,

Says include ($rocket_config_path . $host . '.php');

Where $host is pre-defined as:

44: $host = trim(strtolower($_SERVER['HTTP_HOST']), '.');

This page can be accessed to anyone and requires no wordpress authentication. The HTTP_HOST header can be manipulated simply by tampering with the HOST header. (Edit: This is only applicable if certain Apache/php.ini are fulfilled.) I then wrote about the bug to Offensive-Security, they responded 12mins later saying they disabled the plug in.

In an LFI theory, an attacker can poison log files and include them as ../../logfile to cause Remote code execution. (RCE) Practically that would be hard to exploit for RCE because an attacker would need to bypass the WAF they are running called Sucuri. And also php doesn’t let null termination (%x00) work (because its patched since < 5.2.1), this would be difficult to achieve But...

This can be exploited by using php://filter for local file inclusion by sending a HOST headers like
php://filter/convert.base64-encode/resource=index then when the include happens, $host.'php'); our resource parameter will get index.php, this forces PHP to base64 encode the file before it is used in the include statement. From this point its a matter of then decoding the base64 string to obtain the source code for the PHP files. Simple yet effective..

Or This theoretically would also had been exploitable to RFI (Remote File Inclusion) if the path wasn't relative. In absolute URL cases, we can use the data:// Scheme to cause RFI. By encoding a PHP script in base64 and then URL encoding any special characters contained within this string we can successfully execute a script. Below example shows how phpinfo() can be executed using the above script to enumerate more information about the targe. Or a simple RCE by using the expect:// scheme (same as the one that caused the XXE RCE in Facebook)

<? phpinfo(); die();?>

// Base64 Encoded

// URL + Base64 Encoded

// Final URL in HOST

The die() statement is there to prevent the execution of the rest of the script or the execution of of the incorrectly decoded ".php" string which is appended to the stream.

Using a data stream over a standard remote or local file inclusion has several benefits:

  • It doesn't require a remote server.
  • Its doesn't require a null-byte to be appended to the end of the script.
  • It works behind a firewall that blocks outbound traffic.

However, exploitation was blocked because of a fair WAF called Suruci and The include being relative. Nevertheless, they treated the bug as critical as it is, and pushed a fix in < hr of my initial report  and added my name to their Special Thanks page.(of course with a bounty)!

Special Thanks to Julio Potier, a programer of the WP-Rocket team. He acknowledged my report, fixed the bug, and even issued a generous bounty.


April 19, 6:54 am – Initial Report
April 19, 7:08 am – Confirmation
April 19, 7:43 – Complete Fix + Bounty

Tuesday, May 19, 2015

Posted by Paulos Yibelo
No comments | 12:56 PM

The (kind of this) bug was a originally found by Deusen and then by Rafay Baloch. Affecting the Android Web Browser, and Safari in both OSX and iOS.

Here is a simple PoC to demonstrate the issue; if you see the URL, it says when in reality, the page is actually hosted at another website.

So far, Safari and the Android Browser have been confirmed vulnerable by Baloch on a blog post earlier today.

But now, I also noticed this bug can be produced at Opera Android and Opera Mini browsers. 
function f()

The code is hilariously simple to understand, webpage reloads roughly every 10 milliseconds (random) using the setInterval() function, just before the browser can get the real page and so the user sees the ‘real’ web address instead of the fake one.

There is another example Rafay used though, is really valuable for spammers/phishers. He used (the one you see in the URL), but hosted content actually is being delivered to attacker controlled site.

Another example would be, say a page X (malicious) hosts a page similar to with malicious content and you get to click on something like
<a href=""></a>

Its very likely you will click on that, when you instead will be redirected to but that site will spoof the URL and you will see in the URL.
There are uncountable possibilities about this bug that will be bad for the average joe, the people without no technical backgroud. 

Google reported releasing patches for Android Lollipop (5.0.x) on April 7, and for Android KitKat (4.4.x) on April 30.