לדלג לתוכן

זיהום פרוטוטייפ - Prototype Pollution - תרגיל

תרגיל 1: זיהום בסיסי

הקוד הבא מכיל פונקציית מיזוג פגיעה:

function merge(target, source) {
  for (let key in source) {
    if (typeof source[key] === 'object' && source[key] !== null) {
      if (!target[key]) target[key] = {};
      merge(target[key], source[key]);
    } else {
      target[key] = source[key];
    }
  }
  return target;
}

let userInput = JSON.parse(getUserInput());
let config = {};
merge(config, userInput);

// בהמשך הקוד
let user = {};
if (user.role === 'admin') {
  showAdminPanel();
}

א. כתבו JSON payload שיגרום ל-user.role להחזיר 'admin'.

ב. הסבירו מדוע JSON.parse לא מונע את הזיהום.

ג. תקנו את פונקציית merge כך שתהיה מוגנת מפני זיהום פרוטוטייפ.


תרגיל 2: מציאת gadgets

הקוד הבא קיים בדף:

function createWidget(options) {
  let defaults = {
    width: 300,
    height: 200
  };

  let config = {};
  merge(config, defaults);
  merge(config, options);

  let widget = document.createElement('div');
  widget.style.width = config.width + 'px';
  widget.style.height = config.height + 'px';

  if (config.innerHTML) {
    widget.innerHTML = config.innerHTML;
  }

  if (config.src) {
    let script = document.createElement('script');
    script.src = config.src;
    document.body.appendChild(script);
  }

  document.body.appendChild(widget);
}

createWidget({});

א. זהו את כל ה-gadgets בקוד.

ב. כתבו URL payload שינצל כל gadget בנפרד.

ג. איזה gadget הכי מסוכן ומדוע?


תרגיל 3: זיהום בצד השרת

שרת Express הבא פגיע:

const express = require('express');
const ejs = require('ejs');
const app = express();
app.use(express.json());
app.set('view engine', 'ejs');

function deepCopy(target, source) {
  for (let key in source) {
    if (typeof source[key] === 'object' && source[key] !== null) {
      target[key] = {};
      deepCopy(target[key], source[key]);
    } else {
      target[key] = source[key];
    }
  }
}

app.post('/api/settings', (req, res) => {
  let settings = {};
  deepCopy(settings, req.body);
  res.json({ status: 'ok' });
});

app.get('/dashboard', (req, res) => {
  res.render('dashboard', { title: 'Dashboard' });
});

א. כתבו בקשת HTTP שתבצע זיהום פרוטוטייפ.

ב. כתבו בקשת HTTP שתנצל את ה-gadget של EJS כדי להשיג RCE.

ג. איזו פקודה תרוץ בשרת? הדגימו עם curl לשרת התוקף.


תרגיל 4: טכניקות זיהוי

א. זיהוי JSON spaces

כתבו בקשת HTTP שתשנה את ה-JSON spaces ב-Express. הסבירו כיצד תוכלו לזהות האם הזיהום הצליח על סמך התגובה.

ב. זיהוי status code

כתבו בקשת HTTP שתשנה את קוד הסטטוס של תגובות Express. מה קוד הסטטוס שתצפו לראות?

ג. כתבו סקריפט Python שבודק אוטומטית אם endpoint פגיע לזיהום פרוטוטייפ בצד השרת.


תרגיל 5: מעבדות PortSwigger

מעבדה 1: זיהום פרוטוטייפ בצד הלקוח דרך URL

  • כתובת: Client-side prototype pollution via browser APIs
  • רמה: Practitioner
  • משימה: מצאו מקור זיהום פרוטוטייפ ו-gadget, ונצלו אותם ל-XSS
  • רמז: בדקו איך האתר מפרסר פרמטרים מה-URL

מעבדה 2: זיהום פרוטוטייפ דרך DOM XSS

מעבדה 3: זיהום פרוטוטייפ דרך flawed sanitization

מעבדה 4: זיהום בצד השרת עם זיהוי

מעבדה 5: זיהום בצד השרת ל-RCE


תרגיל 6: כתיבת כלי סריקה

כתבו סקריפט Python שמבצע את הבדיקות הבאות:

  1. שולח בקשת POST עם JSON שמכיל __proto__ עם תכונות זיהוי
  2. בודק שינוי ב-status code
  3. בודק שינוי ב-JSON spaces
  4. בודק שינוי ב-charset
  5. מדווח על ממצאים
import requests
import json

def test_prototype_pollution(url):
    """
    השלימו את הפונקציה
    """
    pass

תרגיל 7: תיקון קוד פגיע

הקוד הבא הוא חלק מאפליקציית Node.js. מצאו את כל נקודות הפגיעות ותקנו אותן:

const express = require('express');
const app = express();
app.use(express.json());

// פגיע?
function extend(target, source) {
  Object.keys(source).forEach(key => {
    if (typeof source[key] === 'object' && source[key] !== null) {
      target[key] = target[key] || {};
      extend(target[key], source[key]);
    } else {
      target[key] = source[key];
    }
  });
}

app.post('/api/user/preferences', (req, res) => {
  let prefs = {};
  extend(prefs, req.body);

  // שמירה ב-DB
  db.updatePreferences(req.user.id, prefs);
  res.json({ status: 'ok' });
});

app.get('/api/user/profile', (req, res) => {
  let user = db.getUser(req.user.id);
  if (user.isAdmin) {
    // ...
  }
  res.json(user);
});

א. האם Object.keys מגן מפני זיהום? הסבירו.

ב. מה ההבדל בין Object.keys ל-for...in בהקשר של זיהום פרוטוטייפ?

ג. כתבו גרסה מאובטחת של הקוד.