Dan Quixote Codes

Adventures in Teaching, Programming, and Cyber Security.

~/blog$ Detecting JS Alerts In Wargames

A major part of my teaching philosophy is "teaching through doing". It's my own personal belief that we learn better (and certainly with practical skills like pen-testing) through practice. I feel this helps us get familiar with a class of problem, and each time we encounter something similar, we can use the knowledge of this to solve harder issues.

One topic I teach is XSS (Cross Site Scripting), this is where we can place malicious code on a website, that is then activated when someone visits. This usually comes about when the developer doesn't check user submitted data correctly, allowing JavaScript to be included.

A traditional (not nasty) way of checking for if XSS exists, is to pup up an alert box, this gives some nice visual feedback that the attack has worked, without causing any issues to others. Normally, I would set up a sequence of challenges with varying levels of input sanitisation, then ask the students to submit whatever they used to create the alert.

This has some overhead, as there can be many ways working round the sanitisation, meaning there isn't ONE answer, so its not really suitable for an automated CTF (ie I have to do the leg work and check the answer is correct).

Inspired by Googles XSS game https://xss-game.appspot.com/, I tried to work out a way to make this better fit the CTF.

Detecting Alerts using JavaScript.

Turns out its pretty easy to detect an alert using JavaScript, we simply overload the alert function:

//Stash a reference to the window.alert function
var originalAlert = window.alert;

//Overload the window.alert.  
window.alert = function(s) {
    //Display some message to the student, we could use the s param to show the specified message.
    originalAlert("Congratulations, you executed an alert:\n");
}

This is pretty cool, gives us some scope for customisation, which means I can probably add a Flag.

Customising the Flag text.

My first thoughts were to do this through some kind of text mangling (loving template languages link Jinja), have each XSS challenge inject the flag into the page, then have the alert display it. This falls over through a couple of reasons:

  • The students quickly learn to "Use the Source" and any sensible way of encoding the string would be visible, and even if obsfrucated, most should recognise the encoding.
  • I don't know a huge amount of JavaScript, but even I know Globals are a BadThing(TM)

Had a few other ideas but ended up using AJAX, Its one of the things that JS was intended for, and it gives me some control over the logic for presenting the flags. (And if the students manage to de-obfuscate the JS, they learn about API exploitation, so its a win)

The plan was:

  1. Detect the Alert being triggered
  2. Use JS to call some API to fetch the flag
  3. .....
  4. Profit

Resulting in the following code:

//Stash window.alert link
var originalAlert = window.alert;

//Overload alert function
window.alert = function(s) {
    originalAlert("Congratulations, you executed an alert:\n");

    // Add some data to the API payload
    // Scope for some anti dissasembly here
    data = {AlertSuccess: "True",
            Checksum: "Redacted :)",
            AlertMessage: s}

    //Make a Request to a separate API, and display the data.
    $.post("scripts/xss-process.php", data, function(result ) {
        msgdiv = $("#outputdiv")[0]
        msgdiv.innerHTML="<em>Congratulations!</em> The Flag for this level is: " + result
        msgdiv.className = "alert alert-success"
    });
    }
}

Again this works quite nicely, the data part lets me send data (such as checksums to make disassembly harder) to the API, and grab the relevant flag. I keep track of the Levels through session cookies, and use this to make sure the correct flag is returned.

It's not flawless, and the whole Checksum thing needs thinking about, but again, the folks who can de-obfuscate the code and reverse the API, probably don't need to brush up on basic XSS techniques.

Detecting Alerts from the Console.

Its at this point, its time to think "What Would Scooby Doo?".

While the Scooby thing is a nice, line. It was more How will Greg troll me when he gets his hands on this?

Time to think like a Hacker, its a nice Idea, but how can I break it? Turns out its pretty easy:

  1. Open the Console
  2. Type alert();
  3. ....
  4. Profit.

While I say I was inspired by the XSS game, it was also a few months ago I last played with it. As I write this, took a look to see if it was vulnerable to the console based alert (it isn't). Looks like they use Iframes, which is something to take a look at.

Anyway, mutch Thruching around reading about how different browsers work, Turns out its quite easy to detect if chrome uses the console (it has a keys method). Otherwise we need to bugger about inspecting the stack to work out where the function was called from (Thanks stack overflow)

So we add a method to detect whether the alert was called from the console()

function fromConsole()
{

    //So Chrome has this thing called Keys that we can use to detect.
    var wasConsole = typeof keys === 'function' && keys.toString().indexOf('Command Line API') !== -1
    //console.log("From Console " + fromConsole)
    if (wasConsole){
    return true
    }

    //Otherwise use the approach from Stack
    var stack;

    try
    {
       // Throwing the error for Safari's sake, in Chrome and Firefox
       // var stack = new Error().stack; is sufficient.
       throw new Error();
    }
    catch (e)
    {
        stack = e.stack;
    }
    if (!stack)
        return false;

    //var stack = new Error().stack;
    var lines = stack.split("\n");
    for (var i = 0; i < lines.length; i++)
    {
        if (lines[i].indexOf("at Object.InjectedScript.") >= 0)
            return true;   // Chrome console
        if (lines[i].indexOf("@debugger eval code") == 0)
            return true;   // Firefox console
        if (lines[i].indexOf("_evaluateOn") == 0)
            return true;   // Safari console
    }
    return false;
}

And modify the alert script to deal with it.

//Stash window.alert link
var originalAlert = window.alert;

//Overload alert function
window.alert = function(s) {

    if (fromConsole()) {
        originalAlert("You need to Tigger the Alert using XSS, not the console:\n");
    }
    else{
        originalAlert("Congratulations, you executed an alert:\n");

        // Add some data to the API payload
        // Scope for some anti dissasembly here
        data = {AlertSuccess: "True",
               Checksum: "Redacted :)",
               AlertMessage: s}

       //Make a Request to a seperate API, and display the data.
       $.post("scripts/xss-process.php", data, function(result ) {
          msgdiv = $("#outputdiv")[0]
          msgdiv.innerHTML="<em>Congratulations!</em> The Flag for this level is: " + result
          msgdiv.className = "alert alert-success"
       });
    }
}

Which works pretty nicely. Add the relevant codez to the xss-process.php page, and the students can have per level flags.

Summary

Its not the cleanest code, but I don't claim to be a web developer :p

But we have a method to detect whether alert boxes have been triggered through XSS based attacks. This lets me add flags on a per challenge basis for my lessons.

There are still a few flaws, The whole checksum thing is not the best approach, but it should be enough to stop any casual "cheating", (if you call reverse engineering obfuscated JS, then the remote API cheating)

Biggest issue is that It doesn't work in Edge (although not sure about new "chrome" based edge), I need to take a better look at that.