Tuesday, December 18, 2012

Secure JavaScript Source for Windows 8 Store Apps

I demonstrated how to import an installed Windows JavaScript/HTML application in my previous post. JavaScript is an interpreted language and theoretically you can't prevent it from being reverse engineering. But Windows 8 store apps' architecture makes super easy for a user with administration right to see apps' source file by simply a few clicks. This is not acceptable and I agree with Justin Angel's opinion: that's a fundamental design flaw.

Originally JavaScript is designed to run inside browser. It's mainly for presentation layer and the application flow is driven by the web server. This has been evolved a bit recently due to the popularity of JavaScript, for instance the node.js framework developed for server environment. Now JavaScript becomes one of the main stream languages for developing Windows 8 store apps and the JavaScript code plays more important role there. Those apps' source is so easy to get from physical file system that it would attract people to do so. No need to jailbreak or root the Windows 8 devices, now even casual attackers can have an easy starting point simply by a few clicks. The worst thing is that most developers may not aware of that potential security hole. They simply trust Microsoft and do little or nothing to protect their application. That's why Justin was so easy to break various popular games built by C++, C#/XAML and HTML/JavaScript.

As time goes by I believe more and more measures will be introduced to address the security issues of Windows 8 store apps. For developers, what we can do is to secure our code and data. Following three methods can be used to improve the code security for Window 8 applications:

1. Move critical logic and data back to server side. This is kind of hybrid approach. The Windows 8 app runs locally but some pages or sometimes it would just act like an embedded browser.

2. Split some code into Windows Runtime Component using C#/C++/VB. The Runtime Component is compiled as a dll and can be called directly from JavaScript. For further protection we can obfuscate the code in Runtime Component.

3. Minimize/obfuscate JavaScript code. That's an easy but effective way to protect your code and your logic. Scott Hanselman has a great post going through a couple of tools to do this job. For example following batch file will go through all JavaScript in a solution folder and make a minimized version of it with .min.js extension (original js file unchanged) using AjaxMin:

dir /s /b *.js | find /v ".min.js" | find /v "\bin\" > jsminlist.txt
for /f "usebackq delims=" %%x in (`findstr /V min.js jsminlist.txt`) do (AjaxMinifier.exe "%%x" -o "%%~dpx/%%~nx.min.js" -clobber)
Note that the AjaxMin's executable AjaxMinifier.exe needs to be copied to the solution's root folder before running above script. After run the batch command, we simply exclude the original javascripts not ending with *.min.js, and include those minimized version of JavaScript ending with *.min.js, then update all html files to reference the new JavaScript.

Another topic is secure the data we stored in client machine. I will discuss that in my next post.

Update 2013-01:
1. when publishing the app if you get app validation error of "xxx.js is not properly UTF-8 encoded. Re-save the file as UTF-8 (including Byte Order Mark).", you simple the open the JavaScript file in Visual Studio and click File => Save xxxx.js As... from the menu, select "Save with Encoding" (default is "Save") from the popup window, and select "Unicode (UTF-8 without signature) - Codepage 65001" encoding format then click OK to save the file with proper format for publishing.

2. if get the "Optimized Binding References" error during app validation, something like "WinJS.Binding.optimizeBindingReferences = true is not set and data-win-bind was found in xxxx.html on line number xxx.", to resolve the problem you have to add "WinJS.Binding.optimizeBindingReferences = true;" right on top of your JavaScript if you have data binding in your page. If you get this error only after JavaScript minification, that means the Windows app certification kit doesn't recognize the obfuscated JavaScript and you need to try another tool to do the job. Using JSMin from Douglas Crockford would work for sure since it only removes the space and comments without any other code scrambling.