1

Why I want to know

We need to write XSS worms for an university project in which those worms fight against each other. The goal is to gain as much points as possible which are generated by a post request with our team id to a server. Each worm must not send more than exactly one of those post requests and replicates itself once.

To win, we are allowed to attack other worms. We are also allowed to defend our own worms from others. So we want our worms to make more successful post requests than the others.

I thought about blocking or rewriting the send() method of XMLHttpRequest, so that post requests from other worms/teams would send our team id or wouldn't be send at all. But I'm unfamiliar with JavaScript and I don't know if something like that would be possible...

Question

Attack

Is it possible to override a class/object (or a function of that class/object) - more especially XMLHttpRequest - in JavaScript? And if so, is the overridden class still valid in the global context (valid from another <script> tag)?

Let's say we have a first <script> tag with the following content: (not sure if correct JavaScript)

XMLHttpRequest = function () { // or class () ?
    const originalXMLHttpRequest = XMLHttpRequest;

    function send () {
        alert('successful attack');
        originalXMLHttpRequest.send(our_team_id);
    }
};

And a second <script> tag which calls the send() method with their_team_id:

const request = new XMLHttpRequest();
// ... configure request here
request.send(their_team_id);

Does a call from the second <script> tag now trigger the alert and send our_team_id to the server instead?

Defend

Is it possible to detect a overridden class/object? And if so, can I somehow reverse the change or access the original function?

Assuming we could only write code inside the second <script> tag and the first already overrode the send() method of XMLHttpRequest, would the original method still be accessible somehow?


If someone can think about another (and better) attack or defend vector, I would like to hear about it.

winklerrr
  • 13,026
  • 8
  • 71
  • 88
  • 3
    I'm pretty confused about what the words "class" and "override" mean here. *edit* OK now I get it. – Pointy Jan 26 '19 at 16:31
  • Some `window` properties (global symbols) can be overwritten, and the effect is exactly like you'd expect and is indeed global for all code on the page. Some cannot. This is something you could at least investigate experimentally. – Pointy Jan 26 '19 at 16:33
  • 2
    Also note that this is more about the JavaScript runtime environment than about JavaScript itself. `window.XMLHttpRequest` is part of the browser environment, not part of JavaScript. – Pointy Jan 26 '19 at 16:34
  • 2
    If your aim is to decorate `XMLHttpRequest`, then make sure you have the capitalisation right. Also, realise that the `fetch` API will not call `XMLHttpRequest#send`, so doing this will not ensure that you capture all HTTP requests. – trincot Jan 26 '19 at 16:41
  • 1
    "*Does a second script now trigger the alert?*" - surely you have tried this out and found the answer to be Yes?! – Bergi Jan 26 '19 at 16:50
  • @Pointy so it's possible that I could block `send()` requests from `window.XMLHttpRequest`? – winklerrr Jan 26 '19 at 17:02
  • 2
    If you would describe what you actually want to accomplish you would get more helpful suggestions. – Pointy Jan 26 '19 at 17:03
  • 1
    This feels like an XY problem. http://xyproblem.info – Nate Jan 26 '19 at 17:27
  • @Pointy I updated the question so that you know what I want to achieve. – winklerrr Jan 26 '19 at 17:35
  • @Nate yeah, I think my first version of the question was exactly that. Thanks for pointing out. – winklerrr Jan 26 '19 at 17:35
  • See [this example for overwriting `send`](https://stackoverflow.com/a/24196317/1048572) – Bergi Jan 26 '19 at 18:00

2 Answers2

2

I believe overriding Object/function is possible. However it would only work if the variable/function created is visible on the current scope. Please check this article about javascript function overriding

JavaScript supports overriding not overloading, meaning, that if you define two functions with the same name, the last one defined will override the previously defined version and every time a call will be made to the function, the last defined one will get executed.

catzilla
  • 1,901
  • 18
  • 31
1

I think what you want is to redefine the send method of XMLHttpRequest. If that's the case you could do the following:

// save original `send` method
const origSend = XMLHttpRequest.prototype.send;

// redefine `send` method
// you could also pass extra parameters if needed
XMLHttpRequest.prototype.send = (...origParams) => {
  console.log('send called');
  origSend(...origParams);
}

const req = new XMLHttpRequest();
req.open("GET", "http://www.example.org/example.txt");
req.send();

// will print `send called` 

This approach will generally work for anything you want to redefine.

  • Perfect, thanks! (I just edited my question while you posted your answer and it seems like I nearly wrote the code that you did) – winklerrr Jan 26 '19 at 17:38
  • How could I detect or even reverse those changes to `send()`? (Assuming we wouldn't have access to `origSend`) – winklerrr Jan 26 '19 at 17:52
  • 2
    @winklerrr You could detect them by `XMLHttpRequest.prototype.send.toString() !== "function send() { [native code] }"` - unless someone had overwritten `Function.prototype.toString` as well. It's a race of arms, and if you are the second script running inside a page you're bound to lose as the first script could set up a completely virtual environment and "sandbox" your worm. – Bergi Jan 26 '19 at 18:03