miércoles, 5 de abril de 2017

Some weird behaviour in the Google endpoints - Possible DoS by application-layer flooding?

More than a month ago I reported to Google a weird behaviour that I detected while uploading a picture to Google Docs. I was working on a script to upload pictures and attach them to documents when I made a mistake while sending the document ID and the API kept the request waiting for about 3 minutes to end up sending back an internal server error after a weird four-way handshake.

This behaviour made me think that Google Docs would be trying to find the document and since it was unable to find it in any sort of recently used documents, the request was forwarded to another subsystem for long term storage. Another possible option was that since the document was not in the DB index it was performing a full-scan.
After try some other requests I found other two endpoints with a similar behaviour where it is more easy to perform the possible DoS attack since these doesn't require to upload pictures or to send multiple requests. These endpoints keep the client waiting for 4 mins instead of 3. 

The endpoints are:
  • https://docs.google.com/document/d/invalid_docu_id/edit

And this is what happens when you use ApacheBenchmark to test the docs.google.com URL:

As you can see from the ab results, on this case all the 10 requests are taking 4 mins.

Other times some requests are resolved in ms, this was a bit disconcerting to me, making me think that this could be caused by any sort of rate limiter. In order to verify that this was not the case I run the same request from a server that had never execute a request like this being the result the same 4 mins as before. After this, I think that the most plausible explanation is that there is a crash report system or any other sort of logs collector trying to get information from the document that ends up timing out.

The next is what we can see using WireShark:

The transmission abobe is as next:
  1. The server starts answering but it get stuck
  2. The client sends a TCP Window Update since the transmission is not complete
  3. The client sends every minute a TCP Keep-Alive and the server answers to this keep-alive packages, this means that the server is actually listening and has the socket open
  4. The server sends the FIN, ACK in order to execute the four-ways handshake, I guess that after an internal timeout
  5. The client answers with an ACK as expected during the handshake
  6. The client answers with an “Encripted Alert”, this is the client requesting the termination of the TCP secured connection and because of the payload was not completely sent
  7. The client sends the FIN, ACK as expected
  8. The server instead of the ACK, sends a RST now dropping the connection without shut it down gracefully

This kind of behaviour facilitates (a lot) a DoS by application-layer flooding. This means that, if you start performing requests to this endpoints, you could end-up causing the collapse of the system.

The collapse could be produced by:
  1. The reach of the max open sockets limit. Since the servers keep answering to the keep-alive but not verifying that the customer has the socket still open you could just send requests and don't wait for any answer causing the servers to start rejecting incoming connections, this will also cause other resources consumption like memory, CPU and so. You have 4 mins to send as many requests as you can.
  2. In case of this request being causing memory, I/O or CPU pressure in any of the shards, you can just send several requests using different IDs in order to flood all the shards, this would make the systems collapse causing the DoS

Since you have 4 mins to cause one of the above described situations, that facilitates a lot a possible DoS attack, being able to be launched from a single computer using a commodity network. The attack could also be performed by mistake.

Google doesn't consider this as a security issue:

I understand that a generic DDoS attack shouldn't be considered a security issue, since there is too little you can do to prevent a Botnet from attacking your systems. But on this specific case it is like leave yours home door completely open because you can't do anything to prevent people from breaking in.

From my point of view, this is a security issue, I answered with the e-mail below explaining the reasons why I think so:

They answered with the next e-mail:

But after some weeks I received a generic e-mail discarding this issue as security issue, the issue is still reproducible.

viernes, 17 de marzo de 2017

Some Gmail endpoints are storing e-mails in the browser cache. Google doesn't consider this a security issue

It is well known that if you serve private information, like e-mails, you have to specify the no-store value inside the cache-control header so the browser doesn't persists this information in the cache, that would be insecure since after the user closes the session the data will still be there.

According to the W3C: The purpose of the no-store directive is to prevent the inadvertent release or retention of sensitive information. ( https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.2 ) Google is sending this value on most of the responses that contains sensible data as you can see from the screenshot below:


The problem is that some old Gmail endpoints are not including this value, like for instance:

The mentioned endpoint is the one used by the official Gmail ChromeExtension:

So every time this endpoint is acceded by your browser it stores the result in the cache, storing all your unread e-mail in a shared space including several private information:

I reported this about three weeks ago, sending a detailed description and the next video:

Nobody visualised the video before I got a the next answer from Google:

So, since in order to explode this security flaw it is required access to the computer Google doesn't care about your security, you must use your own computer :(

In the real world the people share computers and they also use public ones. After a user closes the session, the expected result is that all the user data should be safe when the used computer is not compromised at all, I wasn't talking about install any sort of malware, keyloger or whatever, just the official Gmail extension.

This is a super easy bug to fix, but the no-store is still no present. All the other e-mail companies are sending the no-store value, for instance WorkMail, FastMail and so.

The other day while I was waiting at the airport to take a flight I went to print my tickets using a shared computer, I had to connect to Gmail in order to download the tickets. I decided to install the official Gmail ChromeExtension (perhaps Google is distributing malware).
When I came back I made a video where I was able to access the private e-mail of more than twenty accounts.

I will not publish this video since I prefer to don't get in trouble, but I really think that this is an important security issue, easy to fix that should be addressed as soon as possible.

sábado, 8 de junio de 2013

Not all the Redis values are strings...

Working with a Redis database we discovered a very strange behavior after a refactor on one of the services.
Before the refactor we have been storing on Redis sets with only integer values, but we decided to add some information as a suffix of a couple of chars, something like: 12312412 -> 12312412:b after this refactor, the memory usage of the instances of the cluster, was increased from ~2GB to ~10GB, this was something unexpected for us, according to the Redis documentation, the sets only store "binary-safe strings" values: "Redis data types"
And after check how Redis handles the strings (Hacking Strings), the relative memory increase should to be directly proportional to the increase of characters of the values. According to the increase of the values lengths after the refactor we expected an increase of the 20% but it was of the 500% :( .

I decided to do a little proof of code:

Well, as you can see, we test two kind of values, the integer sets will contain numbers from 10000 to 10030 with a zero at the end, then the result will be integers: 100000, 100010, 100020, ..., 100300 , and the string sets will contain the same number but with the zero before the number, this will force to Redis to store this values as strings: 010000, 010001, 010002, ..., 010030 .
The expected behavior, if Redis stores the values as strings, is that after create all the sets, the memory usage will be the same for both test cases... but:

This unexpected behavior is caused by the next lines of the Redis source code: t_set.c
Redis checks if the value can be represented as "long long", and in that case stores the value as its integer representation, a clever behavior, but I didn't find it documented.

lunes, 11 de marzo de 2013

New Spotify Puzzles - Reversed Binary, Zipf's song, Cat vs. Dog - solutions

I discovered some months ago that Spotify has published some new puzzles. I love the puzzles, and was impossible to me resist the tentation to solve all of them :)

Reversed Binary Numbers

This is the simplest problem, I used less than ten minutes to solve it.
The steps to solve it are:
  1. Get the string representation of the number in binary using the bin() Python function
  2. Remove the first two characters, that Python adds to identify the string as a binary representation using the [:] notation
  3. Using [::-1] Python will reverse the array (-1 is the step)
  4. Convert the reversed array to an integer again using the int() call and specifying as second parameter the base 2

Zipf's song

This puzzle was a little more complicated, not for the problem, is only to apply a simple formula, was because the team who did the puzzles made a little mistake and the platform always was returning a "Run Time Error" each time that I tried to send the answer, I wasted around two hours trying to found the error on my code, and when all the hope was left, one of the persons in charge of the puzzles sent me an e-mail:

Was really nice discover that was a concerned team behind the puzzles, and that I was not in a mistake :)

The steps to solve this puzzle are:
  1. Calculate the quality of each song applying the formula: number of times plus the song position
  2. Sort the array of tracks by quality
  3. Split the array to get only the necessary song names
  4. Return the list of tracks as a string

Cat vs. Dog

 - https://github.com/alonsovidales/spotify-puzzles-v2/blob/master/catvsdog/catvsdog.py

This is the most complicated of the three problems, but if you remember the old puzzle "Bilateral":
 - http://alonso-vidales.blogspot.com.es/2012/03/spotify-bilateral-projects-puzzle.html
is much more simple :)
Reading the puzzle was easy to discover some clues:

  1. Also, based on the universal fact that everyone is either a cat lover (i.e. a dog hater) or a dog lover (i.e. a cat hater), it has been decided that each vote must name exactly one cat and exactly one dog. -> Is a bipartite graph
  2. procedure which guarantees that as many viewers as possible will continue watching the show -> Is a maximun cardinality problem :)
Then we have a bipartite graph:
Now we have a reduced number of algorithms to apply with a small complexity. 
We have two options, study the compatible or the incompatible graphs of voters. If we build the bipartite graph of the incompatible voters, we can obtain the maximun matching on this graph, and a full coverage of all the vertex.
The minimun number of edges who cover all the vertexes of the incompatibles graph are equal to the minimun number of voters to be discarded in order to obtain the maximun number of happy voters :)
To obtain this we found an old friend, one of the most beautiful algorithms, the Hopcroft-Karp algorithm (the same to be used in order to solve the old puzzle):

The steps to solve the problem are:
  1. Create the bipartite graph of incompatible voters, I used sets to do it as fast as possible
  2. Apply the Hopcroft-Karp algorith to obtain the min number of edges who cover all the graph
  3. Subtract the number of edges who cover the graph of the total number of voters, this will give us the max number of happy voters that we can obtain :)

Thanks Spotify for this puzzles :)

lunes, 4 de febrero de 2013

Spoofed links on Facebook

This bug allows to share links on Facebook that will seems absolutely legit, but linking to a different location than the location who Facebook show.
The problem is the flow who Facebook uses when a user share a link:
  1. Connect with the linked site
  2. Download the site information
  3. Check that all is correct, sanitize all in order to ensure that the user don't send something that can harm to the other users, etc
  4. Put all the information in a form that the user will send to publish the link
  5. And, this is the problem, trust on the information that the user send on this form
All the developers knows that  is dangerous to trust on the information that the users send, If the user want, him can send a spoofed form altering the information contained into the form values.

I reported this bug the past 30 of december (more than a month ago), but I didn't receive any response, and they didn't watch or download the demonstration video (I uploaded the video to one of my servers, and I can't find any access on the access_log file to the video):

jueves, 6 de diciembre de 2012

Non persistence XSS on the Spanish Senate site

The last week, when I was visiting the senator web site, I discovered something stupid, when you add some GET params to the URL this params are included directly without escape on the links used to share the current page on the different social networks (Facebook, Tuenti and Twitter).
On the next example I add a new attribute with name "aaabbb" and value "hello" to the social links:

Ok, I can add attributes to the links, now the problem is that if I try to use any of this characters: ', <, >, (, ) , the page redirect us to a 404 page:

Well, we have a problem, we can insert JavaScript code inside the attributes, but we can't execute anything without the ( or ) characters... or not...

If insert an attribute, for example onmouse over, you can insert assignations, for example:
   var aux1 = this.parentNode.parentNode.innerHTML;

We didn't use any of the forbidden characters, and we have a very interesting string like:
    <link type="text/css" href="/web/css/jquery-ui.css" rel="stylesheet"><a href="#" title="Enviar"><img src="/web/images/enviar.png" alt="Enviar" onclick="MostrarDialog();" title="Enviar"></a><a href="#" onclick="$(&quot;#menu_buscador&quot;).hide();

Ok, what can we do with variable assignations and this string on JavaScript to execute code out of the jail....
We can for example do the next:
    this.innerHTML = "<img onload=\"code_to_execute();\">";
But... as you can see I'm using the <, (, ) and " characters and I can't use this characters on the URL. Then, for create the "<img..." string I can use the string that I get on the aux1 assignation.
For example for the < character I can do aux1[0], that concatenated with the aux1[2] will give me the sting "<i"and I don't need to use eny of the forbidden characters. Then doing:
    this.innerHTML = aux1[0] + aux1[2] ....
I can obtain any string to be used as innerHTML, then I'm out of the jail :)

Is really tedious try to create complex strings concatenating characters one by one, to do this easy I did a very simple PHP script:
Inside the "buildInjection" call parameter you can put the code what you want. For this example, I use the system to using jQuery load a Script from a external server, then you can include more complex code on this script.

The code that I inject modify the art gallery by another more sophisticated :) :

In resume, yes, we don't have a permanent XSS, but, we have the control of the site using the social links, then we can, for example, share this URL instead of the correct one by the social networks as a "XSS Worm":

I reported this bug a week ago to the official senate twitter account, and by e-mail but I didn't receive any answer: 

A video that show all the process:

miércoles, 25 de julio de 2012

HTML5 Guitar Simulator app rejected by Spotify

A video of the proof of concept:

I sent an application to create a Spotify App, but it was rejected due to:
"That’s because you have a Guitar hero feature in the app."
The App is a simple Guitar simulator as another Guitar simulators, ex:

I sent an e-mail trying to show the error to the Spoify team, because I want to do a Guitar simulator, not a Guitar Hero copy :( , and now they told me:
 "It is not the fact that it is similar to Guitar Hero per sé it is the fact that we cannot have games with these concept in Spotify."

Ok, then I don't know why the app was rejected :( , the reason "we cannot have games with these concept in Spotify" is stupid, I don't know what kind of apps they want to have in the store...

You can find the source code of the proof of concept here:

And the specifications document here:

The e-mails: