0

We are running user-submitted JavaScript, server-side to be executed within a headless browser that doesn't have a DOM or any child of the window or document or location objects - because these are already removed. Is there a way for plain JavaScript on a fully updated version of WebKit/Chrome can create an HTTP request or otherwise use the network using the API and not the DOM? The team thought that just taking care of the DOM, fetch(), and XMLHttpRequest() was enough. However, there are other features of the browser that can be used to make requests, for example - the following will trigger an HTTP GET request:

const font = new FontFace('http_request', 'url(https://cdn.domain.com/file)');
// wait for font to be loaded
font.load();

Is it just these methods described? Or is there some other underhanded JavaScript that can generate malicious network traffic?

5
  • Another one might be: var x = document.createElement('img'); x.src = 'http://cdn.domain.com/image';
    – mti2935
    Commented Jul 2, 2022 at 17:48
  • @mti2935 that sends one, but it is a DOM operation, not using the Browser's JS API.
    – rook
    Commented Jul 2, 2022 at 18:56
  • Not exactly an answer, but is there some reason you can't just block the headless browser from making outbound network requests at all, or indeed sandbox it so hard it has no ability to access the network, access unneeded files, access processes, etc.?
    – CBHacking
    Commented Jul 2, 2022 at 22:27
  • @CBHacking we aren't blocking - we are hooking and then giving selective access. It is a selective filter, not a wall.
    – rook
    Commented Jul 3, 2022 at 19:44
  • Hooks can often be undone or spoofed, depending on exactly how they're done, so be careful of that. The way browser sandboxes handle this is that the sandboxed process can't make network calls at all; it instead uses IPC to its broker process to request any network action, and the broker performs the filtering when deciding whether or not to honor the request.
    – CBHacking
    Commented Jul 9, 2022 at 22:09

1 Answer 1

1

Have you blocked or at least restricted web workers? They already don't have DOM access, but can use fetch and XHR, and have their own root element which is not a Window (so overwriting the members of Window won't help).

You also don't mention WebSockets, which can be used for some types of SSRF and are available both from normal windows and from web workers.

Did you remove access to the Document() constructor, or just to the DOM that normally exists in any window? People may be able to get a clean document, or even window, by abusing constructors.


In general, I really can't recommend this approach. API sandboxes are always difficult to get right, and this is especially true of JS and its complicated object model, type system, and ever-expanding standard library. Even if you get it right today, there's no guarantee that an update tomorrow won't introduce a new vector.

Instead, you should sandbox the entire browser process. Don't let it access network connectivity at all unless absolutely necessary, and if it is necessary, severely limit that access to the specific host(s) and port(s) needed. Ideally don't let it open sockets at all. Similarly restrict the file system access. The specifics of how to implement such sandboxing vary from platform to platform, but they all support it (for network access in particular you can also use a software firewall).

1

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .