לדלג לתוכן

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

תרגיל 1: pollution בסיסי

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

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);

// continuing the code
let user = {};
if (user.role === 'admin') {
  showAdminPanel();
}

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

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

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


תרגיל 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: pollution בצד השרת

שרת 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 שתבצע pollution פרוטוטייפ.

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

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


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

א. זיהוי JSON spaces

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

ב. זיהוי status code

כתבו בקשת HTTP שתשנה את הstatus code של תגובות Express. מה הstatus code שתצפו לראות?

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


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

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

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

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

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

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

מעבדה 5: pollution בצד השרת ל-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):
    """
    Complete the function
    """
    pass

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

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

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

// vulnerable?
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);

  // save to 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 מגן מפני pollution? הסבירו.

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

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