TS*: Taming the Un-typed Adversary in JavaScript Aseem Rastogi (University of Maryland, College Park) Joint work with: Nikhil Swamy, Cedric Fournet, Juan Chen, Karthik Bhargavan, Pierre-Yves Strub, and Gavin Bierman
Writing Security Critical JavaScript Code is Hard ! 11/29/2018
Example – Html5 localStorage -- No schema -- No authorization localStorage.setItem(string, string), localStorage.getItem(string), … Client Storage 11/29/2018
Example – Html5 localStorage -- Enforce Schema -- Authorization -- Efficient High Integrity, Secure, Efficient Interface localStorage.setItem(string, string), localStorage.getItem(string), … Client Storage 11/29/2018
Let’s write Storage library in JavaScript ! JS Demo ! Let’s write Storage library in JavaScript ! 11/29/2018
That didn’t turn out well, huh ? JS Demo ! (Demo elided: The basic idea is that despite writing clean idiomatic code in JavaScript providing a localStorage API, when interacting with a malicious third-party script in the same page, the clean code can easily be subverted by the third-party. Attacks include prototype poisoning, global namespace corruption, stack walks, etc. ) That didn’t turn out well, huh ? 11/29/2018
Migration from JavaScript to TS* Security Critical Code in JS No Heap Separation No Heap Separation Low Effort Migration Other App Code in JS (e.g. UI) Third-party Code in JS (e.g. Ads) Complete Heap Separation Complete Heap Separation Security Critical Code in TS* Gradually-typed, Idiomatic JS 11/29/2018
Let’s try writing Storage library in TS* TS* Demo ! See: http://rise4fun.com/FStar/tutorial/tsStar Let’s try writing Storage library in TS* 11/29/2018
TS* Demo ! Pretty Cool, isn’t it ! 11/29/2018
Gradual Security 11/29/2018
TS* Tour with Example type Point : { x : number; y : number }; function bar (t) { t.x = true; } function foo ( s : Point ) : number { bar ( s ); return s.x + s.y; } var r = { x = true }; r.x = 2; r.y = 3; foo ( r ); 11/29/2018
TS* Tour with Example type Point : { x : number; y : number }; function bar (t) { t.x = true; } function foo ( s : Point ) : number { bar ( s ); return s.x + s.y; } var r = { x = true }; r.x = 2; r.y = 3; foo ( r ); 11/29/2018
TS*: Gradually Typed Gradual type system, compiles to JavaScript type Point : { x : number; y : number }; function bar (t) { t.x = true; } function foo ( s : Point ) : number { bar ( s ); return s.x + s.y; } var r = { x = true }; r.x = 2; r.y = 3; foo ( r ); Gradual type system, compiles to JavaScript Supports idiomatic JavaScript 11/29/2018
TS*: RTTI based Gradual Typing type Point : { x : number; y : number }; function bar (t) { t.x = true; } function foo ( s : Point ) : number { bar ( s ); return s.x + s.y; } var r = { x = true }; r.x = 2; r.y = 3; foo ( r ); Every value carries a type tag at run-time 11/29/2018
TS*: RTTI based Gradual Typing type Point : { x : number; y : number }; function bar (t) { t.x = true; } function foo ( s : Point ) : number { bar ( s ); return s.x + s.y; } var r = { x = true }; ◄ r.x = 2; r.y = 3; foo ( r ); any { x = true } r: 11/29/2018
TS*: Type Safety in Any-typed Code type Point : { x : number; y : number }; function bar (t) { t.x = true; } function foo ( s : Point ) : number { bar ( s ); return s.x + s.y; } var r = { x = true }; r.x = 2; ◄ r.y = 3; foo ( r ); Instrumented with run time type checks Must respect RTTI tags 11/29/2018
TS*: Type Safety in Any-typed Code type Point : { x : number; y : number }; function bar (t) { t.x = true; } function foo ( s : Point ) : number { bar ( s ); return s.x + s.y; } var r = { x = true }; r.x = 2; ◄ r.y = 3; foo ( r ); Is r a record ? Does ( r.x = 2 ) respect r’s RTTI ? ✔ any { x = true } r: any { x = 2 } r: 11/29/2018
TS*: Type Safety in Any-typed Code type Point : { x : number; y : number }; function bar (t) { t.x = true; } function foo ( s : Point ) : number { bar ( s ); return s.x + s.y; } var r = { x = true }; r.x = 2; r.y = 3; ◄ foo ( r ); Is r a record ? Does ( r.y = 3 ) respect r’s RTTI ? ✔ any { x = true } r: any { x = 2 } r: any { x = 2; y = 3 } r: 11/29/2018
TS*: RTTI Evolution Check that value has expected type … type Point : { x : number; y : number }; function bar (t) { t.x = true; } function foo ( s : Point ) : number { bar ( s ); return s.x + s.y; } var r = { x = true }; r.x = 2; r.y = 3; foo ( r ); ◄ Check that value has expected type … And tag it -- RTTI tags evolve Ensures type safety in the presence of mutable records 11/29/2018
TS*: RTTI Evolution ✔ Is r a Point ? type Point : { x : number; y : number }; function bar (t) { t.x = true; } function foo ( s : Point ) : number { bar ( s ); return s.x + s.y; } var r = { x = true }; r.x = 2; r.y = 3; foo ( r ); ◄ Is r a Point ? ✔ any { x = 2; y = 3 } r: Point { x = 2; y = 3 } r, s: 11/29/2018
TS*: Any-subtyping Seamless via Subtyping type Point : { x : number; y : number }; function bar (t) { t.x = true; } function foo ( s : Point ) : number { bar ( s ); ◄ return s.x + s.y; } var r = { x = true }; r.x = 2; r.y = 3; foo ( r ); Seamless via Subtyping 11/29/2018
TS*: Type Safety in Any-typed Code type Point : { x : number; y : number }; function bar (t) { t.x = true; ◄ } function foo ( s : Point ) : number { bar ( s ); return s.x + s.y; } var r = { x = true }; r.x = 2; r.y = 3; foo ( r ); Is t a record ? Does ( t.x = true ) respect t’s RTTI ? ✗ Point { x = 2; y = 3 } r, s, t: ( t.x = true ) fails s remains as is 11/29/2018
TS*: Statically-typed Code type Point : { x : number; y : number }; function bar (t) { t.x = true; } function foo ( s : Point ) : number { bar ( s ); return s.x + s.y; ◄ } var r = { x = true }; r.x = 2; r.y = 3; foo ( r ); Executes as is No runtime checks in statically-typed code 11/29/2018
TS*: Un – The Other Dynamic Type type Point : { x : number; y : number }; show : Un function foo ( s : Point ) : number { show ( s ); return s.x + s.y; } Interaction with Un-typed code mediated by wrappers Enforce heap separation from Un code 11/29/2018
TS*: Defensive Wrapper for Un type Point : { x : number; y : number }; show : Un function foo ( s : Point ) : number { show ( s ); ◄ return s.x + s.y; } wrap ( Un, Point unit ) ( show ) ( s ) var t1 = wrap ( Point, Un ) ( s ); /* makes a deep copy of s */ var t2 = show ( t1 ); wrap ( Un, unit) ( t2 ) 11/29/2018
TS* Summary Statically-typed code: Any-typed code: Un-typed code: No run-time type checks No run-time failures No performance penalty (except adding RTTI tags) Any-typed code: Instrumented with run-time type checks Respects RTTI tags set by the statically-typed code Un-typed code: Complete heap separation from TS* code 11/29/2018
You still don’t know all we did this summer ! Support for Arrays in TS* Performance Tweaking Formalization of TS* compilation in JSVerify† Type soundness proof Submitted TS* work to POPL’14 Spent couple of weeks reading Mental Poker ! †Swamy et. al. POPL’ 13 11/29/2018
TS* Summary TypeScript like surface language Gradual type system, compiles to JavaScript Not one, but two dynamic types Any and Un Type safe (unlike TypeScript) Even when interacting with malicious context 11/29/2018