Weaknesses in the Node.Js Event-Driven Architecture
Total Page:16
File Type:pdf, Size:1020Kb
The Case of the Poisoned Event Handler: Weaknesses in the Node.js Event-Driven Architecture James Davis Gregor Kildow Dongyoon Lee Virginia Tech Virginia Tech Virginia Tech Blacksburg, VA, USA Blacksburg, VA, USA Blacksburg, VA, USA [email protected] [email protected] [email protected] ABSTRACT and pending events are handled by an event thread. The Node.js has seen rapid adoption in industry and the open- event thread may offload expensive activity to a small, fixed- source community. Unfortunately, its event-driven architec- size worker pool, which generates an event to note the com- ture exposes Node.js applications to Event Handler-Poisoning pletion of each offloaded task. The worker pool is typi- denial of service attacks. Our evaluation of the state of prac- cally implemented using threads or separate processes, and tice in Node.js| combining a study of 353 publicly reported performs services like offering \asynchronous" (blocking but security vulnerabilities and a survey of 151 representative concurrent) access to the file system. This architecture is common to all mainstream general-purpose EDA frameworks npm modules | demonstrates that the community is not equipped to combat this class of attack. We recommend today, discussed further in Section 2.2. several changes to the state of practice and propose both programming language and runtime approaches to defend against Event Handler-Poisoning attacks. Keywords Node.js; Event-driven architecture; Denial of service; ReDoS 1. INTRODUCTION The Event-Driven Architecture (EDA) is coming into its own. Although EDA approaches have been discussed and implemented in the academic and professional communities Figure 1: Classic Event-Driven Architecture. In- for decades (e.g. [17, 7, 18, 13]), historically EDA has coming events are handled sequentially by the event only seen wide adoption in user interface settings like web thread. The event thread may offload tasks to the browsers. It is increasingly relevant in systems programming worker pool. today thanks to the explosion of interest in Node.js1, an event-driven server-side JavaScript framework. In applications built using EDA, there is a set of possible Server-side applications implemented using the EDA are events (e.g. \mouse click" or \incoming network traffic") for vulnerable to a unique type of denial of service attack which which the developer supplies a set of Event Handlers (also we term the Event Handler-Poisoning (EHP) attack. Key known as callbacks); these Event Handlers will be executed to the EDA is the use of a small, fixed-size set of Event when the corresponding events occur [5]. During the execu- Handlers that handle each event in turn. In the EDA design tion of such an application, events are generated by external of Figure 1, there are two classes of Event Handlers: the activity and routed to the appropriate Event Handlers. event thread, and the workers in the worker pool. If either Figure 1 illustrates the classic EDA formulation, known as class of Event Handlers (the event thread, or every worker AMPED [11]: the operating system or a framework places in the worker pool) becomes blocked, the handling of every events in a queue (e.g. through Linux's poll system call2), pending event will be delayed. While in a One Thread Per Client (OTPC) setting an 1See https://nodejs.org/en/. expensive request from a client delays only that client, in the 2Per the Linux man page, \poll...waits for one of a set of file EDA context an expensive request delays every client. Thus, Permission to make digital or hard copies of all or part of this work for personal or the EDA model resurrects an old foe: DoS vulnerabilities in classroom use is granted without fee provided that copies are not made or distributed an essentially single-threaded server. for profit or commercial advantage and that copies bear this notice and the full citation Event Handlers might block due to an expensive computa- on the first page. Copyrights for components of this work owned by others than the tion or due to I/O. In our study of the state of practice in the author(s) must be honored. Abstracting with credit is permitted. To copy otherwise, or republish, to post on servers or to redistribute to lists, requires prior specific permission Node.js community in Section 4.3, developers appear to be and/or a fee. Request permissions from [email protected]. well apprised of the risks associated with blocking I/O. How- EuroSec’17, April 23 2017, Belgrade, Serbia ever, a surprising number of developers appear to take a cav- c 2017 Copyright held by the owner/author(s). Publication rights licensed to ACM. alier approach to the possibility of blocking the event thread ISBN 978-1-4503-4935-2/17/04. $15.00 DOI: http://dx.doi.org/10.1145/3065913.3065916 descriptors to become ready to perform I/O." with computation, as shown in Section 6.2. The prevalence Framework Contributors Commits Releases of EHP vulnerabilities in many common modules suggests Node.js 1176 15666 399 the need for reform in the community's practices, and for libuv 247 3643 183 both programming language and runtime aids to facilitate EventMachine 113 1141 27 community adoption. Reactor 56 4249 42 1.1 Contributions Twisted 35 20751 38 This paper makes the following contributions: Table 1: Popularity of event-driven programming environments measured by development activity. 1. After identifying Node.js as the most popular general Data were obtained from GitHub in December 2016. EDA framework, we analyze the 353 security vulner- abilities publicized in its package ecosystem, npm. We identify and discuss the CPU-bound and I/O-bound GitHub survey are shown in Table 1, and show that Node.js EHP vulnerabilities among them. has by far the largest developer community and a significant 2. We evaluate the ease with which a Node.js developer number of commits. can avoid EHP vulnerabilities. Our assessment of de- Node.js is a server-side event-driven framework for velopment aids and our study of 151 npm modules iden- JavaScript that uses the architecture shown in Figure 1. The tify significant shortcomings in the tools, documenta- worker pool is used internally to perform asynchronous DNS tion, and modules on which a developer might rely. queries and file system I/O. In addition, user-defined code can be offloaded to the worker pool. Node.js claims 3.5 mil- 3. We discuss ways to reduce EHP vulnerabilities in the lion users [1], and its open-source package ecosystem, npm, is Node.js ecosystem through changes in the community's the largest of any programming language or framework10. practices and by various programming language and Though Node.js has seen significant use in industry (e.g. runtime defenses. LinkedIn11, PayPal12, eBay13, and IBM14), to the best of our knowledge the only academic engagement with security 2. BACKGROUND aspects of Node.js applications was Ojamaa et al.'s high-level survey [10]. We believe that more academic involvement in In this section we compare the EDA with the OTPC ar- the Node.js community will increase the security of many of chitecture. We then identify the most popular server-side the web services we use every day. EDA framework for analysis. Lastly, we discuss two types of EHP vulnerabilities in the EDA. 2.3 Event Handler-Poisoning Attacks 2.1 EDA vs. OTPC The key characteristic of the EDA is that many request There are two main architectures for scalable web servers. events are addressed by a small number of Event Handlers. The traditional approach is the OTPC architecture, of which An Event Handler-Poisoning attack exploits this design by Apache3 is the most prominent. In the OTPC style, a thread causing the Event Handlers to block indefinitely, poisoning or a process is assigned to each client, with a large maximum them. This is done through the submission of an expensive number of concurrent clients. The OTPC model isolates task, either CPU-bound or I/O-bound. clients from one another, reducing the risk of interference. We emphasize that in the EDA design of Figure 1, of- However, each additional client incurs memory and context floading tasks to a fixed-size worker pool is not a panacea switching overhead. In contrast, by multiplexing multiple for EHP vulnerabilities. Suppose an attacker identifies an client connections into a single thread and offering a small EHP vulnerability in code executed by the worker pool. A worker pool for asynchronous tasks, an EDA approach sig- pool of size k will jam after only k poisonous requests; the nificantly reduces a server's per-client resource use. But the EHP vulnerability is essentially the same whether the attack EDA model also exposes the server to instability, e.g. due is against the event thread or the worker pool. Therefore, to vulnerabilities like EHP. an attacker's aim is to submit requests that cause either the event thread or the entire worker pool to jam up, thereby 2.2 General-Purpose EDA Frameworks delaying the handling of subsequent requests. Though an EDA approach can be implemented in most It should be noted that an attack that jams the worker programming languages, the mainstream general-purpose pool can in principle be carried out against any architecture EDA frameworks for server applications are Java/Reactor4, or system with a cap on the amount of resources available C/libuv5, Python/Twisted6, Ruby/EventMachine7, and for clients, including both EDA and pool-based OTPC de- JavaScript/Node.js8. To capture the scope and variety of ac- signs. However, the connection pool in a OTPC system is tivity for each framework, we surveyed each of their GitHub9 significantly larger than the worker pool in typical EDA im- repositories using the metrics of number of commits, number plementations.