Protecting JavaScript source code using obfuscation - OWASP Europe Tour 2013 Lisbon


Published on

The goal of code obfuscation is to delay the understanding of what a program does. It can be used, for example, in scenarios where the code contains Intellectual Property (algorithms) or when the owner wants to prevent a competitor for stealing and reusing the code. To achieve it, an obfuscation transformation translates easy to understand code into a much harder to understand form. But in order to be resilient, obfuscation transformations need also to resist automatic reversal performed using static or dynamic code analysis techniques. This presentation focuses on the specific case of JavaScript source obfuscation, main usage cases, presents some obfuscation examples and their value in providing real protection against reverse-engineering.

Published in: Technology
  • You can try the new site for Free ... it embeds the js code into a image ... Hope to be helpful
    Are you sure you want to  Yes  No
    Your message goes here
  • Hello @prasad1210 - That result is achieved using JScrambler ( and the source code transformations indicated in the slide. Its not the most obfuscated version you can get with JScrambler, but rather an example of how the combination of several obfuscation techniques results in better protection (more obfuscation potency and more obfuscation resilience). It can be achieved directly using the JScrambler website (you don't have to code anything) or automated using one of the supplied JScrambler API clients (e.g. PHP, Java). You can extend these clients and/or integrate them with your build process/application.
    Are you sure you want to  Yes  No
    Your message goes here
  • Any implementation of 'All Together Now' mentioned on Slide 43?

    way to implementation also would be great help (preferred Java / PHP).
    Are you sure you want to  Yes  No
    Your message goes here
  • I used to play with things like this in my teenage years! :-)
    Good stuff though!
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide

Protecting JavaScript source code using obfuscation - OWASP Europe Tour 2013 Lisbon

  1. 1. Protecting JavaScriptsource code usingobfuscationFacts and FictionPedro Fortuna, Co-Founder and CTOAuditMarkOWASP Europe Tour 2013Lisbon - June 21st, 2013
  2. 2. 2CodeObfuscationconceptsCodeObfuscationmetricsPracticalexamplesOutlineOWASP Europe Tour 2013
  4. 4. 4Obfuscation“transforms a program into a form that is more difficult for anadversary to understand or change than the original code” [1]Where more difficult means“requires more human time, more money, or more computing powerto analyze than the original program.”[1] in Collberg, C., and Nagra, J., “Surreptitious software: obfuscation, watermarking, andtamperproofing for software protection.”, Addison-Wesley Professional, 2010.Code ObfuscationOWASP Europe Tour 2013
  5. 5. 5Lowers the code quality in terms ofReadability MaintainabilityDelay program understandingTime required to reverse it > programuseful lifetimeResources needed to reverse it > valueobtained from reversing itDelay program modificationCost reversing it > cost of developing itfrom scratchCode ObfuscationOWASP Europe Tour 2013
  6. 6. 6Obfuscation != EncryptionWebApplicationEncryptionAlgorithmDecryptionAlgorithmJS EngineExecutable JavaScriptSource CodeExecutable JavaScriptSource CodeNon-ExecutableEncrypted CodeEncryption Key Decryption Key{{{• This is a common misconception• Encrypted code is not executable by the browser or JS Engine• A decryption process is always neededOWASP Europe Tour 2013
  7. 7. 7Obfuscation != EncryptionWebApplicationObfuscationEngineJS EngineExecutable JavaScriptSource CodeExecutable JavaScriptSource Code{{• JavaScript obfuscated code is still valid, ready to execute code• It does not require a symmetric deobfuscation functionOWASP Europe Tour 2013
  8. 8. 8JavaScript Obfuscation Example #1HTML5 Canvasexample• Being JavaScript, this code is delivered to the browser as cleartext, and as such, it can be captured by anyone
  9. 9. 9JavaScript Obfuscation Example #1• This is the obfuscated version of the code.• It can still be captured by anyone, but it is much harder tograsp and to change.
  10. 10. What is it good for?Good• Prevent code theft and reuse– E.g. Stop a competitor from using your codeas a quickstart to build its own• Protect Intellectual Property– Hide algorithms– Hide data– DRM (e.g. Watermarks)• Enforce license agreements– e.g. domain-lock the code• As an extra security layer– Harder to find vulnerabilities in the client-side• Test the strength of security controls(IDS/IPS/WAFs/web filters)Evil• Test the strength of security controls(IDS/IPS/WAFs/web filters)• Hide malicious code• Make it look like harmless codeOWASP Europe Tour 2013
  11. 11. 11• Question often raised: why not move security sensitive code tothe server and have JS request it whenever needed ?• Sometimes you can... and you should!• But there are plenty situations where you can’t:– You may not have a server• Widgets• Mobile Apps• Standalone, offline-playable games• Windows 8 Apps made with WinJS– You may not want to have a server• May not be cost effective doing computations on a server (you have to guarantee 100% uptime,support teams)• LatencyWhy not rely on the Server?OWASP Europe Tour 2013
  13. 13. 13• Potency• Resilience• Stealthiness• Execution Cost• MaintainabilityMeasuring ObfuscationNext:• We’ll present each metric usingsimple examples• This is intentional, to ease theprocess of understanding themetrics• However, they do not represent tothe full extent what you can obtainif you combine a large set ofdifferent obfuscationtransformations.OWASP Europe Tour 2013
  14. 14. 14Generates confusionObfuscation PotencyMeasuring Obfuscation• Measure of confusion that a certainobfuscation adds• Or “how harder it gets to read andunderstand the new form whencompared with the original”• To the left you can see a simpleexample of a factorial functionOWASP Europe Tour 2013
  15. 15. 15Generates confusionObfuscation PotencyMeasuring ObfuscationRename all + Comment removal• Now to the right you see the result of renaming every symbol to a mix of lower and upper O’s.We all know that function names and variable names are quite useful for the purpose ofunderstanding the code. Not only we’ve lost that, but the new names can be easily confused.• Also comments were removed. They are also important to understand a program.• So we can definitely say that the obfuscation introduced a certain degree of confusion. It hasadded some potency.
  16. 16. 16Generates confusionObfuscation PotencyMeasuring ObfuscationRename all + Comment removalWhitespace removal• Now, below, you can see the result of removingwhitespaces from the code. It becomes slightly moreconfusing, so we can say it is slighly more potent thanthe previous example.
  17. 17. 17Resistance to deobfuscation techniquesbe it manual or automaticObfuscation ResilienceMeasuring Obfuscation• Represents the measure of theresistance that a certain obfuscationoffers to deobfuscation techniques• Or “how hard it is to undo the backto the original form”• To the left you can see the sameexample function as beforeOWASP Europe Tour 2013
  18. 18. 18Resistance to deobfuscation techniquesbe it manual or automaticObfuscation ResilienceMeasuring ObfuscationRename all + Comment removal• On the right you can see the result of applying rename_allobfuscation.• This is an example of an obfuscation which is 100% resilient,because, assuming that you don’t have access to the originalsource code, it’s impossible to tell what were the original names.• The comment removal obfuscation is also 100% resilient as youcan’t possibly know if the original form had any comments andrecover them
  19. 19. 19Resistance to deobfuscation techniquesbe it manual or automaticObfuscation ResilienceMeasuring ObfuscationRename all + Comment removalString splitting• on the bottom, you see the result after applying stringsplitting.• You can definitly see that it is more potent than theprevious, but if you look carefully, you can see that itsnot hard to revert back to the previous form.• So we can say that this version does not really addmuch resilience when compared with the previousform.
  20. 20. 20One way of attacking obfuscation is using a Static Code Analyser1. Parses the code2. Transforms it to fullfill a purpose– Usually to make it simpler => better performance– Simpler also fullfills reverse-engineering purpose• Example simplifications– Constant propagation, constant folding– Remove (some) dead code• And most importantly, it is automatic!Static Code Analysisfor defeating obfuscationConstant propagation:x = 10;y = 7 – x / 2;x = 10;y = 7 – 10 / 2;Constant folding:N = 12 + 4 – 2;N = 14;OWASP Europe Tour 2013
  21. 21. 21• We used Google Closure Compiler, a Static Code Analyser to simplify the code.• The result is on the right, which as you can see returned much easier to read code.
  22. 22. 22• If we compare the code on the right with the original code (on the left) wecan see that they are not far apart.• So the potency of the obfuscation is only apparent. The real potency or thepotency we should consider is the one that you get after using automatedways of reversing the code.• This does not mean that the string-splitting obfuscation is useless. It has tobe combined with other obfuscations that provide more resilience.
  23. 23. 23• Another way of attacking obfuscation• Analysis performed by executing the code– Retrieves the Control flow graph (CFG) of the code executed– Retrieve values of some expressions• How it can be used to defeat obfuscation– Understand (one instance of) the program execution• You can focus on parts that you are sure that are executed– Retrieve values of some expressions• Aids code simplification• Find needle in the haystack => e.g. retrieve encryption key– Bypasses deadcode– Not very good for automatic reversal of obfuscation• May not “see” all useful code• If you need to make sure the code will remain 100% functional, you cannot use this technique– Gather knowledge for manual reverse engineeringDynamic Code Analysisfor defeating obfuscationOWASP Europe Tour 2013
  24. 24. 24• How hard is to spot?– Or “how hard is to spot the changes performed by theobfuscation”– Or “how successfull the obfuscation was in making theobfuscated targets look like other parts of the code”• An obfuscation is more stealthy if it avoids common telltaleindicators– eval()– unescape()– Large blocks of meaningless textObfuscation StealthinessMeasuring ObfuscationOWASP Europe Tour 2013
  25. 25. 25• Impact on performance– Runs per second– FPS (e.g. Games)– Usually obfuscation does not have a positive impact on performance, but it doesnot necessarily have a negative impact. It depends on the mix of transformationschosen and on the nature of the original source code.• E.g. Renaming symbols => Same execution cost• Impact on loading times– Time before starting executing– Usually a function of file size– Usually obfuscation tends to grow filesize. But there are also some obfuscationtransformations which also makes it smaller.• E.g. Renaming symbols againObfuscation Execution CostMeasuring Obfuscation
  26. 26. 26Effect on maintainability = 1/potency (after static code analysis)Lower maintainability => mitigates code theft and reuseThis is one of the most importantconcepts around obfuscationObfuscation & MaintainabilityMeasuring ObfuscationOWASP Europe Tour 2013
  28. 28. 28Compression/Minification vs Obfuscation• This first example aims to clarify one of the most commonmisconceptions around obfuscation: a lot of people do notunderstand very well the difference between compressingor minifying the code and obfuscating it.• This code is a portion of a md5 function in JavaScript.
  29. 29. 29Compression/Minification vs Obfuscation• This is a compressedversion of it• It really seems to be morepotent. No doubt about it.
  30. 30. 30Compression/Minification vs Obfuscation• But look, it has got an eval()on it. Not much stealthy.• It is needed because thejavascript has been encodedand the result of decoding itmust be evaluated inruntime.• When encoding is used,there is always a decodingfunction somehwere.• The real questions is: Is itresilient ?
  31. 31. 31eval((function(....)));document.write(‘<textarea>(function(...))</textarea>’);A simple trick will do it• By replacing the eval() with adocument.write (just oneway to do it) you get accessto the decoded source.OWASP Europe Tour 2013
  32. 32. 32Reverse-engineered resultOriginal source• And that results in the code you see on the right. If you compare with the original source code, you can see that it’s pretty muchthe same code.• To many this isn’t surprising, but a lot of people uses JavaScript compressors or minifiers with the intention of protecting the code.• This is perfect example of a code transformation that is very potent but with almost null resilience.• Compressor/Minifier tools do not aim at protecting the code. Their sole purpose is to make it smaller and faster.
  33. 33. 33• First JavaScript version proposed by Yosuke Hasegawa (in, Jun 2009)• Encoding method which uses strictly non-alphanumeric symbols• Example: alert(1) (obfuscated version below)Non alphanumeric Obfuscation
  34. 34. 34• Using type coercion and browser quirks• We can obtain alphanumeric characters indirectlyHow is that possible ?+[] -> 0+!+[] -> 1+!+[]+!+[] -> 2 Easy to get any number+”1” -> 1 Type coercion to number“”+1 = “1” Type coercion to stringHow to get letters?+”a” -> NaN+”a”+”” -> “NaN”(+”a”+””)[0] -> “N”Ok, but now without alphanumerics:(+”a”+””)[+[]] -> “N”How to get an “a” ?![] -> false![]+“” -> “false”(![]+””)[1] -> “a”(![]+””)[+!+[]](+(![]+"")[+!+[]]+””)[+[]] -> “N”eval( (![]+"")[+!+[]]+"lert(1)");OWASP Europe Tour 2013
  35. 35. 35
  36. 36. 36• “eval” uses alphanumeric characters!• eval() is not the only way to eval() !• You have 4 or 5 methods more• Examples– Function("alert(1)")()– Array.constructor(alert(1))()– []["sort"]["constructor"]("alert(1)")()• Subscript notation• Strings (we already know how to convert them)Wait... What about the eval ?OWASP Europe Tour 2013
  37. 37. 37Let me see that again!OWASP Europe Tour 2013
  38. 38. 38• 100% potent• 0% stealthy (when you see it, you know someone is trying to hide something)• High execution cost– eval is a bit slower– But the worst is: file is much larger => slower loading times• May not work in all browsers• What about resilience ?– Unfortunately, not much (you can get a parser to simplify it back to theoriginal source)• Good for bypassing filters (e.g. WAFs)Non alphanumeric ObfuscationOWASP Europe Tour 2013
  39. 39. 39Original source codeDeadcode injection + Rename localDeadcode injectionCan you spot whereis the dead code ?
  40. 40. 40Original source codeDeadcode injection + Rename localDeadcode injection
  41. 41. 41• Deadcode insertion is a natural way of adding confusion to a source code, and thus increasingthe potency of obfuscation.• Being deadcode, the code isn’t really executed, so this has no impact on Execution Cost• Would a Static Code Analyser remove this particular dead code?• No, because it relies on opaque predicates– Not removable using Static Code Analysis– Predicates similar to ones found in the original source ( ++stealthiness )• Randomly injected ( ++potent )• Increase complexity of control flow ( ++potent )• Dummy statements created out of own code (++potent & ++stealthiness )Deadcode injectionOWASP Europe Tour 2013
  42. 42. 42All Together NowHTML5 Canvasexample• Up to now we have mostlyseen no more than two orthree obfuscationtransformations workingtogether.• Let’s go back to the firstexample and see whathappens when we mix alarger number of codeobfuscation transformationstogether.
  43. 43. 43All Together Now• remove comments• dot notation• rename local• member enumeration• literal hooking :low• deadcode injection• string splitting :high• function reordering• function outlining• literal duplicates• expiration date "2199-12-3100:00:00"
  44. 44. 44All Together Now• As you can see, you get and heavily obfuscatedresult.• We intentionally didn’t used any encoding-based obfuscation in this example to let yousee the effect of these transformationstogether. Also, you are not seeing the wholecode here.• For the record, not all encodingtransformations are easily reversed. We coulduse for instance a Domain-lock encoding whichneeds to get the correct information from thebrowser to decode properly.
  45. 45. 45After Closure Compiler• And this is the result after running the codethrough Google Closure Compiler.• It didn’t improved the readability much becausethe obfuscation transformations offered a gooddegree of resillience.
  46. 46. 46• People often judge obfuscation based on its (aparent) potency• Its resilience and the “real” potency that matters– Potency that you get after applying automated tools to reverse it• Evaluating resilience is not trivial– Looking at simpler examples it may be relatively easy “at naked eye” to tell whichof two obfuscations is more resilient– But looking when comparing complicated obfuscated versions, that use manycode transformations, its not easy to say which version is more resilient.– This is a job for JavaScript obfuscators• They should offer not only potency, but also resilience• Make an effort to explain its users what is best to protect their code• Avoid making available options that may reduce resilienceConclusionOWASP Europe Tour 2013
  47. 47. 47• Don’t forget execution cost– And where the code is executed. A Smartphone usually has less resources than adesktop computer. Obfuscation should be tuned to the platform where the code isbeing executed.• Obfuscation can be very effective as a way to prevent code theft and reuse, by– Making it a real pain to understand of the code– Making it a real pain to change the code successfully– Significantly lower the value that can be obtained by an attacker from reversing acodeConclusionOWASP Europe Tour 2013
  48. 48. Contact InformationPedro FortunaOwner & Co-Founder & CTOpedro.fortuna@auditmark.comPhone: +351 917331552Porto - HeadquartersEdifício Central da UPTECRua Alfredo Allen, 4554200-135 Porto, PortugalLisbon officeStartup LisboaRua da prata, 121 5A1100-415 Lisboa, Portugal