18

Initially I thought the answer to this question was yes, so malicious JavaScript cannot be injected into the page if it is in the response.

Yet upon a further look at this question it is a lot harder to inject JavaScript than you may think (or at least I did). I think the most common example is some malicious user enters script into a text field on a record, this value is queried, added to the page, and there you go...JavaScript injection. Except even if you do this, the JavaScript will not execute it as it appears to be completely ignored by the browser. Take the following example. JavaScript Remoting returns a script tag and this is added to the page but the alert() never happens.

public class Inject {

    @RemoteAction
    public static String getScriptString(){
        //Pretend this could be queried from a record
        return '<div>hi<script type="text/javascript">alert("Hello.");</script></div>';
    }
}

<input type="button" value="Inject!" onclick="injectScript();"/>

<div id="target" style="border: 1px solid grey; height: 50px;"></div>

<script type="text/javascript">
    function injectScript(){
        //Do remoting call to get script and add it to and existing DIV on the page, and a new div, neither cause the alert

        Visualforce.remoting.Manager.invokeAction('{!$RemoteAction.Inject.getScriptString}', function(result, event){
            if (event.status) {
                //Existing div
                document.getElementById('target').innerHTML = result;

                //New div, still no alert
                var newDiv = document.createElement('div');
                newDiv.innerHTML = result;
                document.body.appendChild(newDiv);
            }
        },{escape: false});
    }
</script>   

So two questions really. Why is the alert() not happening and what is the danger of returning un-escaped results? Is this simply to escape HTML and is more of a display and formatting issue? An example would be great.

Thanks,

Jason

12

While your Javascript alert does get appended to the HTML body, it doesn't get immediately executed (as you found). You need something that will cause the browser to execute the script.

This isn't too difficult, you just need to be a bit more malicious :)

For example:

@RemoteAction
public static String getScriptString(){       
    return '<img src="/img/seasonLogos/2013_spring_aloha.png" onload="alert(\'all your Salesforce are belong to us\');" />';
}

Note the absence of a script tag. The browser will execute the alert after loading the image.

So the injection risk here is very real. If users can get unescaped content onto the page you are vulnerable.

I don't have a full explanation on why a browser doesn't evaluate appended script content immediately. There is some discussion on this here - Executing elements inserted with .innerHTML

  • Perfect example, thanks. Oddly enough I had tried something similar as inserting an entire JavaScript function and then tried calling that from the console and this didn't work either. – TehNrd Mar 10 '13 at 22:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.