Question

Background

I'm building up a website that lists organisations in my local area. The site is powered by an API and stores it's data in an instance of MongoDB.

I'm fetching JSON from the API and dynamically building the content in Javascript.

Now to test against XSS attacks I deliberately added some code to inject a Javascript alert into my page.

But it's not working? Which obviously I'm happy about but I'm more confused as to why not.

The JSON

{
"_created": "Tue, 11 Mar 2014 19:27:30 GMT",
"_etag": "fd8102613204000414cceff538771453b984a2c6",
"_id": "531f63a246e29300025291ba",
"_updated": "Tue, 11 Mar 2014 19:27:30 GMT",
"description": "<script>alert('hello');</script>",
"tags": [
    "Antiques"
],
"title": "HTML Injection",
"url": "www.link.com"
}

the injected code

<script>alert('hello');</script>

The code to retrieve the JSON and render it

function S_GET(id) {
    var a = new RegExp(id+'=([^&#=]*)');
    return decodeURIComponent(a.exec(window.location.search)[1]);
}

// retrieves languages and adds them to a list
var organisationId = S_GET('organisationId');

var url = 'http://damp-island-8192.herokuapp.com/organisations/' + organisationId;


var dataRequest = new XMLHttpRequest();
dataRequest.open('GET',url, false);
dataRequest.onreadystatechange = processJSON;
dataRequest.send();

function processJSON() {
    if ( dataRequest.readyState == 4 && dataRequest.status == 200 ) {    
        showJSON(dataRequest.responseText);
    }
}

function showJSON(input) {

    //dom elements
    var list = document.createElement('ul');
    list.setAttribute('id', 'organisation-details-list');

    var organisation = JSON.parse(input);

    // list organisation details
    // title
    var title = document.createElement('li');
    title.setAttribute('class', 'organisation-title');
    title.innerHTML = organisation.title;
    list.appendChild(title);
    // description
    var desc = document.createElement('li');
    desc.setAttribute('class', 'organisation-desc');
    desc.innerHTML = organisation.description;
    list.appendChild(desc);
    // link
    var link = document.createElement('li');
    link.setAttribute('class', 'organisation-link');
    var a = document.createElement('a');
    a.setAttribute('href', organisation.url);
    a.innerHTML = organisation.url;
    link.appendChild(a);
    list.appendChild(link);

document.getElementsByClassName('organisation')[0].appendChild(list);
};

The HTML

<!DOCTYPE html>
<head>
    <title>Moving To Leicester</title>
    <link rel="stylesheet" type="text/css" href="css/styles.css">
</head>
<body>
    <div class="container">
        <div class="header">
            <ul class="nav nav-pills dropdown-menu-right">
                <li class="active"><a href="splash-page.html">Home</a></li>
                <li><a href="#">About</a></li>
                <li><a href="#">Contact</a></li>
            </ul>
        </div>
        <div class="row padding-top-5">
            <div class="col-md-2">
                <!--Sidebar content-->

            </div>
            <div class="col-md-10">
                <!--Body content-->
                <div class="organisation"></div>

            </div>
        </div>
    </div>
    <script type="text/javascript" src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
    <script src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
    <script type="text/javascript" src="js/organisation-details-page.js"></script>
</body>
</html>

Question

Why doesn't the page trigger an alert when I'm viewing it?

Was it helpful?

Solution

To my knowledge inserting executable Javascript via AJAX is somewhat limited. You cannot just get code via AJAX, put it in a LI's innerHTML an have it executed. This is what you do:

var organisation=JSON.parse(input);
var title=document.createElement('li');
title.setAttribute('class','organisation-title');
title.innerHTML=organisation.title;
list.appendChild(title);

However, one work-around could be if you change your injection into this:

<iframe src='/' width='1' height='1' onload='window.alert("boo");'></iframe>

I think that would inject itself.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top