480 likes | 713 Views
Type-based Taint Analysis for Java Web Applications. Wei Huang , Yao Dong and Ana Milanova Rensselaer Polytechnic Institute. Taint Analysis for Java Web Applications. Untrusted input. Sensitive sinks. unsanitized. SOURCES : ServletRequest.getParameter (), etc . SINKS :
E N D
Type-based Taint Analysis for Java Web Applications Wei Huang, Yao Dong and Ana Milanova Rensselaer Polytechnic Institute
Taint Analysis for Java Web Applications Untrusted input Sensitive sinks unsanitized SOURCES: ServletRequest.getParameter(), etc. SINKS: Statement.execute(), etc • Tracks flows from untrusted sources to sensitive sinks • Such flows can cause SQL-injection, Cross-site scripting, other attacks
SQL Injection Tainted input HttpServletRequestreq = ...; Statement stat = ...; String user = req.getParameter(“user”); String query = “SELECT * FROM Users WHERE name = “ + user; stat.execute(query); “John OR 1=1” SELECT * FROM Users WHERE name = John OR 1 = 1
Work on Taint Analysis Finding Security Vulnerabilities with Static Analysis [Livshits and Lam, Usenix Security’05] TAJ [Tripp et al. PLDI’09] F4F [Sridharan et al. OOPSLA’11] Andromeda [Tripp et al. FASE’13] TAJ, F4F and Andromeda are included in a commercial tool from IBM, called AppScan
Issues with Existing Work Dataflow and points-to based approaches Reflection Libraries Frameworks
Our Type-based Taint Analysis • SFlow: a type system • SFlowInfer: inference tool for SFlow • Takes Java program where sources are typed tainted andsinks are typed safe • Infers SFlow types for the rest of the variables • If inference succeeds --- no flows from sources to sinks • If it fails with type errors --- potential flows • Easily and effectively handles reflection, libraries and frameworks
Inference and Checking Framework Parameters • Immutability (ReIm) • Universe Types (UT) • Ownership Types (OT) • SFlow • AJ • EnerJ • More? Unified Typing Rules Program Source Instantiated Rules Set-Based Solver Annotated Libraries Set-based Solution ExtractTyping Concrete Typing Type Checking
SFlowInfer Sources and Sinks Annotated Libraries Java source Result SFlowInfer The instantiated inference tool Detects (or verifies the absence of) information flow violations
SQL Injection Source: the return value is tainted HttpServletRequestreq = ...; Statement stat = ...; tainted String user = req.getParameter(“user”); tainted String query = “SELECT * FROM Users WHERE name = “ + user; stat.execute(query); Sink: the parameter is safe Subtyping: safe<: tainted Type error!
Contributions • SFlow: A context-sensitive type system for secure information flow • SFlowInfer: An inference algorithm for SFlow • SFlowInfer is an effective taint analysis tool • Implementation and evaluation
Outline SFlowtype system Inference algorithm for SFlow Handling of reflection, libraries and frameworks Implementation and evaluation
SFlowType Qualifiers • safe<: poly <: tainted tainted: A variable x is tainted, if there is flow from an untrusted source to x safe: A variable x is safe if there is flow from x to a safe sink poly: The polymorphic qualifier, can be instantiated to taintedor safe
Instantiated Typing Rules for SFlow Viewpoint adaptation accounts for context sensitivity.qy is the context of adaptation. (TCALL) Additional constraints… T
Outline SFlowtype system Inference algorithm for SFlow Handling of reflection, libraries and frameworks Implementation and evaluation
Inference and Checking Framework Parameters • Immutability (ReIm) • Universe Types (UT) • Ownership Types (OT) • SFlow • AJ • EnerJ • More? Unified Typing Rules Program Source Instantiated Rules Set-Based Solver Annotated Libraries Set-based Solution ExtractTyping Concrete Typing Type Checking
Set-based Solver • Set Mapping S: • variable {tainted, poly, safe} • Iterates over statements s • Removes infeasible qualifiers for each variable in saccording to the typingrule • Until reaches a fixpoint, and outputs • Type errors if one or more variables get assigned the empty set, or • A set-based solution
From Stanford Securibench-micro StringBufferbuf; … foo(buf, buf, resp, req); void foo(StringBufferb,StringBuffer b2, ServletResponseresp, ServletRequestreq) { String name; name = req.getParameter(NAME);//source b.append(name); PrintWriterwriter = resp.getWriter(); String str = b2.toString(); writer.println(str); //sink }
From Stanford Securibench-micro StringBufferbuf; … foo(buf, buf, resp, req); void foo(StringBufferb,StringBuffer b2, ServletResponseresp, ServletRequestreq) { String name; name= req.getParameter(NAME);//source b.append(name); PrintWriterwriter = resp.getWriter(); String str = b2.toString(); writer.println(str); //sink }
From Stanford Securibench-micro StringBufferbuf; … foo(buf, buf, resp, req); void foo(StringBufferb,StringBuffer b2, ServletResponseresp, ServletRequestreq) { String name; name= req.getParameter(NAME);//source b.append(name); PrintWriterwriter = resp.getWriter(); String str = b2.toString(); writer.println(str); //sink }
From Stanford Securibench-micro StringBufferbuf; … foo(buf, buf, resp, req); void foo(StringBufferb,StringBuffer b2, ServletResponseresp, ServletRequestreq) { String name; name= req.getParameter(NAME);//source b.append(name); PrintWriterwriter = resp.getWriter(); String str = b2.toString(); writer.println(str); //sink }
From Stanford Securibench-micro StringBufferbuf; … foo(buf, buf, resp, req); void foo(StringBufferb,StringBuffer b2, ServletResponseresp, ServletRequestreq) { String name; name= req.getParameter(NAME);//source b.append(name); PrintWriterwriter = resp.getWriter(); String str = b2.toString(); writer.println(str); //sink }
From Stanford Securibench-micro StringBufferbuf; … foo(buf, buf, resp, req); void foo(StringBufferb,StringBuffer b2, ServletResponseresp, ServletRequestreq) { String name; name= req.getParameter(NAME);//source b.append(name); PrintWriterwriter = resp.getWriter(); String str = b2.toString(); writer.println(str); //sink, BAD! }
Set-based Solver {tainted,poly,safe} StringBufferbuf; … foo(buf, buf, resp, req); void foo({tainted,poly,safe} StringBufferb, {tainted,poly,safe} StringBuffer b2, ServletResponseresp, ServletRequestreq) { {tainted,poly,safe} String name; name = req.getParameter(NAME);//source b.append(name); PrintWriterwriter = resp.getWriter(); {tainted,poly,safe} String str = b2.toString(); writer.println(str); //sink, BAD: flow from source! }
Set-based Solver {tainted,poly,safe} StringBufferbuf; … foo(buf, buf, resp, req); void foo({tainted,poly,safe} StringBufferb, {tainted,poly,safe} StringBuffer b2, ServletResponseresp, ServletRequestreq) { {tainted,poly,safe} String name; name = req.getParameter(NAME);//source b.append(name); PrintWriterwriter = resp.getWriter(); {tainted,poly,safe} String str = b2.toString(); writer.println(str); //sink, BAD: flow from source! }
Set-based Solver {tainted,poly,safe} StringBufferbuf; … foo(buf, buf, resp, req); void foo({tainted,poly,safe} StringBufferb, {tainted,poly,safe} StringBuffer b2, ServletResponseresp, ServletRequestreq) { {tainted,poly,safe} String name; name = req.getParameter(NAME);//source b.append(name); PrintWriterwriter = resp.getWriter(); {tainted,poly,safe} String str = b2.toString(); writer.println(str); //sink, BAD: flow from source! }
Set-based Solver {tainted,poly,safe} StringBufferbuf; … foo(buf, buf, resp, req); void foo({tainted,poly,safe} StringBufferb, {tainted,poly,safe} StringBuffer b2, ServletResponseresp, ServletRequestreq) { {tainted,poly,safe} String name; name = req.getParameter(NAME);//source b.append(name); PrintWriterwriter = resp.getWriter(); {tainted,poly,safe} String str = b2.toString(); writer.println(str); //sink, BAD: flow from source! }
Set-based Solver {tainted,poly,safe} StringBufferbuf; … foo(buf, buf, resp, req); void foo({tainted,poly,safe} StringBufferb, {tainted,poly,safe} StringBuffer b2, ServletResponseresp, ServletRequestreq) { {tainted,poly,safe} String name; name = req.getParameter(NAME);//source b.append(name); PrintWriterwriter = resp.getWriter(); {tainted,poly,safe} String str = b2.toString(); writer.println(str); //sink, BAD: flow from source! }
Set-based Solver {tainted,poly,safe} StringBufferbuf; … foo(buf, buf, resp, req); void foo({tainted,poly,safe} StringBufferb, {tainted,poly,safe} StringBuffer b2, ServletResponseresp, ServletRequestreq) { {tainted,poly,safe} String name; name = req.getParameter(NAME);//source b.append(name); PrintWriterwriter = resp.getWriter(); {tainted,poly,safe} String str = b2.toString(); writer.println(str); //sink } Type error!tainted or poly str cannot be assigned to safe parameter!
Set-based Solver (Cont’d) • What if the set-based solver terminates without a type error? • Extract the maximal typing from set-based solution according to preference ranking tainted > poly > safe • If S(x) = {poly, safe} the maximal typing types x poly • Unfortunately, the maximal typing for SFlow does not always type-check
Inference and Checking Framework Parameters • Immutability (ReIm) • Universe Types (UT) • Ownership Types (OT) • SFlow • AJ • EnerJ • More? Unified Typing Rules Program Source Instantiated Rules Set-Based Solver Annotated Libraries Set-based Solution Extract Typing Concrete Typing Type Checking
Maximal Typing class A { {String f; {String get(A this) { return this.f; } } A y = ...; String x = y.get(); writer.println(x); // sink Unfortunately, the maximal typing for SFlow does not always type-check!
Maximal Typing (Cont’d) class A { {poly} String f; {poly,safe} String get({poly,safe}this) { return this.f; } } {tainted,poly,safe} A y = ...; {safe} String x = y.get(); writer.println(x);
Maximal Typing (Cont’d) class A { {poly} String f; {poly,safe} String get({poly,safe}this) { return this.f; } } {tainted,poly,safe} A y = ...; {safe} String x = y.get(); writer.println(x);
Maximal Typing (Cont’d) class A { {poly} String f; {poly,safe} String get({poly,safe}this) { return this.f; } } {tainted,poly,safe} A y = ...; {safe} String x = y.get(); writer.println(x); • ✗
Method Summary Constraints String id(String p) { String x = p; return x; } Reflect the relations between parameters and return values Further remove infeasible qualifiers
Method Summary Constraints (Cont’d) class A { {poly} String f; {poly,safe} String get({poly,safe}this) { return this.f; } } {tainted,poly,safe} A y = ...; {safe} String x = y.get(); writer.println(x);
Method Summary Constraints (Cont’d) class A { {poly} String f; {poly,safe} String get({poly,safe}this) { return this.f; } } {tainted,poly,safe} A y = ...; {safe} String x = y.get(); writer.println(x); • ✔
Outline SFlowtype system Inference algorithm for SFlow Handling of reflection, libraries and frameworks Implementation and evaluation
Reflection, Libraries and Frameworks X x = (X)Class.forName(“str”).newInstance(); x.f = a; // a is a source y = x; b = y.f; // b is a sink • Reflective object creation is easy! • There is no need to abstract heap objects! • Flow from x to y is reflected through subtyping x <:y
Reflection, Libraries and Frameworks (Cont’d) Libraries (JDK, third-party, frameworks) Unknown library methods are typed poly, poly poly safe l = r.m(r1,r2) l = r.m(tainted r1,r2)
Reflection, Libraries and Frameworks (Cont’d) • Frameworks (e.g., Struts, Spring) • Framework classes/interfaces are subclassed/implemented in web application code • Superclass-subclass relation is handled using function subtyping constraints UserAction.execute(ActionFormuserForm) <: Action.execute(taintedActionForm form) entails form <:userForm //userForm is tainted
Outline SFlowtype system Inference algorithm for SFlow Handling of reflection, libraries and frameworks Implementation and evaluation
Implementation • Built ininference and checking framework for pluggable types [Huang et al. ECOOP’12] • Instantiated framework with SFlow • Built on top of the Checker Framework [Papi et al. ISSTA’08, Dietl et al. ICSE’11] • Publicly available at • http://code.google.com/p/type-inference/
Evaluation • DroidBench • A suit of 39 Android apps by [Arzt et al. PLDI’14] for evaluating taint analysis for Android • Java web applications • Stanford Securibench:a suit by Ben Livshits designed for evaluating taint analysis • Other web applications from previous work • 13 web applications comprising 473kLOC
DroidBench [Arzt et al. PLDI’14] • SFlowInferoutperforms AppScan and Fortify SCA • FlowDroid [Arzt et al. PLDI’14] is flow-sensitive • DroidBench is designed for flow sensitivity
Java Web Applications • We manually examined all type errors • Parameter Manipulation / SQL Injection • 7 benchmarks have no type errors • 66 type errors correspond to true flows • Average false positive rate: 15% • Parameter Manipulation / XSS • 8 benchmarks have no type errors • 143 type errors correspond to true flows • Average false positive rate: 4%
Runtime Performance • SFlowInfertakes less than 3 minutes on all but 2 benchmarks • Largest benchmark, photov126kLOC, takes 640 seconds • Can be optimized • Maximal heap size is set to 2GB!
Conclusion • A type system for secure information flow • An efficient type inference algorithm • Effective taint analysis tool • Evaluation on 473kLOC • Publicly available at • http://code.google.com/p/type-inference/