A Sense of Time For JavaScript and Node - Js - First-Class Timeouts As A Cure For Event Handler Poisoning
A Sense of Time For JavaScript and Node - Js - First-Class Timeouts As A Cure For Event Handler Poisoning
js:
First-Class Timeouts as a Cure for Event Handler Poisoning
1
and frameworks, but it provides a universal solution for Loop. The Event Loop may offload expensive Tasks
EHP-safety with strong security guarantees. The Time- like file I/O to the queue of a small Worker Pool, whose
out Approach makes timeouts a first-class member of an Workers execute Tasks and generate “Task Done” events
EDA framework, securing both types of Event Handlers for the Event Loop when they finish [60]. We refer to the
with a universal timeout mechanism. Event Loop and the Workers as Event Handlers.
Our Node.cure prototype (§7) demonstrates the Time-
out Approach in the complex Node.js framework, com-
pletely defending real applications against EHP attacks.
Node.cure spans the entire Node.js stack, modifying
the Node.js JavaScript engine (V8, C++), core modules
(JavaScript and C++), and the EDA mechanism (libuv,
C), and can secure real applications with low overhead
(§8). We feel our work is timely, as Staicu and Pradel
recently reported that hundreds of popular websites are
vulnerable to one type of EHP attack with minimal at-
tacker effort [94]; Node.cure defeats this and all other
EHP attacks.
Figure 1: This is the AMPED Event-Driven Architecture. Incoming
In summary: events from clients A and B are stored in the event queue, and the as-
1. We formally define Event Handler Poisoning (EHP) sociated Callbacks (CBs) will be executed sequentially by the Event
(§3), a DoS attack against the EDA. We systemati- Loop. We will discuss B’s EHP attack (CBB1 ), which has poisoned the
cally demonstrate that EHP attacks are common in the Event Loop, in §3.3.
largest EDA community, the Node.js ecosystem (§4).
2. We describe a general antidote for Event Handler Because the Event Handlers are shared by all clients,
Poisoning attacks: first-class timeouts. We demon- the EDA has a particular development paradigm. Each
strate effectiveness with our Node.cure prototype for Callback and Task is guaranteed atomicity: once sched-
Node.js in §7. We evaluate the security guarantees of uled, it runs to completion. Atomicity calls for coopera-
timeouts (strong, §6) and their costs (small, §8). tive multitasking [91], and developers partition the gen-
3. Our findings have been corroborated by the Node.js eration of responses into multiple stages. The effect of
community. Our guide on EHP-safe techniques is on this partitioning is to regularly yield to other requests by
nodejs.org, and our PRs documenting and improving deferring work until the next stage [52]. This partition-
unsafe Node.js APIs have been merged (§9). ing results in a Lifeline [39], a DAG describing the parti-
tioned steps needed to complete an operation. A Lifeline
2 Background can be seen by following the arrows in Figure 1.
In this section we review the EDA (§2.1), explain our 2.2 Node.js among other EDA frameworks
choice of EDA framework for study (§2.2), and introduce Examples of EDA frameworks include Node.js
directly related work (sections 2.3 and 2.4). (JavaScript) [13], libuv (C/C++) [9], Vert.x (Java) [26],
2.1 Overview of the EDA Twisted (Python1 ) [25], and Microsoft’s P# [56].
These frameworks have been used to build a wide
There are two paradigms for web servers, distinguished variety of industry and open-source services (e.g.
by the ratio of clients to resources, which corresponds [6, 82, 66, 77, 30, 29, 7, 3]).
to an isolation-performance tradeoff. The One Thread Most prominent among these frameworks is Node.js, a
Per Client Architecture (OTPCA) dedicates resources to server-side event-driven framework for JavaScript intro-
each client, for strong isolation but higher memory and duced in 2009. The popularity of Node.js comes from its
context-switching overheads [84]. The Event-Driven Ar- promise of “full stack JavaScript” — client- and server-
chitecture (EDA) tries the opposite approach, with many side developers can speak the same language and share
clients sharing execution resources: client connections the same libraries. This vision has driven the rise of the
are multiplexed onto a single-threaded Event Loop, with JavaScript package ecosystem, npm, which with 575,000
a small Worker Pool for expensive operations. modules is the largest of any language [55]. Node.js is
All mainstream server-side EDA frameworks use the still accelerating: use doubled between 2016 and 2017,
Asymmetric Multi-Process Event-Driven (AMPED) ar- from 3.5 million developers [31] to 7 million [33].
chitecture [83]. This architecture (hereafter “the EDA”)
The Node.js codebase has three major parts [61],
is illustrated in Figure 1. In the EDA, the OS or a frame-
whose interactions complicate top-to-bottom extensions
work places events in a queue, and the Callbacks of
pending events are executed sequentially by the Event 1 In addition, Python 3.4 introduced native EDA support.
2
like Node.cure. An application’s JavaScript code is exe- ity. The attacker knows how to exploit this vulnerability:
cuted using Google’s V8 JavaScript engine [63], its pro- they know the victim feeds user input to a Vulnerable
grammability is supported by Node.js core JavaScript API, and they know evil input that will cause the Vulner-
modules with C++ bindings for system calls, and the able API to block the Event Handler executing it. Lastly,
event-driven architecture is implemented in C using once identified, the victim will blacklist the attacker.
libuv [9].
3.2 A formal definition of an EHP attack
2.3 Algorithmic complexity attacks
Total/synchronous complexity and time. Before we
Our work is inspired by Algorithmic Complexity (AC)
can define EHP attacks, we must introduce a few def-
attacks ([74, 50]), a form of Denial of Service attack. In
initions. First, recall the standard EDA formulation il-
an AC attack, a malicious client crafts input that trig-
lustrated in Figure 1. Each client request is handled by
gers the worst-case complexity of the victim server’s
a Lifeline [39] partitioned into one or more Callbacks
algorithms, causing execution resources to be wasted.
and Tasks. A Lifeline is a DAG whose vertices are Call-
Well-known examples of AC attacks include attacks on
backs or Tasks and whose edges are events or Task sub-
hash tables [50] as well as Regular expression Denial of
missions.
Service (ReDoS) attacks, which exploit the worst-case
We define the total complexity of a Lifeline as the cu-
exponential-time behavior typical of regular expression
mulative complexity of all of its vertices as a function
(regexp) engines [49].
of their cumulative input. The synchronous complexity
As will be made clear in §3, EHP attacks are not sim-
of a Lifeline is the greatest individual complexity among
ply the application of AC attacks to the EDA. The first
its vertices. A Lifeline’s total time and synchronous time
distinction is a matter of perspective: where AC attacks
are defined analogously. Since the EDA relies on cooper-
focus on the complexity of the algorithms the service em-
ative multitasking, a Lifeline’s synchronous complexity
ploys, EHP attacks target the software architecture used
and synchronous time provide theoretical and practical
by the service, and are only concerned with time. The
bounds on how vulnerable it is. Note that a Lifeline with
second distinction is one of definition: AC attacks rely
large total time is not vulnerable so long as each vertex
on CPU-bound activities to achieve DoS, while EHP at-
(Callback/Task) has a small synchronous time; only syn-
tacks may use either CPU-bound or I/O-bound activities
chronous time matters for EHP.
to poison an Event Handler.
EHP attacks. An EHP attack exploits an EDA-based
2.4 Preliminary work on EHP attacks service with an incorrect implementation of cooperative
Davis et al.’s workshop paper [51] was the first to sketch multitasking. Here is how it works. The attacker iden-
EHP attacks. Their description was superficial, lacking tifies an exploitable Lifeline, one with large worst-case
a threat model or a formal description. Their (unimple- synchronous complexity, and poisons the corresponding
mented) solution was the “C-WCET Principle”, which large-complexity Callback or Task with evil input. This
would incur significant refactoring costs at the language, evil input causes the Event Handler executing it to block,
framework, and application levels. starving pending events or Tasks.
Our work offers a formal treatment of the EHP prob- An EHP attack can be carried out against either the
lem (§3), and introduces criteria for EHP-safety (§5) that Event Loop or the Workers in the Worker Pool. A poi-
explain why the C-WCET Principle is both ad hoc and soned Event Loop brings the server to a halt, while for
unsuited to dealing with I/O-based EHP attacks (§6). We each poisoned Worker the responsiveness of the Worker
then propose and prototype the Timeout Approach in Pool degrades. Thus, an attacker’s aim is to poison either
our Node.cure extension of Node.js (sections 7 and 8), the Event Loop or enough of the Worker Pool to harm the
and engage with the Node.js developer community to in- throughput of the server. Remember, the Worker Pool is
crease awareness of EHP attacks (§9). small enough that poisoning it will not attract the atten-
tion of network-level defenses.
3 Event Handler Poisoning Attacks Trends in software development [89] have made EHP
In this section we provide our threat model (§3.1), for- attacks relatively easy both to find and to launch. When
mally define Event Handler Poisoning (EHP) attacks commercial applications embrace open-source software,
(§3.2), and present an attack taxonomy (§3.5). To illus- including open-source package ecosystems, vulnerabili-
trate the problem, we demonstrate minimal EHP attacks ties in these (open-source) libraries may become vulner-
using ReDoS and “ReadDoS” (§3.3). abilities in the application. In §4.2 we show that many
npm modules have exploitable EHP vulnerabilities, and
3.1 Threat model that hundreds of real Node.js-based websites have been
We assume the following. The victim is an EDA-based affected. Even worse, these example EHP attacks are
server, e.g. a Node.js server, with an EHP vulnerabil- asymmetric, requiring a few small evil inputs from an
3
1 def serveFile ( name ) :
2 if name . match (/(\/.+) + $ /) : # ReDoS
3 data = await readFile ( name ) # ReadDoS
4 client . write ( data )
3.4 Aren’t EHP attacks possible in the OTPCA? 4 EHP Attacks In the Wild
EHP attacks are only possible when clients share exe- With a definition of EHP attacks in hand, we now assess
cution resources; they are not possible when clients are the awareness and incidence of EHP vulnerabilities in the
isolated as in the OTPCA. In the EDA, all clients share Node.js ecosystem. We found that the Node.js documen-
one Event Loop and a small Worker Pool. For exam- tation does not carefully outline the need for cooperative
ple, Node.js has a maximum of 128 Workers [17]. By multitasking (§4.1), which might contribute to the fact
2 In addition to files exposed on network file systems,
that 26% of known npm module vulnerabilities can be
/dev/random is a good example of a Slow File: “[r]eads from used for EHP attacks (§4.2); indeed, some already have
/dev/random may block” [34]. been [94].
4
Event Loop (§7.2) Worker Pool (§7.1)
Vuln. APIs
CPU-bound I/O-bound CPU-bound I/O-bound
Language Regexp, JSON N/A N/A N/A
Framework Crypto, zlib FS Crypto, zlib FS, DNS
Application while(1) DB query Regexp [12] DB query
5
The fundamental cause of EHP vulnerabilities should Vulnerable API is always called with a safe input. The
be clear: EHP vulnerabilities stem from Vulnerable APIs Sanitary Approach is developer-unfriendly, because it re-
that fail to honor cooperative multitasking. As catego- quires developers to identify evil input for the APIs they
rized in Table 1, Vulnerable APIs can poison the Event call. And when Vulnerable APIs like regexps are used to
Loop or the Worker Pool, they can be CPU-bound or filter input, quis custodiet ipsos custodes?
I/O-bound, and they occur at any level of the application
stack: language (vulnerable constructs), framework (vul- 6.3 Refactor Vulnerable APIs
nerable core modules), or application (vulnerable code in A more promising path to EHP-safety is to refactor Vul-
the application or libraries). nerable APIs into safe ones, as proposed by Davis et
To be EHP-safe, an application must use APIs whose al. [51]. Since the goal of EHP-safety is to bound the syn-
synchronous time (§3.2) is (small and) bounded. If an ap- chronous time of a Lifeline, a developer could restrict the
plication cannot bound the synchronous time of its APIs, complexity of each of its Callbacks and Tasks, perhaps to
it is vulnerable to EHP attack; conversely, if an applica- Constant Worst-Case Execution Time (C-WCET). This
tion can bound the synchronous time of its APIs, then it would bound the synchronous complexity of the Life-
is EHP-safe. This application-level guarantee must span line. If all Vulnerable APIs were replaced with APIs fol-
the application’s full stack: the language constructs it lowing the C-WCET Principle, the application would be
uses, the framework APIs it invokes, and the application EHP-safe. The C-WCET Principle is the logical extreme
code itself. of cooperative multitasking, extending input sanitization
In §6, we outline several approaches to EHP-safety. To from the realm of data into the realm of the algorithms
choose between them, we suggest three criteria: used to process it.
1. General. A developer must be able to use existing Evaluating the C-WCET Principle. The C-WCET
APIs or slight modifications thereof. This ensures that Principle has two benefits. First, by bounding the syn-
applications are general, that they can solve meaning- chronous complexity of all Callbacks and Tasks, there
ful problems. would be no such thing as evil input. Every client re-
2. Developer-friendly. A developer should not need ex- quest could be handled. Second, the C-WCET Princi-
pertise in topics outside of their application domain. ple can be applied largely without changing the language
3. Composable. If a developer uses only EHP-safe APIs, specification. For example, as has previously been pro-
they should be unable to create a Vulnerable API. posed [48], a non-exponential-time regexp engine could
In a composably EHP-safe system, an API contain- be used in place of Node.js’s exponential-time Irregexp
ing while(1); would not be Vulnerable, because it engine [47], and most applications would be none the
is composed only of non-Vulnerable language con- wiser.
structs. In contrast, without composability a sys- The C-WCET Principle meets the generality criterion;
tem has only ad hoc EHP safety, because in addi- every API can be partitioned towards C-WCET. It is also
tion to making language- and framework-level APIs somewhat developer-friendly: language- and framework-
non-Vulnerable, all application-level APIs composed level APIs can be C-WCET partitioned by framework
of them must also be assessed. developers, leaving developers responsible for C-WCET
partitioning their own APIs. One difficulty, though, is
6 Antidotes for Event Handler Poisoning that application developers rely heavily on third-party
npm modules that might not be C-WCET-partitioned.
Here we discuss four schemes by which to guarantee
Critically, like the Blacklist and Sanitary Approaches,
EHP-safety: removing Vulnerable APIs (§6.1), only call-
the C-WCET Principle is not composable. Since Vulner-
ing Vulnerable APIs with safe input (§6.2), refactoring
able APIs can always be composed from non-Vulnerable
Vulnerable APIs into safe ones (§6.3), and bounding a
APIs3 , developers would need to take responsibility for
Callback or Task’s synchronous time at runtime (§6.4).
applying and maintaining the C-WCET Principle at the
We evaluate these schemes using the criteria from §5.
application level.
6.1 Remove calls to Vulnerable APIs It is worth noting that while the C-WCET Principle
To become EHP-safe, an application might eliminate applies readily to CPU-bound algorithms, it is unclear
calls to Vulnerable APIs. Obviously, this Blacklist Ap- how to achieve C-WCET Partitioning for I/O. Computa-
proach fails the generality criterion. tion can be partitioned to the instruction granularity, but
the granularity of I/O is poorly defined. For example, the
6.2 Sanitize input to Vulnerable APIs C-WCET Principle would have no trouble with ReDoS,
Many Vulnerable APIs are only problematic if they are 3 As noted in §5, an API consisting of a while(1); loop is Vulner-
called with unsafe input. Another approach to EHP- able in the Blacklist, Sanitary, and C-WCET Approaches, even though
safety, then, is the Sanitary Approach: ensure that every it only calls the constant-time “language APIs” while(1) and ;.
6
but cannot cleanly combat ReadDoS. .NET framework has used timeouts to combat ReDoS
since 2012 [20]. Unfortunately, such ad hoc timeouts
6.4 Dynamically bound the running time will always be non-composable. The second approach
The goal of the C-WCET Principle was to bound a Life- is on a per-thread basis: OSes commonly use a heart-
line’s synchronous complexity as a way to bound its syn- beat mechanism to detect and restart unresponsive ap-
chronous time, and would require refactoring every Vul- plications, and in the OTPCA a client thread can easily
nerable API. But instead of statically bounding an API’s be killed and replaced if it exceeds a timeout. But the
synchronous complexity, what if we could dynamically same approach fails in the EDA. Detecting and restart-
bound its synchronous time? Then the worst-case com- ing a blocked Event Loop will break all existing client
plexity of each Callback and Task would become irrel- connections, achieving the very DoS we seek to defeat.
evant, because they would be unable to take more than Remember the double-edged sword of the EDA: scala-
the quantum provided by the runtime. In this Timeout bility at the cost of client isolation. Because clients are
Approach, the runtime detects and aborts long-running not isolated on separate execution resources, our Time-
Callbacks and Tasks by emitting a TimeoutError, thrown out Approach makes timeouts a first-class member of
from Callbacks and returned from Tasks. JavaScript and Node.js, non-destructively guaranteeing
The Timeout Approach says that in the EDA, pure co- that no Event Handler can block on an event or Task.
operative multitasking is unsafe. Just as safe general- Another objection to the Timeout Approach is that
purpose languages offer null pointer exceptions and “someone must select a timeout,” and there is some evi-
buffer overflow exceptions, so a safe EDA framework dence that little thought has been given to the choice of
must offer timeout exceptions, and developers must be timeouts [85]. For the purpose of avoiding EHP attacks
prepared to deal with them. Developers should not have under our threat model, however, this does not pose a se-
to explicitly wrap sensitive code in timers or offload it rious problem. Remember that a typical web server han-
to separate threads or processes; in the EDA, timeouts dles hundreds or thousands of clients per second (Fig-
should be provided by the framework just like any other ure 3). If so, simple arithmetic tells us that in a Node.js
security-relevant exception. server, individual Callbacks and Tasks must be taking no
The Timeout Approach provides EHP-safety. Like the longer than milliseconds to complete. Thus, a univer-
C-WCET Principle, the Timeout Approach is general. It sal Callback-Task timeout on the order of 1 second will
is more developer-friendly because it only requires de- not discomfit normal Callbacks and Tasks, will certainly
velopers to handle TimeoutErrors in their own APIs. ensure that an EHP attack is detected and defeated expe-
And where the C-WCET Principle was ad hoc, the Time- diently, and might briefly annoy existing clients but not
out Approach is composable. If the EDA runtime had a significantly undermine their experience. It then falls to
sense of time, then a long-running Callback/Task could the application to blacklist the attacker.
be interrupted no matter where it was, whether in the lan- The last objection is “it’s trivial!” We report, however,
guage, the framework, or the application. that though the Timeout Approach is conceptually sim-
Although the Timeout Approach fulfills all of the ple, realizing it in a complex real-world framework like
EHP-safety criteria, like C-WCET Partitioning it re- Node.js is difficult. The challenges that face a sound im-
quires application-level refactoring. Because the pro- plementation are:
posed TimeoutErrors emitted by the runtime are not cur-
1. Enforcing timeouts on both Callbacks and Tasks.
rently part of the language and framework specification,
2. Enforcing timeouts in both the language (V8) and the
existing applications would need to be ported. We do not
framework (Node.js core modules and libuv).
anticipate this to be a heavy burden for well-written ap-
3. Ensuring that timeouts are low-overhead.
plications, whose Callbacks should already be exception-
aware to catch errors like null pointers (ReferenceError)
and buffer overflows (RangeError), and which should 7 First-Class Timeouts in Node.cure
test the result of Tasks for errors.
Our Node.cure prototype implements the Timeout Ap-
Though the C-WCET Principle and the Timeout Ap-
proach for Node.js by bounding the synchronous time of
proach both meet the generality criterion, the Timeout
every Callback and Task. To do so, Node.cure makes
Approach is more developer-friendly, and is the only
timeouts a first-class member of Node.js, extending the
EDA-centric solution we analyzed that is composable4 .
JavaScript specification by introducing a TimeoutError
Objections. One objection to the Timeout Approach
to abort long-running Callbacks and Tasks.
is that “timeouts are hardly novel.” We disagree. To
At a high level, here is the timeout behavior
the best of our knowledge, existing timeouts take one
Node.cure enforces. A long-running Callback poisons
of two approaches. The first is on a per-API basis: the
the Event Loop; in Node.cure these Callbacks throw
4 We discuss alternative approaches to achieve EHP-safety in §9. a TimeoutError whether they are in JavaScript or in a
7
Callback Description
void work Perform Task.
int timed out* When Task has timed out. Can request extension.
void done When Task is done. Special error code for timeout.
void killed* When a timed out Task’s thread has been killed.
8
read and write, we introduced a private buffer for work earlier than after the current JavaScript instruction fin-
and added copyin/copyout steps. In addition, we used ishes. High priority interrupts take effect immediately,
pthread setcancelstate to ensure that Workers will not interrupting long-running JavaScript instructions. Time-
be killed while in a non-cancelable libc API [5]. DNS outs require the use of a high priority interrupt because
is read-only so there is no risk of the Dangling Worker they must be able to interrupt long-running individual
modifying external state. In the file system, write mod- JavaScript instructions like str.match(regexp) (possi-
ifies external state, but we avoid any Dangling Worker ble ReDoS).
state pollution via blacklisting. Our blacklisting-based To support a TimeoutError, we modified V8 as fol-
Slow Resource policy is discussed in more detail in §7.4. lows: (1) We added the definition of a TimeoutError
At the top of the Node.js stack, when the Event Loop into the Error class hierarchy; (2) We added a
sees that a Task timed out, it invokes the application’s TimeoutInterrupt into the list of high-priority in-
Callback with a TimeoutError. terrupts; and (3) We added a V8 API to raise a
TimeoutInterrupt. The TimeoutWatchdog calls this
7.2 Timeouts for Callbacks
API, which interrupts the current JavaScript stack by
Node.cure defends against EHP attacks that target the throwing a TimeoutError.
Event Loop by bounding the synchronous time of Call- The only JavaScript instructions that V8 instruments
backs. To make Callbacks timeout-aware, we introduce to be interruptible are regexp matching and JSON
a TimeoutWatchdog that monitors the start and end of parsing; these are the language-level Vulnerable APIs.
each Callback and ensures that no Callback exceeds the Other JavaScript instructions are viewed as effectively
timeout threshold. We time out JavaScript instructions constant-time, so these interrupts are evaluated e.g. at
using V8’s interrupt mechanism (§7.2.1), and we mod- the end of basic blocks. We agreed with the V8 devel-
ify Node.js’s C++ bindings to ensure that Callbacks that opers in this5 , and did not attempt to instrument other
enter these bindings will also be timed out (§7.2.2). JavaScript instructions to poll for pending interrupts.
7.2.1 Timeouts for JavaScript 7.2.2 Timeouts for the Node.js C++ bindings
9
uv queue work prio (Figure 5). This Executor follows accesses6 , with the happy side effect of solving the Dan-
the same Manager-Worker-Hangman paradigm as the gling Worker problem for write. This policy is appropri-
Executors in Node.cure’s Worker Pool. To make these ate for the file system, where access times are not likely
Vulnerable synchronous APIs timeout-aware, we offload to change7 . For DNS queries, timeouts are likely due to a
them to the Priority Executor using the existing asyn- network hiccup, and a temporary blacklist might be more
chronous implementation of the API, and had the Event appropriate.
Loop await the result. Because these synchronous APIs
are performed on the Event Loop as part of a Callback, 7.5 Prototype details
we propagate the Callback’s remaining time to this Ex- Node.cure is built on top of Node.js LTS v8.8.18 , a re-
ecutor’s Manager to ensure that the TimeoutWatchdog’s cent long-term support version of Node.js. Our proto-
timer is honored. type is for Linux, and added 4,000 lines of C, C++,
and JavaScript code across 50 files spanning V8, libuv,
7.3 Timeouts for application-level Vulnerable APIs the Node.js C++ bindings, and the Node.js JavaScript li-
Let us revisit Node.cure’s composability guarantee. As braries.
described above, Node.cure makes Tasks (§7.1) and Node.cure is a complete and correct implementation
Callbacks (§7.2) timeout-aware to defeat EHP attacks of the Timeout Approach. It passes the core Node.js test
against language and framework APIs. The Timeout Ap- suite, with a handful of failures due to bad interactions
proach is composable, so an application composed of with experimental or deprecated features. In addition,
calls to these APIs will be EHP-safe. several cases fail when they invoke rarely-used file sys-
However, applications can still escape the reach of the tem APIs we did not make timeout-aware. Real applica-
Timeout Approach by defining their own C++ bindings. tions run on Node.cure without difficulty (Table 3).
These bindings would need to be made timeout-aware, In Node.cure, timeouts for Callbacks and Tasks are
following the example we set while making Node.js’s controlled by environment variables. Our implementa-
Vulnerable C++ bindings timeout-aware (file system, tion would readily accommodate a fine-grained assign-
DNS, encryption, and compression). Without refactor- ment of timeouts for individual Callbacks and Tasks.
ing, applications with their own C++ bindings may not be
EHP-safe. In our evaluation we found that application- 8 Evaluating Node.cure
defined C++ bindings are rare (§8.3).
We evaluated Node.cure in terms of its effectiveness
7.4 Exploring policies for slow resources (§8.1), costs (§8.2), and security guarantees (§8.3). In
summary: with a lazy TimeoutWatchdog, Node.cure de-
Our Node.cure runtime detects and aborts long-running feats all known EHP attacks with low overhead on the
Callbacks and Tasks executing on Node.js’s Event Han- “good path”, estimated at 1.3x using micro-benchmarks
dlers. For unique evil input this is the best we can do, as and manifesting at 1.0x-1.24x using real applications.
accurately predicting whether a not-yet-seen input will Node.cure guarantees EHP-safety to all Node.js appli-
time out is difficult. If an attacker might re-use the same cations that do not define their own C++ bindings, a rare
evil input multiple times, however, we can track whether practice.
or not an input led to a timeout and short-circuit subse- All measurements provided in this section were ob-
quent requests that use this input with an early timeout. tained on an otherwise-idle desktop running Ubuntu
While evil input memoization could in principle be ap- 16.04.1 (Linux 4.8.0-56-generic), 16GB RAM, Intel i7
plied to any API, the size of the input space to track is a @3.60GHz, 4 physical cores with 2 threads per core.
limiting factor. The evil inputs that trigger CPU-bound For a baseline we used Node.js LTS v8.8.1 from which
EHP attacks like ReDoS exploit properties of the vulner- Node.cure was derived, compiled with the same flags.
able algorithm and are thus usually not unique. In con- We used a default Worker Pool (4 Workers).
trast, the evil inputs that trigger I/O-bound EHP attacks
like ReadDoS must name a particularly slow resource, 8.1 Effectiveness
presenting an opportunity to short-circuit requests on this To evaluate the effectiveness of Node.cure, we devel-
slow resource. oped an EHP test suite that makes EHP attacks of all
In Node.cure we implemented a slow resource man- types shown in Table 1. Our suite is comprehensive and
agement policy for libuv’s file system APIs, targeting conducts EHP attacks using every Vulnerable API we
those that reference a single resource (e.g. open, read,
6 Toavoid fd leaks, we do not eagerly abort close.
write). When one of the APIs we manage times out, we 7 Of course, if the slow resource is in a networked file system like
mark the file descriptor and the associated inode num- NFS or GPFS, slowness might be due to a network hiccup, and incorpo-
ber as slow. We took the simple approach of perma- rating temporary device-level blacklisting might be more appropriate.
nently blacklisting these aliases by aborting subsequent 8 Node.js v8.8.1 commit dc6bbb44da on Oct. 25, 2017.
10
identified, including the language level (regexp, JSON), the lazy overhead drops to 1.3x and the precise overhead
framework level (all Vulnerable APIs from the file sys- drops to 2.7x; at 10,000 empty loop iterations, the lazy
tem, DNS, cryptography, and compression modules), and precise overheads are 1.01x and 1.15x, respectively.
and application level (infinite loops, long string opera- Worker buffering. Our timeout-aware Worker Pool re-
tions, array sorting, etc.). This test suite includes each quires buffering data to accommodate Dangling Work-
type of real EHP attack from our study of EHP vulner- ers, affecting DNS queries and file system I/O. While
abilities in npm modules (§4.2). Node.cure defeats all this overhead will vary from API to API, our micro-
92 EHP attacks in this suite: each synchronous Vulnera- benchmark indicated a 1.3x overhead using read and
ble API throws a TimeoutError, and each asynchronous write calls with a 64KB buffer.
Vulnerable API returns a TimeoutError. Overhead: Macro-benchmarks. Our micro-
To finish our suite, we ported a vulnerable npm mod- benchmarks suggested that the overhead introduced by
ule to Node.cure. We selected the node-oniguruma [12] Node.cure may vary widely depending on what an ap-
module, which offers asynchronous regexp APIs. Since plication is doing. Applications that make little use of
the Oniguruma regexp engine is vulnerable to ReDoS, the Worker Pool will only pay the overhead of the ad-
its APIs are Vulnerable. However, they evaluate the reg- ditional V8 interrupt (minimal) and the TimeoutWatch-
exps in a Task rather than in a Callback, and so poi- dog’s async hooks, whose cost is strongly dependent
son a Worker rather than the Event Loop. We made on the size of the Callbacks. Applications that use the
node-oniguruma timeout-aware by using our modified Worker Pool will also pay the overhead of Worker buffer-
Worker Pool uv queue work API (Table 2). Node.cure ing (variable, perhaps 1.3x).
times out ReDoS attacks against this module’s Vulnera- We chose macro-benchmarks using a GitHub pot-
ble APIs. pourri technique: we searched GitHub for “lan-
guage:JavaScript”, sorted by “Most starred”, and iden-
8.2 Costs tified server-side projects from the first 50 results. To
The Timeout Approach introduces runtime overheads, add additional complete servers, we also included Lok-
which we evaluated using micro-benchmarks and macro- iJS [10], a popular Node.js-based key-value store, and
benchmarks. It may also require some refactoring, and a IBM’s Acme-Air airline simulation [2].
choice of timeout. Table 3 lists the macro-benchmarks we used and the
Overhead: Micro-benchmarks. Whether or not they performance overhead for each type of TimeoutWatch-
time out, Node.cure introduces several sources of over- dog. These results show that Node.cure introduces min-
heads to monitor Callbacks and Tasks. We evaluated the imal overhead on real server applications, and they con-
following overheads using micro-benchmarks: firm the value of a lazy TimeoutWatchdog. Matching our
1. Every time V8 checks for interrupts, it now tests for a micro-benchmark assessment of the TimeoutWatchdog’s
pending timeout as well. async-hooks overhead, the overhead from Node.cure in-
2. Both the lazy and precise versions of the Timeout- creased as the complexity of the Callbacks used in the
Watchdog instrument every asynchronous Callback macro-benchmarks decreased — the middleware bench-
using async-hooks, with relative overhead dependent marks sometimes used empty Callbacks to handle client
on the complexity of the Callback. requests. In non-empty Callbacks like those of the real
3. To ensure memory safety for Dangling Workers, servers, this overhead is amortized.
Workers operate on buffered data that must be al- Refactoring. Node.cure adds a TimeoutError to the
located when the Task is submitted. For example, JavaScript and Node.js specifications. See §9.
Workers must copy the I/O buffers supplied to read Choice of timeout. See §6.4 and §9.
and write twice.
New V8 interrupt. We found that the overhead of our 8.3 Security Guarantees
V8 Timeout interrupt was negligible, simply a test for We discussed the general security guarantees of the
one more interrupt in V8’s interrupt infrastructure. Timeout Approach in §6.4. Here we discuss the precise
TimeoutWatchdog’s async hooks. We measured the security guarantees of our Node.cure prototype. As de-
additional cost of invoking a Callback due to Timeout- scribed in §7, we gave a sense of time to JavaScript (in-
Watchdog’s async hooks. A lazy TimeoutWatchdog in- cluding interrupting long-running regexp and JSON op-
creases the cost of invoking a Callback by 2.4x, and a erations) as well as to framework APIs identified by the
precise TimeoutWatchdog increases the cost by 7.9x. Of Node.js developers as long-running (file system, DNS,
course, this overhead is most noticeable in Callbacks that cryptography, and compression).
are empty. As the number of instructions in a Callback Because the Timeout Approach is composable,
increases, the cost of the hooks amortizes. For exam- application-level APIs composed of these timeout-aware
ple, if the Callback executes 500 empty loop iterations, language and framework APIs are also timeout-aware.
11
Benchmark Description Overheads Principle11 . First, we submitted a PR with a guide
LokiJS [10] Server, Key-value store 1.00, 1.00 to building EHP-safe EDA-based applications. It was
Node Acme-Air [2] Server, Airline simulation 1.02, 1.03
webtorrent [27] Server, P2P torrenting 1.02, 1.02
merged and can be found on nodejs.org, where new
ws [28] Utility, websockets 1.00, 1.00*
Node.js developers go to learn best practices for Node.js
Three.js [24] Utility, graphics library 1.08, 1.09 development. We believe that it will give developers in-
Express [4] Middleware 1.06, 1.24 sights into secure Node.js programming practices.
Sails [22] Middleware 1.14, 1.23* Second, we studied the Node.js implementation
Restify [21] Middleware 1.14, 1.63* and identified several unnecessarily Vulnerable APIs
Koa [8] Middleware 1.24, 1.60
in Node.js (fs.readFile, crypto.randomFill, and
crypto.randomBytes, all of which submit a single un-
Table 3: Results of our macro-benchmark evaluation of Node.cure’s partitioned Task). Our PRs warning developers about
overhead. Where available, we used the benchmarks defined by the the risks of EHP attacks using these APIs have been
project itself. Otherwise, we ran its test suite. Overheads are reported merged. We also submitted a trial pull request repair-
as “lazy, precise”, and are the ratio of Node.cure’s performance to that
of the baseline Node.js, averaged over several steady-state runs. We ing the simplest of these, by partitioning fs.readFile. It
report the average overhead because we observed no more than 3% was been merged after a multi-month discussion on the
standard deviation in all but LokiJS, which averaged 8% standard de- performance-security tradeoff involved.
viation across our samples of its sub-benchmarks. *: Median of sub-
What might timeout-aware programs look like? As
benchmark overheads.
discussed in §7, applying the Timeout Approach while
preserving the EDA changes the language and frame-
However, Node.js also permits applications to add their work specifications. In particular, all synchronous APIs
own C++ bindings, and these will not be timeout-aware may now throw a TimeoutError, and all asynchronous
without refactoring. APIs may now be fulfilled with a TimeoutError. These
To evaluate the extent of this limitation, we measured changes have two implications for application develop-
how frequently developers use C++ bindings. To this ers: Timeout-aware applications must be able to toler-
end, we examined a sample of npm modules. We npm ate arbitrary TimeoutErrors (just like any other excep-
install’d 125,173 modules (about 20% of the ecosys- tion), and developers should pursue low-variance Call-
tem) using node v8.9.1 (npm v5.5.1), resulting in 23,070 backs and Tasks (to permit the choice of a tighter timeout
successful installations9 . Of these, 695 (3%) had C++ threshold).
bindings10 . Are there other avenues toward EHP-safety? In
From this we conclude that the use of user-defined §6 we discussed several EHP-safe designs. There are of
C++ bindings is uncommon in npm modules, unsur- course other approaches, like significantly increasing the
prising since many developers in this community come size of the Worker Pool, performing speculative concur-
from client-side JavaScript and may not have strong C++ rent execution [45], or using explicitly preemptable Call-
skills. This implies, but does not directly indicate, that backs and Tasks. However, each of these is a variation
C++ bindings are unusual in Node.js applications. We on the same theme: dedicating resources to every client,
conclude that the need to refactor C++ bindings to be i.e. the One Thread Per Client Architecture. If the server
timeout-aware would not place a significant burden on community wishes to use the EDA, which offers high
the community. As a template, we performed several responsiveness and scalability through the use of coop-
such refactorings ourselves in the Node.js framework and erative multitasking, we believe the Timeout Approach
our port of node-oniguruma. is a good path to EHP-safety.
ule’s directory tree for files with endings like “.h” and “.c[pp]”. 11 We omit references to meet the double-blind requirement.
12
DoS attacks seek to exhaust the resources critical to “Don’t block the Event Loop”, advised by many tuto-
the proper operation of a server, and various kinds of rials as well as recent books about EDA programming
exhaustion have been considered. The brunt of the lit- for Node.js [98, 44]. Wandschneider suggests worst-case
erature has focused on exhausting the CPU. Some have linear-time partitioning on the Event Loop [98], while
examined the gap between common-case and worst-case Casciaro advises developers to partition any computation
performance in algorithms and data structures, for ex- on the Event Loop, and to offload computationally ex-
ample in quicksort [74], hashing [50], and exponentially pensive tasks to the Worker Pool [44]. Our work offers a
backtracking algorithms like ReDoS [49, 90] and rule more rigorous taxonomy and evaluation of EHP attacks,
matching [92]. Other CPU-centric DoS attacks have tar- and in particular we extend the rule of “Don’t block the
geted more general programming issues, showing how to Event Loop” to the Worker Pool.
trigger infinite recursion [46] and how to trigger [93] or EHP attacks on the server side may correspond to per-
detect [42] infinite loops. But the CPU is not the only formance bugs in client-side EDA programs. Liu et al.
vulnerable resource, as shown by Olivo et al.’s work pol- studied such bugs [72], and Lin et al. proposed an au-
luting databases to increase the cost of queries [79]. We tomatic refactoring to offload expensive tasks from the
are not aware of prior research work that incurs DoS us- Event Loop to the Worker Pool [71]. This approach is
ing the file system, as do our ReadDoS attacks, though sound on a client-side system like Android, where the
we have found a handful of CVE reports to this effect12 demand for threads is limited, but is not applicable to
Our work identifies and shows how to exploit the the server-side EDA because the small Worker Pool is
most limited resource of the EDA: Event Handlers. To shared among all clients. For the server-side EDA, Lin et
launch a similar attack in the OTPCA, attackers must al.’s approach would need to be extended to incorporate
submit enough queries to overwhelm the OS’s preemp- automatic C-WCET partitioning.
tive scheduler, no mean feat. In contrast, in the EDA
As future work, we believe that research into compu-
there are only a few Event Handlers to be poisoned. Al-
tational complexity estimation ([80, 65, 86]) and mea-
though we prove our point using previously-reported at-
surement ([87, 62, 43]) might be adapted to the Node.js
tacks like ReDoS, the underlying resource we are ex-
context for EHP vulnerability detection and automatic
hausting is not the CPU but the small, fixed-size set of
refactoring using the C-WCET Principle. This may be
Event Handlers deployed in EDA-based services.
difficult because of the complexity of statically analyz-
Security in the EDA. Though researchers have stud-
ing JavaScript and the EDA ([73, 40, 64, 99, 59]).
ied security vulnerabilities in different EDA frameworks,
most prominently client-side applications, the security
properties of the EDA itself have not been investigated 11 Conclusion
in detail.
Our work is most closely related to the workshop pa- The Event-Driven Architecture (EDA) holds great
per of Davis et al. [51], discussed earlier (§2.4). Less promise for scalable web services, and it is increasingly
immediately relevant is the Node.js-specific high-level popular in the software development community. In this
survey of Ojamaa et al. [78], which mentioned the rule paper we formally defined Event Handler Poisoning at-
“Don’t block the event loop”, and Staicu and Pradel’s tacks, which exploit the the cooperative multitasking at
study on code injection vulnerabilities in npm [95], the heart of the EDA. The Node.js community has en-
which can be used for EHP attacks. DeGroef et al. [54]’s dorsed our expression of this problem, hosting our guide
proposed method to securely integrate third-party mod- at nodejs.org.
ules from npm is not effective for EHP attacks because
We proposed several defenses against EHP attacks,
Node.js lacks a sense of time.
and prototyped the most promising: first-class time-
More broadly, other security research in the EDA has
outs. Our prototype, Node.cure, defends Node.js appli-
studied client-side JavaScript/Web [70, 68, 53, 75] and
cations against all known EHP attacks. It is available on
Java/Android [58, 57, 41, 67] applications. These have
GitHub13 .
often focused on platform-specific issues like DOM issues
in web browsers [70]. Our findings can be directly applied by the EDA com-
EHP attacks. The server-side EDA practitioner com- munity, and we hope they influence the design of existing
munity is aware of the risk of DoS due to (synchronous) and future EDA frameworks. With the rise of popularity
EHP on the Event Loop. A common rule of thumb is in the EDA, EHP attacks will become an increasingly
critical DoS vector, a vector that can be defeated with
12 For Slow Files (/dev/random), see CVE-2012-1987 and CVE- first-class timeouts.
2016-6896. For a related DOS by reading Large Files, CVE-2001-
0834, CVE-2008-1353, CVE-2011-1521, and CVE-2015-5295 men-
tion DoS by ENOMEM using /dev/zero. 13 We omit the reference to meet the double-blind requirement.
13
Acknowledgments [28] ws: a node.js websocket library. https://github.com/
websockets/ws.
We thank the CCS, NDSS, S&P, and USENIX Security
[29] The Calendar and Contacts Server. https://github.com/
referees for their helpful feedback, as well as XXX for Apple/Ccs-calendarserver, 2007.
their excellent shepherding. L. Cheng, C. Coghlan, A. [30] Ubuntu One: Technical Details. https://wiki.ubuntu.
Kazerouni, S. Rahaman, J. Terner, and the Virginia Tech com/UbuntuOne/TechnicalDetails, 2012.
Systems Reading Group were helpful sounding boards [31] New node.js foundation survey reports new “full stack” in
for our ideas and manuscripts, as were M. Hicks, G. demand among enterprise developers. https://nodejs.org/
Wang, and D. Yao. J.D. Greef of Ronomon suggested en/blog/announcements/nodejs-foundation-survey/,
2016.
several of the EHP attacks listed in the discussion.
[32] 2017 User Survey Executive Summary. The Linux Foundation,
2017.
References
[33] The linux foundation: Case study: Node.js. https:
[1] ab – apache http server benchmarking tool. https://httpd. //www.linuxfoundation.org/wp-content/uploads/
apache.org/docs/2.4/programs/ab.html. 2017/06/LF_CaseStudy_NodeJS_20170613.pdf, 2017.
[2] acmeair-node. https://github.com/acmeair/ [34] Random(4). http://man7.org/linux/man-pages/man4/
acmeair-nodejs. random.4.html, 2017.
[3] Cylon.js. https://cylonjs.com/. [35] This is what node.js is used for in 2017 – sur-
[4] express. https://github.com/expressjs/express. vey results. https://blog.risingstack.com/
what-is-node-js-used-for-2017-survey/, 2017.
[5] Gnu libc – posix safety concepts. https://www.
gnu.org/software/libc/manual/html_node/ [36] How cond nast used node.js to unify brands and create cus-
POSIX-Safety-Concepts.html. tomer faith. https://www2.thelinuxfoundation.org/
node-casestudies-condenast, 2018.
[6] Ibm node-red. https://nodered.org/.
[37] A BDALKAREEM , R., N OURRY, O., W EHAIBI , S., M UJAHID ,
[7] iot-nodejs. https://github.com/ibm-watson-iot/
S., AND S HIHAB , E. Why Do Developers Use Trivial Pack-
iot-nodejs.
ages? An Empirical Case Study on npm. In Foundations of
[8] Koa. https://github.com/koajs/koa. Software Engineering (FSE) (2017).
[9] libuv. https://github.com/libuv/libuv. [38] A BLIZ , M. Internet Denial of Service Attacks and Defense
[10] Lokijs. https://github.com/techfort/LokiJS. Mechanisms. Tech. rep., 2011.
[11] Mozilla developer network: Javascript. https://developer. [39] A LIMADADI , S., M ESBAH , A., AND PATTABIRAMAN , K. Un-
mozilla.org/en-US/docs/Web/JavaScript. derstanding Asynchronous Interactions in Full-Stack JavaScript.
ICSE (2016).
[12] Node-oniguruma regexp library. https://github.com/
atom/node-oniguruma. [40] A RZT, S., R ASTHOFER , S., F RITZ , C., B ODDEN , E., BAR -
TEL , A., K LEIN , J., L E T RAON , Y., O CTEAU , D., AND M C -
[13] Node.js. http://nodejs.org/.
DANIEL , P. Flowdroid: Precise context, flow, field, object-
[14] Nodejs async hooks. https://nodejs.org/api/async_ sensitive and lifecycle-aware taint analysis for android apps. In
hooks.html. PLDI (2014).
[15] Node.js developer guides. https://nodejs.org/en/docs/ [41] BARRERA , D., K AYACIK , H. G., VAN O ORSCHOT, P. C.,
guides/. AND S OMAYAJI , A. A methodology for empirical analysis of
[16] Node.js foundation members. https://foundation. permission-based security models and its application to android.
nodejs.org/about/members. In CCS (2010).
[17] Node.js thread pool documentation. http://docs.libuv. [42] B URNIM , J., JALBERT, N., S TERGIOU , C., AND S EN , K.
org/en/v1.x/threadpool.html. Looper: Lightweight detection of infinite loops at runtime. In
International Conference on Automated Software Engineering
[18] Node.js usage: Statistics for websites using node.js tech-
(ASE) (2009).
nologies. https://trends.builtwith.com/framework/
node.js. [43] B URNIM , J., J UVEKAR , S., AND S EN , K. WISE: Automated
Test Generation for Worst-Case Complexity. In International
[19] Node.js v8.9.1 documentation. https://nodejs.org/dist/
Conference on Software Engineering (ICSE) (2009).
latest-v8.x/docs/api/.
[20] Regex.matchtimeout property. https://msdn. [44] C ASCIARO , M. Node.js Design Patterns, 1 ed. 2014.
microsoft.com/en-us/library/system.text. [45] C HADHA , G., M AHLKE , S., AND NARAYANASAMY, S. Ac-
regularexpressions.regex.matchtimeout. celerating Asynchronous Programs Through Event Sneak Peek.
[21] restify. https://github.com/restify/node-restify. In International Symposium on Computer Architecture (ISCA)
(2015).
[22] sails. https://github.com/balderdashy/sails.
[46] C HANG , R., J IANG , G., I VAN ČI Ć , F., S ANKARANARAYANAN ,
[23] Snyk.io. https://snyk.io/vuln/. S., AND S HMATIKOV, V. Inputs of coma: Static detection of
[24] three.js. https://github.com/mrdoob/three.js. denial-of-service vulnerabilities. In IEEE Computer Security
Foundations Symposium (CSF) (2009).
[25] Twisted. https://twistedmatrix.com/trac/.
[26] Vert.x. http://vertx.io/. [47] C ORRY, E., H ANSEN , C. P., AND N IELSEN , L. R. H. Irregexp,
Google Chrome’s New Regexp Implementation, 2009.
[27] webtorrent. https://github.com/webtorrent/
webtorrent.
14
[48] C OX , R. Regular Expression Matching Can Be Simple And [69] K IRRAGE , J., R ATHNAYAKE , A., AND T HIELECKE , H. Static
Fast (but is slow in Java, Perl, PHP, Python, Ruby, ...), 2007. Analysis for Regular Expression Denial-of-Service Attacks.
[49] C ROSBY, S. Denial of service through regular expressions. Network and System Security 7873 (2013), 35–148.
USENIX Security work in progress report (2003). [70] L EKIES , S., S TOCK , B., AND J OHNS , M. 25 million flows
[50] C ROSBY, S. A., AND WALLACH , D. S. Denial of Service via later: Large-scale detection of dom-based xss. In CCS (2013).
Algorithmic Complexity Attacks. In USENIX Security (2003). [71] L IN , Y., R ADOI , C., AND D IG , D. Retrofitting Concurrency
[51] DAVIS , J., K ILDOW, G., AND L EE , D. The Case of the Poi- for Android Applications through Refactoring. In ACM Inter-
soned Event Handler: Weaknesses in the Node.js Event-Driven national Symposium on Foundations of Software Engineering
Architecture. In European Workshop on Systems Security (Eu- (FSE) (2014).
roSec) (2017). [72] L IU , Y., X U , C., AND C HEUNG , S.-C. Characterizing and
[52] DAVIS , J., T HEKUMPARAMPIL , A., AND L EE , D. Node.fz: detecting performance bugs for smartphone applications. In In-
Fuzzing the Server-Side Event-Driven Architecture. In Euro- ternational Conference on Software Engineering (ICSE) (2014).
pean Conference on Computer Systems (EuroSys) (2017). [73] M ADSEN , M., T IP, F., AND L HOTAK , O. Static analysis of
[53] D E G ROEF, W., D EVRIESE , D., N IKIFORAKIS , N., AND event-driven Node. js JavaScript applications. In ACM SIG-
P IESSENS , F. Flowfox: A web browser with flexible and precise PLAN International Conference on Object-Oriented Program-
information flow control. CCS. ming, Systems, Languages, and Applications (OOPSLA) (2015),
ACM.
[54] D E G ROEF, W., M ASSACCI , F., AND P IESSENS , F. Node-
Sentry: Least-privilege library integration for server-side [74] M CILROY, M. D. Killer adversary for quicksort. Software -
JavaScript. In Annual Computer Security Applications Confer- Practice and Experience 29, 4 (1999), 341–344.
ence (ACSAC) (2014). [75] N IKIFORAKIS , N., I NVERNIZZI , L., K APRAVELOS , A.,
[55] D E B ILL , E. Module counts. http://www.modulecounts. VAN ACKER , S., J OOSEN , W., K RUEGEL , C., P IESSENS , F.,
com/. AND V IGNA , G. You are what you include: Large-scale evalu-
ation of remote javascript inclusions. In CCS (2012).
[56] D ESAI , A., G UPTA , V., JACKSON , E., Q ADEER , S., R A -
JAMANI , S., AND Z UFFEREY, D. P: Safe asynchronous [76] O’D ELL , J. Exclusive: How LinkedIn used Node.js and
event-driven programming. In ACM SIGPLAN Conference on HTML5 to build a better, faster app, 2011.
Programming Language Design and Implementation (PLDI) [77] O’D ELL , J. Exclusive: How LinkedIn used Node.js and
(2013). HTML5 to build a better, faster app, 2011.
[57] E NCK , W., O CTEAU , D., M C DANIEL , P., AND C HAUDHURI , [78] O JAMAA , A., AND D UUNA , K. Assessing the security of
S. A study of android application security. In USENIX Security Node.js platform. In 7th International Conference for Internet
(2011). Technology and Secured Transactions (ICITST) (2012).
[58] E NCK , W., O NGTANG , M., AND M C DANIEL , P. Understand- [79] O LIVO , O., D ILLIG , I., AND L IN , C. Detecting and Exploiting
ing android security. IEEE Security and Privacy (2009). Second Order Denial-of-Service Vulnerabilities in Web Appli-
[59] F ENG , Y., A NAND , S., D ILLIG , I., AND A IKEN , A. cations. ACM Conference on Computer and Communications
Apposcopy: Semantics-based detection of android malware Security (CCS) (2015).
through static analysis. In FSE (2014). [80] O LIVO , O., D ILLIG , I., AND L IN , C. Static Detection of
[60] F ERG , S. Event-driven programming: introduction, tutorial, Asymptotic Performance Bugs in Collection Traversals. PLDI
history. 2006. (2015).
[61] F REES , S. C++ and Node.js Integration. 2016. [81] PADMANABHAN , S. How We Built
eBay’s First Node.js Application. https:
[62] G OLDSMITH , S. F., A IKEN , A. S., AND W ILKERSON , D. S. //www.ebayinc.com/stories/blogs/tech/
Measuring Empirical Computational Complexity. In Founda- how-we-built-ebays-first-node-js-application/,
tions of Software Engineering (FSE) (2007). 2013.
[63] G OOGLE. Chrome v8: Google’s high performance, open [82] PADMANABHAN , S. How We Built eBays First Node.js Appli-
source, javascript engine. https://developers.google. cation, 2013.
com/v8/.
[83] PAI , V. S., D RUSCHEL , P., AND Z WAENEPOEL , W. Flash: An
[64] G ORDON , M. I., K IM , D., P ERKINS , J., G ILHAMY, L., Efficient and Portable Web Server. In USENIX Annual Technical
N GUYENZ , N., , AND R INARD , M. Information flow analy- Conference (ATC) (1999).
sis of android applications in droidsafe. In NDSS (2015).
[84] PARIAG , D., B RECHT, T., H ARJI , A., B UHR , P., S HUKLA ,
[65] G ULWANI , S., M EHRA , K. K., AND C HILIMBI , T. SPEED: A., AND C HERITON , D. R. Comparing the performance of
Precise and Efficient Static Estimation of Program Computa- web server architectures. In European Conference on Computer
tional Complexity. In Principles of Programming Languages Systems (EuroSys) (2007), ACM.
(POPL) (2009).
[85] P ETER , S., BAUMANN , A., ROSCOE , T., BARHAM , P., AND
[66] H ARRELL , J. Node.js at PayPal. https:
I SAACS , R. 30 seconds is not enough! In European Conference
//www.paypal-engineering.com/2013/11/22/
on Computer Systems (EuroSys) (2008).
node-js-at-paypal/, 2013.
[86] P ETSIOS , T., Z HAO , J., K EROMYTIS , A. D., AND JANA , S.
[67] H EUSER , S., NADKARNI , A., E NCK , W., AND S ADEGHI , A.-
SlowFuzz: Automated Domain-Independent Detection of Algo-
R. Asm: A programmable interface for extending android secu-
rithmic Complexity Vulnerabilities. In Computer and Commu-
rity. In Proceedings of the 23rd USENIX Conference on Security
nications Security (CCS) (2017).
Symposium (2014), SEC’14.
[87] P USCHNER , P. P., AND KOZA , C. Calculating the Maximum
[68] J IN , X., H U , X., Y ING , K., D U , W., Y IN , H., AND P ERI ,
Execution Time of Real-Time Programs. Real-Time Systems 1,
G. N. Code injection attacks on html5-based mobile apps:
2 (1989), 159–176.
Characterization, detection and mitigation. In CCS (2014).
15
[88] R ATHNAYAKE , A., AND T HIELECKE , H. Static Analysis [95] S TAICU , C.-A., P RADEL , M., AND L IVSHITS , B. Understand-
for Regular Expression Exponential Runtime via Substructural ing and Automatically Preventing Injection Attacks on Node.js.
Logics. CoRR (2014). Tech. rep., 2016.
[89] R AYMOND , E. S. The Cathedral and the Bazaar. No. July [96] S ULLIVAN , B. Security Briefs - Regular Expression Denial of
1997. 2000. Service Attacks and Defenses. Tech. rep., 2010.
[90] ROICHMAN , A., AND W EIDMAN , A. VAC - ReDoS: Regular [97] VAN D ER M ERWE , B., W EIDEMAN , N., AND B ERGLUND , M.
Expression Denial Of Service. Open Web Application Security Turning Evil Regexes Harmless. In SAICSIT (2017).
Project (OWASP) (2009).
[98] WANDSCHNEIDER , M. Learning Node.js: A Hands-on Guide
[91] S ILBERSCHATZ , A., G ALVIN , P. B., AND G AGNE , G. Oper- to Building Web Applications in JavaScript. Pearson Education,
ating System Concepts, 9th ed. Wiley Publishing, 2012. 2013.
[92] S MITH , R., E STAN , C., AND J HA , S. Backtracking Algorith-
[99] W EI , F., ROY, S., O U , X., AND ROBBY. Amandroid: A precise
mic Complexity Attacks Against a NIDS. In ACSAC (2006),
and general inter-component data flow analysis framework for
pp. 89–98.
security vetting of android apps. In Proceedings of the 2014
[93] S ON , S., AND S HMATIKOV, V. SAFERPHP Finding Seman- ACM SIGSAC Conference on Computer and Communications
tic Vulnerabilities in PHP Applications. In Workshop on Pro- Security (2014), CCS ’14.
gramming Languages and Analysis for Security (PLAS) (2011),
[100] W ELSH , M., C ULLER , D., AND B REWER , E. SEDA : An
pp. 1–13.
Architecture for Well-Conditioned, Scalable Internet Services.
[94] S TAICU , C.-A., P RADEL , M., AND DARMSTADT, T. Freezing In Symposium on Operating Systems Principles (SOSP) (2001).
the Web: A Study of ReDoS Vulnerabilities in JavaScript-based
Web Servers.
16