Resident XSS – Reflected Becomes Stored Thanks to HTML5

HTML5 is the newest version of the HTML. It offers new features that enhance support for creating web applications that can interact with the user and his/her local data and servers. HTML5 successfully does this more easily and effectively than has previously been possible.

In this article we will focus on the new client storage offered by HTML5. The new HTML provides us with the Local & Session Storage, which can hold  15MB and more of client data. The differences between them is that the Local Storage can be accessed from any window, while the Session Storage can by read/modified by the same window only. Additionally, the data within the Session Storage will be automatically deleted when the window is closed, whilst deletion of the data in the Local Storage must be done manually.

Let’s say that the web application stores your account number, the SessionId, username, and some other data that will be read later on in order to display the data without sending requests to the server. The website takes the data it previously entered to the storage and displays it when the page renders. This is how the page looks normally, along with the original information stored in the sessionStorage:

ScreenShot138(Click on the image to enlarge)

Notice that the message within the speech bubble takes its information from the Session Storage, as can be seen in the above image, right below the page. You can access the page’s Resources tab using Chrome’s Developer tools (a.k.a Inspect Element).

We can assume that the page’s code behind it looks something like this when retrieving the data from the Session Storage:
   var username = window.sessionStorage.getItem(“username”);
   var speech = window.sessionStorage.getItem(“Speech-of-the-day”);
   var action = window.sessionStorage.getItem(“Random-action”);

If this website is vulnerable to a Reflected XSS (which in the regular case would be executed once on the response that includes it) and if the website does not perform client-side encoding (escaping), then this Reflected XSS can become a Stored XSS.

If the attacker injected some malicious content to our sessionStorage, thereby exploiting the original XSS, then the XSS would take residence (hence the name Resident XSS) inside our browser, just waiting to be called by the client. It will reside there until the window is closed or until that data is modified. All the attacker needs to know is the name of the key within the storage and then change it simply using: sessionStorage.setItem(key). In our case we’ll use “Speach-of-the-day.” So, in order to store the XSS in the Client Storage and exploit the Resident XSS, the attacker the can inject the following JavaScript command (the script will Pop-up an alert message for PoC):
window.sesssionStorage.setItem(“Speach-of-the-day”, “<script>alert(‘Resident XSS…’)</script>”);

Let’s go back to the example.

The attacker managed to implement a malicious code inside our sessionStorage using regular XSS. Now it will look like this:

(Click on the image to enlarge)

Notice that the value of the Speech-of-the-day key has been changed, and it now contains a malicious script (a simple alert for the PoC). The next time the page refreshes (and every time after that until the window is closed or the data is modified), the XSS will be executed:

(Click on the image to enlarge)

One of the major purposes of HTM5 is to bring power to the client-side. Therefore, in order to prevent those new vulnerabilities that are introduced by HTML5, we need to make a remediation on the client-side. Thus, to prevent XSS in the client-side we should perform the same mitigation that we would implement on the server. But before we read content from the client storage we escape it! We do this so when it is called, even if someone planted a malicious script, it won’t be executed (just as any XSS):

(Click on the image to enlarge)

With all the new powerful features HTML5 has brought to us, many new security issues have also been introduced. An important amount of them involve data stored in the client, or taken from it. As we already know, the client should never be trusted and all the data in it, no matter if we stored it ourselves or not,  should be mitigated. We should take all precautions possible when dealing with it.

2 replies
  1. Aqeel Asif
    Aqeel Asif says:

    What will be the impact in this case, as a fact html 5 doesn’t use cookies so no cookie related attacks.
    And html 5 is said to be implemented with restrictions for other domains to access localStorage.
    When I use this script alert(localStorage.getItem(session_id)) it’s accessing the sessionStorage value not the localStorage value and both of them have ‘session_id’ as a parameter in place.

    Any clarification will be appreciated.

    • Tal
      Tal says:

      If you try to access the localStorage. It will access the localStorage. I any case, if the website is vulnerable to XSS or Physical access, it could be under the risk for Information Leakage.


Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply

Your email address will not be published. Required fields are marked *