Towards Automatic Verification of Javascript Programs
Total Page:16
File Type:pdf, Size:1020Kb
MENG INDIVIDUAL PROJECT DEPARTMENT OF COMPUTING Towards Automatic Verification of JavaScript Programs Supervisor: Author: Prof. Philippa Gardner Beatrix de Wilde Second Marker: Prof. Alessio R. Lomuscio June 19, 2017 Abstract JavaScript, due to its dynamic nature and complex semantics, has fewer verification tools than languages such as C and Java. In order to tackle this challenge, we introduce for the first time a bi-abductive symbolic analysis for JSIL, an intermediate language for JavaScript verification. Our analysis is scalable and can fully automatically infer specifications of JSIL procedures that are non-recursive and do not contain loops. Bi-Abduction provides the foundation of our analysis; we give the rules of our bi-abductive symbolic execution and prove their soundness. We further present an algorithm for generating procedure specifications using these rules. We give an implementation of our bi-abductive analysis for JSIL and use it to generate specifi- cations for JSIL programs. Using the tool, we generate and verify specifications for some of the JavaScript internal functions. Finally, we evaluate the quality of the automatically generated specifications by comparing them with their handwritten counterparts. Acknowledgements First, I would like to thank my supervisor, Prof. Philippa Gardner, for her wholehearted support throughout this project. I would also like to thank José Fragoso Santos for all his input and feedback, it has been a privilege to work with him. I am grateful to Petar Maksimovi´c and Azalea Raad, for sharing their insight during the project. For her inspiration and advice across my time at Imperial, I would like to thank my tutor, Prof. Susan Eisenbach. Finally, I would like to thank my family and friends for their endless support across these past four years. Contents 1 Introduction 5 2 Background 7 2.1 Program Verification..................................7 2.1.1 Program Correctness..............................7 2.1.2 Static Verification Techniques.........................8 2.1.3 Related Tools..................................9 2.2 Separation Logic and Tools............................... 10 2.2.1 Hoare Logic................................... 10 2.2.2 Separation Logic................................ 10 2.2.3 Bi-Abduction.................................. 11 2.2.4 Related Tools.................................. 11 2.3 The JavaScript Language................................ 12 2.4 The JavaScript Intermediate Language........................ 13 2.4.1 Motivation for JSIL............................... 14 2.4.2 The JavaScript Intermediate Language.................... 14 2.4.3 The JavaScript Verification Toolchain..................... 17 3 Symbolic Analysis 21 2 Contents 3 3.1 Axioms for Basic Commands.............................. 21 3.2 Symbolic Execution Rules for Control Flow Commands............... 25 4 Bi-Abductive Symbolic Analysis 31 4.1 Bi-Abductive Analysis: High Level Description.................... 31 4.2 Bi-Abductive Axioms for Basic Commands...................... 32 4.3 Bi-Abductive Proof Rules for Control Flow Commands............... 35 4.4 Bi-Abductive Algorithm for JSIL Programs...................... 39 5 Implementation for Bi-Abductive Symbolic Analysis 43 5.1 Architecture....................................... 43 5.2 Implementation Challenges.............................. 45 6 Evaluation 49 6.1 Evaluation Infrastructure................................ 49 6.2 Generating Specifications for the Internal Functions................. 50 6.2.1 Specification Comparison........................... 51 7 Conclusion 55 7.1 Objectives Achieved.................................. 55 7.2 Future Work....................................... 55 Bibliography 57 A JSIL Semantics and Substitution Lemma 61 A.0.1 JSIL Substitution Lemma........................... 61 A.0.2 JSIL Semantics................................. 61 Contents 4 Chapter 1 Introduction JavaScript is the developer’s language of choice for Web applications and is supported by all major browsers. It is an untyped, dynamic language, with complicated semantics and notori- ously confusing corner cases. Among other features, it supports extensible objects, prototype inheritance, dynamic property access, dynamic functions calls, and type coercion for delaying error reporting. These features interact in an intricate and sometimes unexpected fashion and can lead to developers unknowingly introducing bugs and vulnerabilities. For example, even simple addition can perplex the seasoned developer: adding an object to an empty string results in the number 0 rather than an error, whereas reversing the arguments leads to a completely different result and type. In particular, the JavaScript program ’’+ {} results in the string ’[object Object]’ whereas the program {} + ’’ results in the number 0. In addition to the substantial economic cost resulting from vulnerabilities, program errors in medical software have led to fatalities in the past. Developers aim to reduce bugs dominantly through testing and code reviews. This requires significant developer effort and is subject to human error. Therefore program verification tools have seen a rise in the recent years. For practical applications, it is vital that these tools can scale to industrial-level codebases. Com- pared to other languages, such as Java, C, and C++, JavaScript has far fewer tools available for developers. As part of an endeavour to verify JavaScript programs, the Program Specification and Verifica- tion Group at Imperial College London has developed JaVerT [35], which is a semi-automatic verification toolchain for JavaScript based on separation logic [40]. JaVerT can verify functional correctness properties of JavaScript programs annotated with preconditions and postconditions for functions, loop invariants, and folding and unfolding instructions for user-defined predi- cates, written in an assertion language, JS Logic. JaVerT translates JavaScript programs to the simple intermediate goto language JSIL, translates JS Logic assertions to JSIL Logic assertions, and performs verification at the level of JSIL. Correctness results have been established to prove that verification at the level of JSIL lifts to verification at the level of JavaScript. As a first step towards fully automated verification of JavaScript programs, we aim to generate automatic specifications for JSIL procedures. Bi-Abduction [12] is a technique for automatically generating specifications through the use of separation logic inference rules. The properties that can be proven using bi-abduction are weaker than those provable semi-automatically, but bi- abduction allows verification tools to scale to industry-grade code bases. 5 Chapter 1. Introduction 6 Motivation There are two key motivations for having a fully automatic tool: to automatically verify gen- eral properties and to support the developer in verifying functional properties of JavaScript programs. Specifications provide the footprint of a program. Therefore, using these specifications it is pos- sible to automatically verify properties of programs. In particular, verification of confinement properties is of interest for JavaScript programs. Confinement involves preventing untrusted code from modifying or accessing security-sensitive resources. As web applications are usually composed of many programs coming from different origins executing in the same global con- text, it would be beneficial to automatically verify whether sensitive resources get tainted or leaked. In addition to automatic verification of general properties, generating specifications can support developers in verifying functional properties. As it can be taxing for developers to manually annotate code and write specifications for a large codebase, automatically generating specifica- tions allows the developer to annotate an interesting subset of procedures or adapt generated specifications to verify more expressive functional properties. Contribution We formalise the symbolic analysis used for the semi-automatic JaVerT tool in a way that closely follows the implementation of the tool (Section3). In particular, and in contrast to a previous formalisation of JSIL logic [35], our analysis is specified in an algorithmic fashion, meaning that it can be straightforwardly implemented and serve as a basis for the bi-abductive analysis we are aiming at. Building upon our symbolic analysis for JSIL, we introduce a bi-abductive symbolic analysis that generates verifiable specifications for JSIL procedures (Section4). We establish the soundness of both analyses. Furthermore, we present an algorithm, that given a JSIL program, infers the specifications of its procedures. Our analysis is a first step to a fully-fledged bi-abudctive analysis for JSIL. In particular, we do not support the inference of loop invariants and specifications of recursive procedures. Finally, we introduce the tool, JSIL Abduce, that implements the bi-abductive symbolic analysis for JSIL. The tool is able to produce procedure specifications for a JSIL program (Section5). We evaluate the tool by using JSIL Abduce to automatically generate specifications for the JSIL implementations of the JavaScript internal functions (Section6). We check that the generated specifications are correct by checking that they are satisfied by their corresponding implemen- tations, using the existing verification tool for JSIL, JSIL Verify [35]. We analyse the quality of the bi-abductive analysis by comparing the inferred specifications with the prior handwritten specifications. In the conclusion (Section7)