Over a million developers have joined DZone.

The Most Effective Way to Protect Client-side JavaScript Applications

In this article, weʼd like to delve into security perils in JavaScript. This will cover only front-end code that runs on the browser.

Discover 50 of the latest mobile performance statistics with the Ultimate Guide to Digital Experience Monitoring, brought to you in partnership with Catchpoint.

Protecting JavaScript Applications with Client-Side RASPThere are many useful features in a client-side technology like JavaScript. That’s what made it the most popular programming language in the world. It features many advantages, immediate parsing being one of them. This has benefits, for example, as the browser executes code right as it downloads content. But, with this level of freedom comes responsibility.

In this article, weʼd like to delve into security perils in JavaScript. This will cover only front-end code that runs on the browser. We will focus on other types on future posts.

Imagine what the browser has to do to execute JavaScript. First, it has to download the page and begin parsing. The browser doesnʼt wait around for everything to download. It has the capability to download and parse the page at the same time. So what happens when it encounters JavaScript?

JavaScript is render blocking, this has a tremendous advantage when it executes. What this means is, the browser will halt parsing, execute JavaScript first, then continue. This gives one ultimate flexibility in wielding this programming language. This opens up the code to any number of possibilities.

But, the question is, what are the implications of such features?

Debugging and Tampering

To illustrate, imagine the following code snippet:

<div id="hack-target"></div>
<button>Set Value</button>

<script>
  document.querySelector('button').addEventListener('click', setValue);

  function setValue() {
    var value = '2';
    document.getElementById('hack-target').innerText = value;
  }
</script>

This declares a target in HTML and wires up events. When you click the button, the callback fires.

With client-side JavaScript, one can set a breakpoint right where it sets the value. This breakpoint gets hit right as the event fires. The value that gets set through var value = '2'; can change at will. The debugger halts execution and allows a person to tamper with the page. This capability is great and the browser does not raise any flags while this is happening.

Since the debugger halts the execution, it has the power to halt page rendering too. Debugging is part of the tooling inside the browser so any person gets access to this. They are the Web Developer Tools.

To see this technique in action check out the Code Pen available. Below is a screenshot of this feature:

Hacking The DOM


This feature is great for debugging JavaScript but what does this mean for security?

This means an attacker can change JavaScript at runtime. The attacker can hit a breakpoint, change the DOM and enter arbitrary JavaScript in the console. This kind of attack can exploit vulnerabilities on the client. The attacker can change the data, hijack the session and make arbitrary JavaScript changes on the page.

For example, with the Web Developer Tools opened, one can go to the Console tab and enter:

document.querySelector('button').addEventListener('click', function () { alert('sacked'); });

The next time this event fires, it will fire this JavaScript change.

Why JavaScript?

The question you may be asking is, how did it all come to be like this?
When Netscape released JavaScript in 1995. This new programming language became the “glue language” of the web.

Netscape submitted their JavaScript standard to Ecma International and their version just became the standard, better known as ECMAScript.

Due to the fact that ECMAScript is standardized, any browser that claims to support it really has to comply to this standard and thus it does not cause conflict when used with different browsers. This means that you can write a script for Google Chrome and it would also have to work on Opera, NetScape, Internet Explorer and Microsoft Edge.

JavaScript got built around flexibility. Giving you all the capability necessary to do what you want with it. The dynamic nature of JavaScript flows from this design principle. This allowed it to become the defacto language for the browser.

All this is ancient history now, but what about JavaScript security?

Security on the Client-side

To protect against malicious JavaScript, the best option is to add runtime protection. Runtime Application Self-Protection (RASP) will protect client code during execution. With the flexible and dynamic nature of the web comes the need of securing at runtime, since an attacker can change JavaScript on the client at will.

RASP is the most effective level of protection for client-side applications and it gets summed up in this way:

Runtime application self-protection is a security technology that is built or linked into an application or application runtime environment and is capable of controlling application execution, detecting and preventing real-time attacks.

Once JavaScript hits the browser, there is nothing to shield its execution completely. RASP will guard against debugging and code tampering attacks that only happen at runtime. This will include attacks that modify the application while it is offline. A good RASP solution will also scramble the code to where an attacker canʼt tamper with the solution itself and simply go around it. These several layers of protection guarantee security on the open web.

If the RASP solution is any good, it will send notifications when an attacker attempts to thwart code. This allows one to react and take action, for example by cancelling the user session.

Jscrambler offers a RASP solution that protects applications against runtime attacks. It can make it self-defensive and detect tampering. The self-defending capabilities it offers add active protection to the JavaScript application. Jscrambler uses anti-debugging and anti-tampering techniques – well-known application protection concepts – but for JavaScript specific reality and limitations. Anti-debugging detects the use of debugging tools (e.g. DevTools, Firebug) and tries to stop the reverse-engineer from using it to debug the app. This is achieved with code traps that make the debugging tools stop working and make the call stack grow, keeping the user from inspecting the app’s control-flow. Anti-tampering detects code changes and reacts to that. For instance, if you add/remove a single semicolon from a function protected with Self-defending, it will detect that change and make the code stop working. Both techniques together with code obfuscation make it unfeasible to tamper with the application.

Conclusion

Implementing security in JavaScript must take into account what happens at runtime. By its nature, this dynamic language for the web got built for flexibility. Like any good double-edged sword, you must wield this with responsibility.

Is your APM strategy broken? This ebook explores the latest in Gartner research to help you learn how to close the end-user experience gap in APM, brought to you in partnership with Catchpoint.

Topics:
javascript ,rasp ,client-side ,security ,performance

Published at DZone with permission of Catarina Cardoso. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

SEE AN EXAMPLE
Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.
Subscribe

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}