Is Math.random() Safe? from missing rate limit to bypass 2fa and possible sqli
quality 7/10 · good
0 net
AI Summary
Researcher demonstrates chaining missing rate limits with Math.random() predictability via race conditions to bypass 2FA OTP validation in a Node.js-based React-Native mobile application, combined with SQL injection in the OTP endpoint affecting multiple authentication flows.
Tags
Entities
Yasser Mohammed
HackerOne
React-Native
Math.random()
Turbo Intruder
Burp Suite
OWASP
Is Math.random() Safe? from missing rate limit to bypass 2fa and possible sqli | by Yasser Mohammed (@n3r0li) - Freedium
Milestone: 20GB Reached
We’ve reached 20GB of stored data — thank you for helping us grow!
Patreon
Ko-fi
Liberapay
Close
< Go to the original
Is Math.random() Safe? from missing rate limit to bypass 2fa and possible sqli
Hi everyone It's Yasser Again,
Yasser Mohammed (@n3r0li)
Follow
~4 min read
·
February 20, 2021 (Updated: December 31, 2021)
·
Free: Yes
First of all i wanted to thank you all for sharing my last write-up and I got a lot of positive responses so I decided to write about another nice finding that i found lately.
I was testing a mobile application which was written in React-Native for private program on HackerOne about 5 months ago,
While my server-side testing I didn't found a lot of functions but as always I was working on developing a similar application as school project, and i got some problems with Synchronization, so while testing 2fa functionality I was asked to confirm the OTP which was sent to my phone number,
so let's see if the back end is going to crash if we sent a lot of requests,
So using the intruder i sent a lot of requests and waited for the corresponding messages to fill my phone with many OTPs
and yeah I got a lot of confirmation codes, this is a missing rate limit but i never submit it if I didn't got high impact scenario from it,
remembering that while I was developing my application I had to use Math.random() to generate these codes, but is it really that random ??
pseudo-randoms
Let's have a closer look on how this function works,
we cannot generate a pure random numbers since there is a lot of factors that could affect our randomization process which can make is so predictable,
and that's what is called pseudo-random , it's so unpredictable but it's not impossible since it depends on something called seed ,
to understand how is it working this video is so useful
as in the video the if we inserted 2 duplicate seed's into math.random we will get the same sequence,
so if i was able to use this seed and send the request at the same time I will be able to guess the OTP,
but this is soo hard to implement since it depends on the system clock on the server and my system clock.
Synchronous vs Asynchronous
the server was using asynchronous functions to handle our requests
you can read this great article to understand how does js synchronous/asynchronous works,
shortly synchronous means if we run this code: const second = () => {
console.log('Hello there!');
}const first = () => {
console.log('Hi there!');
second();
console.log('The End');
}first();
the output will be: Hi there!
Hello there!
The End
since the call stack got to execute function first and stop until the code in the function second executed then back to execute the rest of function first
in asynchronous we can execute 2 functions as above but the 2 functions will be executed in parallel with no blocking,
read the above article for more details.
Exploitation
in this case our answer is simple , Race-Condition
using turbo intruder in burp with this race condition script I will be able to send multiple requests in the same time so it will be executed on the server in the same time
so we will call Math.random() many times this could give us a duplicate result in if the length of the result is not too long,
here is a sample for a vulnerable code written in nodejs var http = require("http");
async function asyncCall() {
var x = Math.floor(Math.random() * 1000).toString();
return x;
}
http.createServer(function (request, response) {
response.writeHead(200, {'Content-Type': 'text/plain'});
asyncCall().then((value) =>{
console.log(value);
response.end(value);
});
}).listen(8081);
with sample turbo intruder script: def queueRequests(target, wordlists):
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=30,
requestsPerConnection=100,
pipeline=False
)
for i in range(30):
engine.queue(target.req, "", gate='race1')
engine.openGate('race1')
engine.complete(timeout=60)
def handleResponse(req, interesting):
table.add(req)
we will notice that we got duplicate numbers
POC
Notes
this scenario have a lot of aspects and depends on a lot of things to apply a successful Attack Like:
length of the OTP
internet connection speed
number of requests
concurrent Connections
the back-end framework
this slide by OWASP is so useful to understand the attack more concurrency Vulnerabilities
Life Example (Exposing the OTP and sqli)
applying the above steps on the target leads to expose the OTP Generated code
but the reason why we got a valid Code is that the query inserts our user_id which is the primary key in this case so we got a valid OTP
SQL error
And as always I was like
I noticed that phone number was not being validated well which lead to sqli.
this endpoint was responsible for all the OTP generation in the whole application so 2fa, number confirmation, reset password ..etc
I hope u enjoyed and thanks for reading again.
References
Google Chrome Attack
http://davidbau.com/archives/2010/01/30/random_seeds_coded_hints_and_quintillions.html
https://www.veracode.com/security/race-condition
https://blog.bitsrc.io/understanding-asynchronous-javascript-the-event-loop-74cd408419ff
https://www.youtube.com/watch?v=GtOt7EBNEwQ
concurrency Vulnerabilities
#javascript #race-condition #2fa #bugsbounty #react-native
Reporting a Problem
Sometimes we have problems displaying some Medium posts.
If you have a problem that some images aren't loading - try using VPN. Probably you have problem with
access to Medium CDN (or fucking Cloudflare's bot detection algorithms are blocking you).