I’ve been playing around with the idea of timing attacks lately. The way they work is usually by looking at them as an oracle. What information can be extrapolated depending on the time taken to run an arbitary command in a system?
A real life scenario where timing-attacks are used is in the use of blind SQL-injection. Using specific queries an attacker can make the server execute a sleep command if it satisfies a specific expression. By looking at the response time from the server, the attacker then knows whether or not the expression was true.
So I was recently looking at a possible CSRF-enabled search form. The CSRF itself was not interesting, because it would not affect the system in any way. However, if I could somehow determine the output of the response from the server then that could lead to a breach of privacy.
There were 2 responses that were of interest to me. A positive “Yes”-response and a negative “No”-response. Both responses were always the same sizes returned, but differed from each other by 4 bytes. I figured that in a large enough number of requests, that 4 byte difference might take longer to process and that the time taken would be related to the number of bytes sent.
Ultimately, my experiment in this case failed. The network traffic noise was too much for the difference to matter. But I did end up with a way of timing POST-requests sent via CSRF though, and that is what I want to show in this post.
I usually make my CSRF-exploits in the form of an auto-submitting html form which I then load in a hidden iframe.
So the question is how to time this? I found that the iframe fires a onload event whenever a new page was loaded inside the iframe. However only if there was enough time in between the page-loads. So by adding a small delay inside the payload and timing the time taken between the two resulting iframe.onload events you get a fairly accurate time measurement.
The resulting javascript looked something like this. Small edit to payload to include delay:
<script>
delay = 1000;
document.addEventListener("DOMContentLoaded", function () {
setTimeout('document.getElementById("csrfgo").click()', delay);
});
</script>
Finally, the parent page: listing
This way of measuring time can of course be used to measure the time for GET-requests as well, although using img-tags and their onerror event might be more accurate for this. There is probably a way to make the iframe.onload event trigger without the delay, but as a proof of concept this works. I get within around ~10ms accuracy compared to the output in the network log from the chrome webdeveloper tools. Also, check out the following paper for a more scientific approach to using timing attacks on web applications: http://crypto.stanford.edu/~dabo/papers/webtiming.pdf