26 Apr 2021 • 10 min read
26 Apr 2021 • 10 min read
Before getting into the topic, I’m going to share a brief history that you may or may not know about JavaScript:
JavaScript has become one of the most popular programming languages today and is used ubiquitously on modern websites. According to Octoverse on GitHub, JavaScript has been the top programming language on GitHub consecutively since 2014. Stack Overflow also did a survey looking back to 2020 and the result shows that JavaScript ranks the top among all other programming languages.
One of the reasons why JavaScript becomes so prevalent is that JavaScript is easy to learn and use. Previously, JavaScript was used for making the webpage dynamic. Today, the capabilities of JavaScript have been extended to both the front-end and back-end. The common front-end frameworks are AngularJS, ReactJS, jQuery, etc. NodeJS, ExpressJS, and such back-end frameworks provide RESTful API services and other non-UI functions. It's like a feast for developers, mastering one language to develop a full-stack project is not an imagination anymore.
However, the article today will mainly concentrate on JavaScript as a front-end programming language.
Source: GitHub Octoverse
The JavaScript files are loaded along with other resources of the web pages to provide essential business logic. As the JavaScript codes can be easily accessible by users in the browser debugging mode, unprotected JavaScript codes may expose the core businesses to the outside world, especially attackers, resulting in intellectual property taken unexpectedly, revenue losses, or brand-damaging. The following is a typical example of exposing all the JavaScript code to the public.
So well if you don’t want to have your data lying in the JavaScript code taken by attackers or competitors, you will need to make the codes unreadable by humans but still interpretable by the browsers.
JavaScript obfuscation is a deliberate act of transforming the code into something that is not readable without affecting the functionality, unlike code encryption.
Code obfuscation has been found as the primary technique used by web attackers to masquerade their attacks, for example inserting malicious obfuscated JavaScript code to steal personal information. Up to this point, you may think that JavaScript obfuscation is contrary to morality. Think about this, if your JavaScript code is exposed to the public, then the attackers would find it easier to manipulate your web pages. Therefore, the techniques need to be used to protect client-side codes from those web attackers by concealing the meaning of the data. JavaScript obfuscation is not a once-and-for-all solution that can prevent codes from being reverse-engineered. The obfuscated code is hard to be analyzed and reversed, therefore this technique is a good approach to significantly increase the cost for attackers to carry out reverse-engineering work. JavaScript obfuscation is basic but imperative action in web application security.
As we know, anti-frauds are always a zero-sum game and what we can do is to stay ahead of the fraudsters and reduce the losses as much as possible.
What benefits can JavaScript Obfuscation offer:
But DO REMEMBER you cannot rely on JavaScript obfuscation solely. Good programing habits are combining obfuscation techniques with multi-layered protection to guarantee application security.
It’s no secret that the bot mitigation solutions in the market utilize JavaScript to track and process essential data or rendering the UI components, so does GeeTest CAPTCHA. Therefore, it’s crucial to have JavaScript files secured. The 3rd party JavaScript obfuscation solution was previously used to obfuscate our source codes. We started researching and developing the JavaScript obfuscation algorithm a few years ago to have better control of securing the source code.
Ok, we’ve discussed a lot about JavaScript obfuscation. Now let’s peek at an example of JavaScript obfuscation:
The original code:
(function (window) { "use strict"; if (typeof window === 'undefined') { throw new Error('Geetest requires browser environment'); } var document = window.document; var Math = window.Math; var head = document.getElementsByTagName("head")[0]; ... ... ... load(config, true, config.protocol, newConfig.static_servers || newConfig.domains, newConfig[type] || newConfig.path, null, function (err) { if (err) { status[type] = 'fail'; throwError('networkError', config); } else { status[type] = 'loaded'; var cbs = callbacks[type]; for (var i = 0, len = cbs.length; i < len; i = i + 1) { var cb = cbs[i]; if (isFunction(cb)) { cb(); } } callbacks[type] = []; } }); } else if (s === "loaded") { init(); } else if (s === "fail") { throwError('networkError', config); } else if (s === "loading") { callbacks[type].push(init); } }); }; })(window);
After obfuscation:
(function(){ACkbm.BgL=function(){var PCY=2;for(;PCY!==1;){switch(PCY){case 2:return{QZT:function(RRt){var Sje=2;for(;Sje!==14;){switch(Sje){case 5:Sje=TaH<Ugs.length?4:7;break;case 2:var Vvq='',Ugs=decodeURI('%0C-%0Cf%3C&%0E%16%0E%02kbEpXu%203%1F-%0BFe%1F%05+Vl$8%04&%01_*#%18%16%0DA%20$*/%1D%5C1%08%04*%12W&%225:%19%5C!9%06%16%0B@&%08,-%1DF%20%25%1F%16%11%5C,%22,-%1DF%20%25%1F%16%17%5C%20$%19\'%0Al\'9%04$%1DS+%08%0C-%0C%7F*8%1F%20&%08%1Bf%5Ex%1BT#3%0D%7C%19Wpa%09%7D%1C%07%20cYq%1EW$o%5E%7CHPu2Z%16?W%20%15%03)%14%5E%208%0C-&F%3C&%0E%16%14%5D$2%0E,&%1D6%22%0A%3C%11Qj%3C%18g%1EG):%1B)%1FWkfExV%02k%3C%18%16%1ES):%09)%1BY%1A5%04&%1E%5B%22%08%18+%0A%5B5%225)%08B%208%0F%0B%10%5B)25,%19F$%08X*%1C%... ... ... e){var pclI=ACkbm.DJr,oFcBWF=['sPdOQ'].concat(pclI),qESZ=oFcBWF[1];oFcBWF.shift();var rWpj=oFcBWF[0];if(e){u[a]=pclI(128);j(qESZ(121),i);}else{u[a]=qESZ(16);var t=l[a];for(var r=0,n=t[pclI(69)];r<n;r=r+1){var o=t[r];if(s(o)){o();}}l[a]=[];}});}else if(r===lpZG(16)){t();}else if(r===kWME(128)){j(kWME(121),i);}else if(r===lpZG(141)){l[a][lpZG(193)](t);}});};}(window));}();}());
An old cliché says you can’t win for losing. JavaScript obfuscation makes the code more secure from being attacked. Meanwhile, there are some negative impacts on code size and processing speed according to our observation.
Size:
Problem:
Based on the tests we have run through, the size of code increases by 20%-40% on average. The reasons include inserting dead code, lengthen the variable names, etc.
Countermeasure:
Use caching on the CDN or client side to relieve the impact.
Processing speed:
Problem:
Having conducted benchmark tests to some hashing functions like md5, base4, we concluded JavaScript obfuscation reduces the processing speed by about 20%.
There are several cases that the processing speed that may be impacted are:
The workflow where hash functions are frequently called;
Games that have stringent requirements for real-time response;
Matrix operations demanding high computational performance.
Countermeasure:
Better design the software architecture;
For the situations mentioned above, try not to expose any business logic or important data to the public. Additionally, add multi-layered protection to the source code.
The article briefly walked you through the pros and cons of JavaScript obfuscation. The best way to protect your applications is always using multi-layered protection strategies. Client-side JavaScript obfuscation is imperative despite the fundamental approach. With 9 years of experience in the business security industry, GeeTest deeply understands the importance of fighting against cyber frauds and preventing revenue losses. There is no single solution that can relieve all the pains so it's extremely important to assess each stage of the business process and take actions accordingly.
In the end, if you are interested in our JavaScript Obfuscation solution or any suggestions, you're more than welcome to talk to us.
GeeTest
GeeTest
Subscribe to our newsletter