Fuzzing JavaScript Engines with Aspect-preserving Mutation Soyeon Park, Wen Xu, Insu Yun, Daehee Jang, Taesoo Kim
Everyone uses web browser (+ JS engine) 4,000,000,000 2
New Tab https://gts3.org/ Bank Private Password account data S&P’20! 3
JS bugs are security-critical ( ) 9/11 (82%) 2017 2018 2019 2020 5
Finding JS bugs is hard 443K 1M • Large codebase 995K 797K 6
Finding JS bugs is hard • Deep semantic bugs JS engine Parser / Interpreter JIT compiler Executor 8
Finding JS bugs is hard • Deep semantic bugs 1 25 JIT-OOB JIT-Type confusion JIT-Memory corruption Parser/Interpreter 20 # of Bugs 15 Complex & deep bugs 10 Simple & shallow bugs 5 0 2016 2017 2018 2019 Year 1 Google Project Zero issue trackers and commits of ChakraCore for security updates by Aug 2019 9
Motivating example • Special conditions are necessary to discover new bug from old ones • What human hacker is good at 10
Motivating example • Special conditions are necessary to discover new bug from old ones • JIT-able condition by for-loop & empty object 11
Motivating example • Special conditions are necessary to discover new bug from old ones • “Function” which has side-effect 12
Motivating example • Special conditions are necessary to discover new bug from old ones • Instruction order 13
Motivating example • Special conditions are necessary to discover new bug from old ones • Newly introduced code 14
Aspects • Key features that guide to discover new bugs, which are embedded in the Proof-of-Concept of existing bugs Assign float values to an array and order of the instructions Type confusion 15
Aspects • Key features that guide to discover new bugs, which are embedded in the Proof-of-Concept of existing bugs Assign float values to an array and order of the instructions For loop to invoke JIT compiler 16
Aspects • Key features that guide to discover new bugs, which are embedded in the Proof-of-Concept of existing bugs Assign float values to an array and order of the instructions For loop to invoke JIT compiler Arrow function to assign object value to the same array 17
Ou Our so solu lutio tion: DIE: Fuzzing JS engine with generation and Aspect-preserving mutation 21
DIE overview w/ instrumented Dynamic & JS engine Static analysis Input Typed-AST JS file Crash! Preprocessing Execution generation Original Seeds Code coverage Feedback 22
Preprocessing for typed-AST Pre-Processing Dynamic Analysis w/ instrumented Dynamic & JS engine Static analysis Typed-AST Instrument IMMUTABL E while … Type analysis Input Typed-AST JS file Input Crash! == Preprocessing Execution NUM generation [] 1 generation NUM a 0 NUM NUM Original Seeds Static Analysis ARRAY Code coverage AST + Type Information Feedback 23
Type Analysis: dynamic analysis • Execute instrumented corpus Corpus recordType() var n = 3 recordType() var array = new Array(n) recordType() 24
Type Analysis: dynamic analysis • Execute instrumented corpus Corpus recordType() var n = 3 recordType() var array = new Array(n) recordType() 25
Type Analysis: dynamic analysis • Execute instrumented corpus Corpus recordType() var n = 3 recordType() n : number var array = new Array(n) recordType() 26
Type Analysis: dynamic analysis • Execute instrumented corpus Corpus recordType() var n = 3 recordType() var array = new Array(n) n : number recordType() array: numberArray 27
Type Analysis: dynamic analysis • Execute instrumented corpus Type Information Corpus recordType() var n = 3 recordType() n : number var array = new Array(n) n : number recordType() array: numberArray 28
Type Analysis: static analysis • Propagate type information from bottom to top with custom rules AST while + == [] 1 Type Information 0 a 29
Type Analysis: static analysis • Propagate type information from bottom to top with custom rules Typed-AST AST IMMUTABLE while while + == == NUM [] [] 1 1 Type Information NUM 0 0 a a NUM ARRAY NUM 30
Input generation Input Generation w/ instrumented Dynamic & Typed-AST Mutated Typed-AST JS engine Static analysis IMMUTABL Generation E IMMUTABL while Engine … E while Input == Typed-AST JS file NUM NUM Crash! Preprocessing Execution == [] NUM [] generation [] 1 a . a 0 NUM a 0 NUM NUM NUM NUM Mutated ARRAY a ARRAY Mutation Original Seeds NUM NUM Seeds ARRAY Engine NUM ARRAY “length” Code coverage Mutate (Aspect-preserving) Feedback 31
Aspect-preserving mutation • Type & structure preserving mutation Assign float values to an array and order of the instructions For loop to invoke JIT compiler Arrow function to assign object value to the same array 32
Type-preserving mutation • Mutate typed-AST node with same typed node Generation + Typed-AST Engine Type IMMUTABLE Information while == NUM [] 1 NUM 0 a NUM ARRAY NUM 33
Type-preserving mutation • Mutate typed-AST node with same typed node Generation + Typed-AST Engine Type IMMUTABLE Information while NUM typed node . [] == NUM a length a 0 [] 1 NUM 0 a NUM ARRAY NUM Mutation Engine 34
Type-preserving mutation • Mutate typed-AST node with same typed node Generation + Typed-AST Engine Mutated Typed-AST Type IMMUTABLE Information IMMUTABLE while while NUM typed node . [] == NUM == NUM NUM a length a 0 [] 1 [] [] NUM 0 a NUM a 0 a . NUM NUM ARRAY NUM NUM ARRAY Mutation NUM ARRAY a length Engine 35
Structure-preserving mutation • Selectively mutate nodes to avoid breaking control-flow structure Typed-AST IMMUTABLE while Mutation == Engine NUM [] 1 NUM a 0 NUM ARRAY NUM 36
Structure-preserving mutation • Selectively mutate nodes to avoid breaking control-flow structure Typed-AST IMMUTABLE while Mutation == Engine NUM [] 1 NUM a 0 NUM ARRAY NUM 37
Execution with instrumented JS engine Execution/Feedback Instrumented w/ instrumented Dynamic & JS Engines JS engine Static analysis Execute … Input Input Typed-AST JS file generation Crash! Preprocessing Execution generation Mutated Seeds Original Seeds Distributed Fuzzing Platform Code coverage Feedback Coverage Feedback 38
Implementation • Core fuzzing engine 3,677 lines of TypeScript • Type analyzer 222 lines of Python • Dynamic instrumentation tool • Generation engine 10,545 lines of TypeScript • Mutation engine 2,333 lines of TypeScript • AFL modification 453 lines of C • Distributed fuzzing harness 205 lines of TypeScript • Coordinator 1,419 lines of Python and Shell Script • Local agent 492 lines of Python • Crash reporter 19,346 lines of code • Total 39
Evaluation Fuzzing JS engines with DIE in the wild ... and extra information to understand the techniques applied on DIE 40
Fuzzing JS engines in the wild • We ran DIE up to 3 weeks against 3 major JS engines • 48 unique bugs in total • 39 fixed bug • 11 acknowledged CVEs • 27K USD bug bounty reward as of now 41
Evaluation: effectiveness of leveraging aspect • DIE found 84 distinct crashes and 28 unique bugs in ChakaCore Preserved aspect Bug Crash Structure & Type 14/28 (50.00%) 40/84 (47.62%) Structure-only 12/28 (42.86%) 32/84 (42.86%) Total 22/28 (92.86%) 72/84 (90.48%) 42
Case study: CVE-2019-0990 • corpus: CVE-2018-0777 Generation w/ type information Mutation (structure preserving) Mutation (type preserving) 43
Evaluation: aspect preserving • Ratio difference of JIT-optimization phase invocation between the generated inputs and seed files 200 Forward • vs DIE t : 1.53x FGPeeps FGBuild 175 Backward Optimization Invocation Rate (%) • vs CodeAlchemist : 4.29x CaptureByteCodeRegUse BackEnd 150 DeadStore • vs Superion: negligible GlobOpt Etc 125 • Mutation-based fuzzer 100 75 50 DIE t : DIE without structure-preserving 25 (type preserving only) 0 Die t Superion CodeAlchemist Die 44
Evaluation: validity of generated input • Error rate of generated inputs • vs Superion: 2.31x SyntaxError • vs CodeAlchemist: 2.31x ReferenceError 40 TypeError • vs jsfunfuzz: 2.42x RangeError • DIE c produces less error rate than Error Rate (%) 30 vanilla 20 10 DIE c : DIE without coverage feedback 0 Vanilla Die c Die Superion CodeAlchemist jsfunfuzz Original corpus 45
Evaluation: comparison w/ state-of-the-art fuzzers • Number of unique crashes found by DIE vs state-of-the-art fuzzers for 24 hours JS engine DIE DIE t Superion CodeAlchemist ChakraCore 1.11.10 17 7 0 3 JavaScriptCore 2 0 0 0 2.24.2 V8 7.7.100 2 1 1 0 DIE t : DIE without structure-preserving (type preserving only) 47
Conclusion • DIE is a JS engine fuzzer that preserves the aspects from PoC of existing bugs achieved by type and structure preserving • Discovered 48 unique bugs with 11 CVEs assigned • Open sourced: https://github.com/sslab-gatech/DIE 48
Thank you! Q & A 49
Recommend
More recommend