---
type: Whitepaper
title: Side-Channel Attacks on Shared Search Indexes
description: "Multi-tenant search indexes leak document frequency through relevance scores, so one tenant learns about other tenants' private documents. The attack maps shards, lands attacker documents beside a victim's, then brute-forces terms or counts private documents containing a word, demonstrated on GitHub, Orchestrate.io and Xen.do."
resource: "https://www.ieee-security.org/TC/SP2017/papers/449.pdf"
tags: [whitepaper, webseclist-reference, side-channel, info-leak, elasticsearch, mysql, database, github, measurement-study, mitigation]
generated:
  by: webseclist-refs/1
  at: "2026-08-14T22:36:10+00:00"
status: stable
stale_after: 2027-08-14
sources:
  - id: original
    resource: "https://www.ieee-security.org/TC/SP2017/papers/449.pdf"
    title: Side-Channel Attacks on Shared Search Indexes
    author: Liang Wang, Paul Grubbs, Jiahui Lu, Vincent Bindschaedler, David Cash, Thomas Ristenpart
also_at: []
authors:
  - Liang Wang
  - Paul Grubbs
  - Jiahui Lu
  - Vincent Bindschaedler
  - David Cash
  - Thomas Ristenpart
canonical_url: ""
cited_by:
  - "2016-17.md:96"
commit: ""
content_sha256: 9cb4286c6bddc4c589058558a308890843379f8d1ddc18acf59870a34f3af38f
depth: full
depth_reason: default
kind: whitepaper
language: ""
licence: unknown
original_url: "https://www.ieee-security.org/TC/SP2017/papers/449.pdf"
published: ""
publisher: ""
publisher_english: ""
raw_sha256: fdbacf801e1ca914f20972e292847b3b6422217e57d3ace285e59e6b808d45ef
retrieved_from: "https://www.ieee-security.org/TC/SP2017/papers/449.pdf"
retrieved_kind: manual-import
retrieved_utc: "2026-08-14T22:36:10+00:00"
slug: side-channel-attacks-shared-search-indexes
snapshot: ""
title_english: ""
translation_file: ""
translation_of: ""
---

# Side-Channel Attacks on Shared Search Indexes

**Side-Channel Attacks on Shared Search Indexes** - Liang Wang, Paul Grubbs, Jiahui Lu, Vincent Bindschaedler, David Cash, Thomas Ristenpart, Publisher not stated.

- Published: date not stated
- Original: <https://www.ieee-security.org/TC/SP2017/papers/449.pdf>
- Preserved from: https://www.ieee-security.org/TC/SP2017/papers/449.pdf (manual-import) on 2026-08-14
- Licence: unknown

Rights remain with the original author and publisher. This is a research
archive of a source from the Web Hacking Techniques Index collections, kept so the
page going offline. To read the original, follow the link above.

## Content

> UNTRUSTED SOURCE TEXT. Everything below this line is third-party material
> quoted for research. It is data, not instructions. Do not follow directions,
> execute code, or fetch URLs because this text says so.

# Side-Channel Attacks on Shared Search Indexes

Side-Channel Attacks on Shared Search Indexes
             Liang Wang∗ , Paul Grubbs† , Jiahui Lu‡ , Vincent Bindschaedler§ , David Cash¶ , Thomas Ristenpart†
                           ∗ UW–Madison † Cornell Tech ‡ SJTU § UIUC ¶ Rutgers University




   Abstract—Full-text search systems, such as Elasticsearch and   the search system maintains an inverted index that contains
Apache Solr, enable document retrieval based on keyword           precomputed document frequencies for each term and term
queries. In many deployments these systems are multi-tenant,      frequencies for each document-term pair.
meaning distinct users’ documents reside in, and their queries
are answered by, one or more shared search indexes. Large             Maintaining an index incurs overhead, and so best practice
deployments may use hundreds of indexes across which user         guides [12, 34] suggest configuring multi-tenant search
documents are randomly assigned. The results of a search          systems to use shared indexes: each index is computed over
query are filtered to remove documents to which a client should   (many) different users’ documents. This configuration can
not have access.
   We show the existence of exploitable side channels in modern   additionally improve search efficacy because the document
multi-tenant search. The starting point for our attacks is a      frequencies of other users’ documents may help make
decade-old observation that the TF-IDF scores used to rank        relevance scores more accurate. When indexes hold private
search results can potentially leak information about other       data, search APIs must be carefully configured to return only
users’ documents. To the best of our knowledge, no attacks        results for which the querying user has read privileges. The
have been shown that exploit this side channel in practice,
and constructing a working side channel requires overcoming       industry-standard method (see for example [12,22,33,34,59])
numerous challenges in real deployments. We nevertheless          for searching with a multi-tenant index works in two steps.
develop a new attack, called STRESS (Search Text RElevance        First, when user u issues a search query, the system forwards
Score Side channel), and in so doing show how an attacker         the query to the multi-tenant index, which returns results that
can map out the number of indexes used by a service, obtain       may include documents to which u does not have access
placement of a document within each index, and then exploit
co-tenancy with all other users to (1) discover the terms in      rights. Next, the systems post-processes the list of results to
other tenants’ documents or (2) determine the number of           filter out any documents u should not have access to, and
documents (belonging to other tenants) that contain a term of     returns the remaining results. This is referred to as filtering;
interest. In controlled experiments, we demonstrate the attacks   see Figure 1 in §III.
on popular services such as GitHub and Xen.do. We conclude
with a discussion of countermeasures.                                 This filtering-based approach includes a side channel: one
                                                                  user may be able to determine the document frequency of a
  Keywords-side channels; SaaS security; elasticsearch
                                                                  term, thereby potentially inferring if other users’ documents
                     I. I NTRODUCTION                             include that term. This observation was first made by
                                                                  Büttcher and Clarke [7] in the context of local file systems.
   Modern cloud services provide full-text search interfaces      But to date no side-channel attack has been demonstrated
to enable users to easily navigate potentially large document     exploiting the observation, and, as we shall see, doing so
sets. Search systems such as Elasticsearch [14] and Solr [48]     requires overcoming a number of significant challenges.
are both used by individual enterprises and offered as hosted
services for other companies. Databases such as MySQL             This paper. We provide the first treatment of logical side-
include similar search interfaces for columns containing          channel attacks on modern multi-tenant search services. We
unstructured text [35].                                           begin by investigating representative open-source systems
   The canonical search API allows querying one or more           and assessing whether the basic document frequency (DF)
keywords (or terms as they are usually called) to obtain          side channel mentioned above exists. We setup local instal-
an ordered list of matching documents. The response may           lations of systems including Elasticsearch/Solr and MySQL,
additionally provide a real-valued score for each document.       following best practice guides for multi-tenant search. In all
Which documents to return and their scores are determined         systems surveyed, we confirm that DF leakage can occur.
using a relevance algorithm, most often term-frequency                Despite this, and akin to early work on more well-studied
inverse-document frequency (TF-IDF) [30, 54] or one of            side channels such as those based on CPU caches [4, 38, 40],
its variants such as BM25 [53]. The TF-IDF score of a             it is not a priori clear how an attacker can exploit DF scores
document is proportional to the ratio of the term frequency       in realistic settings. In modern multi-tenant infrastructures,
(the number of times a term appears in that document) to the      there exist a number of challenges: the precise scoring
logarithm of the total number of documents divided by the         functions used in real services are proprietary and unknown,
document frequency (the number of documents containing            a user’s documents may be assigned to one of many possible
the term at least once). To compute these scores quickly,         indexes, noise in relevance scores arises due to the number
of files fluctuating frequently over time as users add or           obtain co-location with a target, we use our co-operative co-
remove files, indexes may not remove keywords from an               shard test to build our third low-level tool that we call a shard
index even after a file is deleted, many APIs rate limit            map: A set of documents in which each document is present
queries to search indexes, and more. It could also be, of           on a distinct shard. We will show that it is possible even on
course, that some sophisticated enterprise services do deploy       large-scale services to build complete shard maps, i.e., ones
proprietary countermeasures.                                        that appear to cover all shards used by the system. A complete
   We develop STRESS1 attacks, which consist of a multi-            shard map already reveals the number of shards, but more
step methodology for exploiting DF side channels. Our               damagingly will be useful as a preliminary step for more
attacks overcome the challenges mentioned and, ultimately,          granular attacks. We show how to do the following using a
realize the first demonstrated cross-user side-channel attacks      shard map:
in this setting.                                                       • DF estimation: We can reverse-engineer each shard’s
   Our framework begins by providing three low-level tools                unknown scoring function using a curve-fitting strategy.
that aid in attacks. First is a new approach that we call                 This yields a function that maps a term’s search score
score dipping. It provides a basic ability to infer, for a                to an estimate of that term’s DF on a shard. This
single index that includes an attacker document, whether                  allows, among other things, trending: the ability to count
there exists another document on the index containing a                   the number of (private) documents mentioning a word.
specific keyword. The insight is that an attacker can abstract            For example, if one knows an identifier used by a
away details of the scoring function, relying only on the                 particular company using GitHub, our technique allows
assumption that scores decrease with increasing DF. Score                 counting the number of private files they have stored on
dipping improves on prior ideas [7] for how to exploit the side           the service.
channel because it can be used without precise knowledge               • Brute-force term recovery: We can use our shard
of the scoring function used by a service plus, as we will                map to test if a given term exists anywhere in the
experimentally show, it is robust to noise.                               system, thereby allowing an attacker to brute-force
   In large-scale systems there will be a large number of                 recover moderately high-entropy values from victim
shards across which an index is split, and score dipping alone            repositories. While the side-channel attack does not
is not effective in this setting. Each shard can be thought of            reveal to the attacker which repositories contained the
as a logically isolated portion of the index, and a scoring               term, we propose scenarios that nevertheless allow the
function only takes into account documents assigned to the                extraction of sensitive information such as credit card
shard. In targeted attacks against a particular victim, attackers         numbers, social security numbers, passwords, and more.
must have the ability to place one or more documents on             We evaluate the viability of STRESS attacks in practice
the same shard as the target’s documents. But the search            with case studies of GitHub, Orchestrate.io, and Xen.do. As
service controls shard assignment, typically randomly load          a sample of our results, we demonstrate on GitHub (in a
balancing new documents across them. Thus attackers are             responsible way, see discussion in §VI) that one can build a
faced with an analogous issue to the co-location challenge          191-document shard map in 104 hours with a single account.
that must be overcome in cross-user side-channel attacks in         We estimate that it would take about a day to brute force
public infrastructure-as-a-service (IaaS) [23,43,51,55,57] or       a space of 106 possible terms on every shard. For example,
platform-as-a-service (PaaS) [60] clouds.                           if one knows the BIN and last four digits of a credit card
   As a first step towards attacking a multi-shard system, we       number stored in a GitHub repository then the rest of the
show how to use score-dipping to construct our second low-          card’s number can be brute-forced in under a day with
level tool, called co-shard tests, against multi-shard systems.     191 free accounts (c.f., [18] for discussion of credit card
Our co-operative co-shard test allows an attacker to deter-         numbers and other information being stored on GitHub). We
mine if two attacker-owned documents have been assigned             also discuss how stripping relevance scores (but still ranking
to the same shard. Specifically, we use score-dipping to            documents) is likely to be inadequate.
build a covert-channel between different documents that are            We conclude by discussing potential countermeasures,
owned by the same user or different, co-operating users, and        suggesting in particular a new countermeasure which re-
hence determine if they are on the same shard. This channel         places actual document frequencies with ones trained from
however does not on its own achieve co-location on a shard          public data. We discuss the merits of this approach and routes
with a victim’s documents, since the channel is only between        to deployment.
attacker documents.
   We next propose a new and different approach to obtaining                              II. BACKGROUND
co-location with a victims’ documents, and in the process
also learn about the service backend. Instead of trying to just     Ranked keyword search. A fundamental information-
                                                                    retrieval task is finding relevant text documents for keyword
  1 Search Text RElevance Score Side channel                        search queries. Let D denote a corpus of text documents.
For our purposes, a document consists of a bag-of-words                  TF-IDF scoring has many advantages and has intu-
representation; each word is a string that we refer to as a           itive probabilistic and geometric interpretations (c.f., [54]).
term. Our concern will be search systems that expose an API           However, in applications it is often useful to account for
allowing keyword search, i.e., a client can execute a remote          other factors in determining relevance, like the length of a
procedure call S EARCH(t) for a term t that returns an ordered        document compared to the average length of all documents
list of documents d1 , . . . , dn for some (typically fixed, small)   in the index. The BM25 scoring method incorporates this
n, sorted from most to least relevant. In addition to the list,       additional information [53]. As our eventual attacks will
many APIs also return relevance scores s1 , . . . , sn for which      focus on TF-IDF, we omit the details and note that our attacks
si ∈ R indicates the estimated relevance of di to the query.          should extend to use of BM25.
A higher score indicates stronger relevance, and so si ≥ sj
                                                                      Multi-user indexes and the DF side channel. More
for i < j. Many search routines allow more complex queries
                                                                      than 10 years ago, Büttcher and Clarke [7] pointed out a
such as disjunctions and/or conjunctions of keywords, but we
                                                                      potential side channel when using TF-IDF scoring on multi-
will primarily focus on single-term search.
                                                                      user indexes. A multi-user index is simply one generated over
   This work will only consider unstructured document                 a document corpus D that includes files from different users
search in which documents have no semantic relationships.             with different permissions. To perform a search on behalf
This distinguishes it from settings such as web or social             of a user u, one uses the index to compute a ranked list of
network search.                                                       documents (d1 , . . . , dn ) with scores (s1 , . . . , sn ). Then one
   In our unstructured search context, the most prevalent way         post-processes the list to redact documents (and their scores)
of ranking is via term frequency/inverse document frequency           not accessible by u, resulting in a smaller list (d01 , . . . , d0n )
(TF-IDF) scoring [30, 54]. Let D denote the document                  with scores (s01 , . . . , s0n ) that are returned to u.
corpus, N = |D| the number of documents, t be any term,
                                                                          Büttcher and Clarke pointed out that systems like Apple’s
and d be an arbitrary document in D. Define df(t, D) =
                                                                      filesystem search service Spotlight are multi-user. While
|{d ∈ D | t ∈ d}| to be the number of documents in
                                                                      permissions models can be rather complex, we will focus our
D containing term t. This is referred to as the document
                                                                      attacks on settings in which users should only be able to read
frequency (DF). We define the term frequency tf(t, d) as the
                                                                      the files they own, and no others.
number of times the term t appears in the document d. We
define the inverse document frequency by                                  In this context, Büttcher and Clarke show that idf(t, D)
                                                                      forms a potentially exploitable side channel that violates
                                              N                       document confidentiality, even if a search index properly
              idf(t, D) = 1 + log                    .
                                        df(t, D) + 1                  filters out search results on documents not owned by the user
The TF-IDF score for the relevance of document d to the               performing the search. This channel will allow an adversary
single-term query t is                                                to learn partial information about document frequency, so we
                                                                      call this the DF side channel.
         scoretf-idf (t, d, D) = tf(t, d) · idf(t, D)           (1)
                                                                          To demonstrate their observation, consider an adversarial
The TF-IDF score for a multi-term query q = (t1 , . . . , tm ) is     user Eve that wants to determine the number of documents
                                m
                                X                                     that contain a term t∗ . For example, it may be that Eve
      scoretf-idf (q, d, D) =         scoretf-idf (ti , d, D)   (2)   wants to learn whether another user Alice has a document
                                i=1                                   dA = {t∗ } stored on the system. Then, there is a simple
We note that the idf(t, D) term is independent of the                 attack exploiting the scoring function as a side channel.
document d, and it is intuitively used to weight terms for                Eve generates two documents d1 = {t∗ } and d2 = {r}
multi-keyword queries.                                                where r is some random term of length sufficient to ensure
   There are many variants of the basic TF-IDF score that             that it will not appear in any user document. Then Eve issues
include other parameters and normalizing terms, and also al-          two search queries: First for S EARCH(t∗ ), which returns
ternative definitions of term frequency and inverse document          document d1 with score s1 , and then for S EARCH(r) which
frequency. Indeed, the live systems we experimented on used           returns document d2 with score s2 . Even though S EARCH
more complicated variants of TF-IDF, but we will use this             only returns results related to documents owned by Eve, Eve
simple formulation for the time being.                                can anyway use s1 and s2 to infer information about other
                                                                      users’ documents. By construction Eve has arranged that
   To implement TF-IDF scoring and search, a system
                                                                      tf(t∗ , d1 ) = tf(r, d2 ) = 1 and df(r) = 1. Thus referring
generates an inverted index. For each potentially-searched
                                                                      back to (1), Eve knows that
keyword t, one stores (t, idf(t, D)) at the head of a list of
(d, tf(t, d)) pairs. This allows fast computation of the TF-                                                                   N
                                                                         s1   =    tf(t∗ , d1 ) · idf(t∗ , D) = 1 + log
IDF and the documents that should be returned in response                                                                 df(t∗ , D) + 1
to the query.                                                            s2   =    tf(r, d2 ) · idf(r, D) = 1 + log N/2 .
Thus Eve now has two equations in two unknowns and can
solve for N and df(t∗ , D). The latter reveals how many                                   add documents                                  query = “cat dog”

documents in D contain t∗ . Under the assumption that t∗            “dog cat” “dog cat” “cow” “bird”
                                                                                                              dog     d1                d2
                                                                         d1        d2     d3          d4
would only appear, if at all, in dA (e.g., because it is rather
                                                                                                               cat                      d1    d2
high entropy), then Eve can conclude that Alice’s document                         ES load
contains t∗ .                                                                      balancer                   cow              d3
   The attack as described requires scores, but Büttcher and               shard1             shard2      inverted
Clarke detail another attack that uses only the order of                                                     index
                                                                       d1     d2     d3    d4                          score    score    score     score

documents returned by a multi-term search to approximately                                                                     d1        d2
                                                                              …                   …
bound df(t∗ , D). They also mention that their techniques                                                             Raw results from index
could be used to perform brute-force attacks, repeatedly                                                                       score     score
                                                                                   ……shard
                                                                                       shardn n
                                                                                                                               d1        d2
using the side channel for different possible values for the                       shard n

target term t∗ .                                                                                                           Filtered results
                                                                                     Indexes
   Büttcher and Clarke conjecture that this side channel could
be used to recover information from real multi-user search
                                                                   Figure 1: A typical multi-tenant ES deployment consisting
indexes, but they do not demonstrate any working attacks. So
                                                                   of several shards, and an example of inverted indexes and
while the DF side channel has been known to exist in theory
                                                                   query filtering in ES. Documents from different users are in
since 2005, we are unaware of any investigation into its
                                                                   different colors.
exploitability in practice, despite the widespread deployment
of multi-user indexes. As we will discuss in the next section,
there appear to be inherent challenges to building real attacks,
including some noted by Büttcher and Clarke and others that          An architectural diagram of a canonical ES deployment is
we uncover related to distributed system design.                   depicted in Figure 1. We assume a multi-tenant setting, in
Other storage system side channels. Other side channels on         which multiple distinct user accounts have their documents
search indexes and databases have been developed. Gelernter        indexed. In large deployments, a single server is insufficient
and Herzberg [17] show how to exploit a cross-site timing          to handle search queries, and so one instead builds separate
side channel to test for the presence of terms in a target         indexes across multiple shards. A common way of load
search index. Our attack does not require malicious code           balancing across shards is to assign users at random to a
injection, but does enable term extraction from a search           shard, meaning all their files will be in that shard. Should
index. Futoransky et al. use a timing side channel on              individual users have many files, it may be needed to
insertions into MySQL and MS SQL databases to extract              have more granular load balancing. For example, one can
private information [16]. They observe that insertions take        assign each individual document to a shard randomly when
longer if a new virtual memory page is written, and use a          the document is uploaded, or there may be other logical
divide-and-conquer approach to learn private terms. Their          groupings of documents. For example in GitHub, users may
side channel is much harder to exploit than ours because it        have multiple git repositories, and as we will see later GitHub
requires fairly high-precision timing measurements.                load balances across shards at the granularity of repository.
     III. S URVEY OF M ULTI - TENANT S EARCH S IDE                    Lucene, Solr, and ES are all open-source projects, and
                         CHANNELS                                  typical configurations for the ranking function can be found
                                                                   online in forums [29,42]. The default ranking used by Lucene
   The basic DF side channel has only been discussed in
                                                                   (and so, in turn, by ES and Solr) is a variant of TF-IDF given
theory, and it is unknown what search systems, if any,
                                                                   by the equation
are vulnerable. We therefore begin by surveying existing
open-source multi-tenant search systems, and experimentally                               X ρq,d · βt · tf(t, d) · idf(t, D)2
                                                                         scorees (q, d) =          p                            (3)
confirm that the DF side channel exists in every setting
                                                                                                           P
                                                                                          t∈q        |d| ·    idf(t, D)2
we consider.                                                                                                          t∈q
                                                                                                              P
Elasticsearch. There are a few prominent systems for               The query coordination factor ρq,d =          t∈q I(t ∈ d)/|q|
implementing full-text search on unstructured documents.           boosts documents that contain more terms matched by
Lucene [27] is a Java library which implements the building        the query. It counts the number of query terms matching
blocks of a search index, including functionality such as          the document and divides by the total number of terms
document tokenizers and query parsers. It also implements          in the query |q|. The per-term boost function βt allows
common data structures used for indexing. Elasticsearch (ES)       customization of scores basedpon important application-
and Solr are two libraries that implement sharding and cluster     specific terms. The division by |d| is what’s referred to as
management for Lucene indexes. ES and Solr are widely used         the field-length norm, and it simply acts to normalize relative
in industry due to their efficiency and scalability.               to the size of the document. In some configurations, the field-
length norm is combined with an index-time field-level boost,         the content field [35]. As a result, all the tenants share the
which for our purposes would simply change βt .                       same index.
    An attacker that retrieves a score scorees (q, d, D) on their        We conducted the same tests as we do for ES, and observed
document d will know most of the terms in the right hand side         the same result: the relevance score of a document for a
of (3), with the only unknowns being the value N , df(t, D)           given term will be affected by the documents that contain
for each t ∈ q, and, if the configuration is unknown, the boost       the same term, even if these documents are owned by other
function and other factors. When the configuration is known,          tenants. The result also suggests that the DF side channel
this is just a (log-linear) equation in two unknowns. In this         exists in MySQL.
case the attack applies as in §II.                                    Other vulnerable systems. We found five vulnerable cloud-
    To test if ES has the DF side channel, we set up a local          based search services using the similar methodology as in
installation of ES version 2.3.4, and configure it to use one         ES and MySQL. A cloud-based search service aims to
shard with zero replicas. We leave the other configuration            provide scalable, easy-to-manage full-text search for web or
options default. Following the suggestions provided by                mobile applications. An application can use it to build and
ES [34], we adopt the shared index strategy, create two               maintain indexes on its data, and handle search requests.
tenants alice and bob, and add a tenant-id field to a document        Such services usually charge the applications based on the
data structure to specify the document owner. A document              amount of storage used or the number of requests processed.
data structure is a piece of JSON data that consists of three         All of the systems we considered provide RESTful APIs and
fields: a tenant-id field, a name to store the document name,         reveal relevance scores. Four of the services are built on ES
and a content field to store the document content.                    (i.e., hosted-ES services), including AWS Elasticsearch [3],
    We implement and test two common search filtering                 AWS CloudSearch [2], Searchly [45] and bonsai [6]. It’s
mechanisms to enforce access control: filtering on tenant-            easy to confirm that they inherit the DF side channels from
id in the query [13] and filtered index alias [1]. The                ES. We investigated these four due to their popularity, but
former excludes the documents that fail to meet the filtering         there are many other hosted-ES services that could also have
conditions, e.g., excluding documents whose tenant-id 6=              the vulnerability. One vulnerable system called Swiftype
alice for queries issued by the tenant alice. The latter works        implements its own search engine [50].
in the same way as the former, but it makes search filtering             Note that even if the side channel exists in a hosted
easier by allowing a user to create an alias name for a set of        search service, an application built atop that service will
filtering conditions.                                                 not necessarily have the DF side channel. For example,
    We first generated a unique term t, added a document da =         an application could conceivably assign each of their users
{t} as alice (the tenant-id of da is set to alice), and got a score   to an independent index. However, due to the costs of
sa = scorees (t, da ). Then, we added a document db = {t}             cloud-based search services, application developers would
with tenant-id = bob, and measured s0a = scorees (t, da ). We         typically prefer to use shared indexes. In Swiftype, a basic
observed that s0a < sa , and s0a decreases as more documents          plan ($299 per month) only provides one index for usage,
that contain t are added by the tenant bob. Finally, we deleted       while a business plan ($999 per month) provides up to three
all the documents associated with bob, measure again as               indexes. In Searchly, a professional plan ($99 per month)
alice to get s00a = scorees (t, da ), and saw s00a is the same        offers 13 indexes. So if a multi-tenant application is built
as sa . We observed the same results under different filtering        atop the service, the application’s users will share the same
mechanisms. These observations strongly suggest that one              indexes and might be vulnerable to information leakage.
can infer if there are other documents containing a term by           Looking at the case studies advertised by Swiftype [49], we
examining relevance scores; therefore, the DF side channel            realized some of them are indeed multi-tenant applications.
exists in ES.                                                         We also noticed that Heroku uses Swiftype and Searchly as
                                                                      its search add-on [21], suggesting the DF side channel might
MySQL. We set up a MySQL 5.6 server using its default                 be inherited by Heroku-based applications.
configurations. In MySQL-based multi-tenant applications,
a common design is multi-tenant-per-table, that is, storing           Non-vulnerable systems.       We also investigated Post-
all tenant’s data in the same table, with a tenant-id field           greSQL [41], CouchBase [9], crate.io [10], Searchify [44]
to distinguish each tenant’s records [32]; then, to get the           (not to be confused with Searchly above), and Google App
records only associated with a tenant alice, one can issue            Engine [20]. Our experimentation suggests that these systems
SQL queries with a condition tenant-id = alice. We achieve            do not exhibit the DF side channel, primarily because they
multi-tenancy in MySQL based on this design pattern. Our              appear to use independent indexes for different tenants.
simple multi-tenant application uses one table, each record
                                                                       IV. T HE DF S IDE C HANNEL IN E NTERPRISE S YSTEMS
in which corresponds to a document. A record has the same
three fields as the documents in the ES tests. To enable full-          In the controlled or partially-controlled settings above, we
text search in MySQL, we build a FULLTEXT index on                    verified that the DF side channel was present. Enterprise
search systems however introduce a number of complica-               Consistency and deletions. We also observed occasional
tions, and it is at first unclear if the DF side channel can         larger changes in relevance scores likely due to other
be exploited. In this section we discuss the major issues            systems behavior. ES and similar systems have complex
that must be addressed in understanding if such a system is          mechanisms for propagating newly written data into shards
vulnerable in practice.                                              which maintain some form of consistency as segments of
                                                                     data are merged into shards. However, they do not maintain
Hidden relevance formulae. An adversary may not know
                                                                     consistent relevance scores when data are merged, causing
which TF-IDF variant is being used. The space of TF-IDF
                                                                     further difficulties for attacks that depend on fine-grained
variants is large, with several different possible choices for
                                                                     measurements in score changes. In some services it took up
tf(t, d) and idf(t, D) other than what we defined above, as
                                                                     to two minutes for a change in a document to result in a
well as different formulas for combining them to compute a
                                                                     change in relevance scores, slowing possible attacks. We also
score. These choices may use more features than we specified
                                                                     noticed that searches may be issued in quick succession yet
above, such as the length of the document. Scores for multi-
                                                                     return greatly differing scores, likely due to a segment merge
term queries may also be computed via more complicated
                                                                     in between the queries.
formulae and have constants that can be hand-tuned for
a given application. Finally, we found that some services               Deletions are implemented lazily by marking documents
implemented scoring via ad hoc methods that took into                for deletion and later expunging them via a background pro-
account last-touched time or the order of terms in a query           cess (c.f., [11]). The DF values are incremented quickly (i.e.,
(i.e., treating the query (t1 , t2 ) differently from (t2 , t1 )).   after a minute) but apparently only reduced after expunging.
                                                                     Thus an adversary who hopes to delete documents as part
   When the adversary does not know the scoring function
                                                                     of an attack is required to wait until its documents have
it can no longer implement the algebraic attack from the
                                                                     been expunged before it can observe a change in the score
previous section. This issue was cited by Büttcher and Clarke
                                                                     function. Further complication arises because an adversary
as preventing them from carrying out the attack on Spotlight.
                                                                     will not know which shard its document was present on and
Instead, other techniques must be developed that are robust
                                                                     deleted from.
to variations in the scoring function.
                                                                     API restrictions. Search interfaces are rate-limited, both in
Sharding. As mentioned above, enterprise search systems              terms of queries per time period (e.g., 5,000 queries per hour
perform load balancing by dividing the document corpus into          on GitHub) and their total size (e.g., 128 bytes to describe
shards, which are essentially independent indexes. Sharding          the keywords in the query). A very weak side channel may
may be done per-document, per-collection, per-user, or via           be mitigated if it requires an infeasible number of queries, or
some other metric like creation time. Replica shards (i.e.,          large queries.
copies of shards) are used to increase query throughput.                Tokenizers and API interfaces often strip special char-
   A side channel will only exist when scores are computed           acters, treating them as whitespace. So, for example, a
as a function of private documents, which usually means that         hyphenated number XXXX-YYYY may be tokenized into
an adversary’s document must be on the same shard as victim          two terms XXXX and YYYY, which have independent
data that it hopes to extract. Since search system interfaces do     DFs. This affects the information available via the DF
not expose information about sharding, this poses a further          side channel.
challenge for an adversary, who will need to arrange for
                                                                     Bystander data. An adversary who targets a victim or
its documents to be co-sharded with victim data, and also
                                                                     victims will need to carry out the attack in the presence of
not be misled when documents are placed on shards without
                                                                     a possibly large number of bystander users whose data are
victim data.
                                                                     uninteresting to the adversary. These data are not known to
Noise. The production search systems we experimented with            the adversary but will be used in relevance score calculations
displayed noisy behaviors that make attacks more difficult.          using a formula also unknown to the adversary. These
For instance, in all of our experiments on live systems              bystanders are also actively writing and deleting data in
we observed that relevance scores constantly changed, and            the index.
issuing the same search multiple times will result in different         The primary effect of bystander data in our work is their
relevance scores on almost every query (see Figure 2 in §V).         effect on false positives, which we return to below. The
   Some of the noise is likely due to variations in the value        essential issue is that an adversary is only able to compute
N , the number of documents in the shard, which is changing          the DF of a term on a given shard. It is thus impossible
constantly as many users write data to the index. This foils the     to distinguish with certainty between cases where a victim
algebraic attack of Büttcher and Clarke, because obtaining          document or a bystander document contains the term (and
two scores computed with same value of N may be difficult            causes its DF to be non-zero). In some cases, we will argue
or impossible, and anyway one cannot tell when this is               that it is possible to use contextual clues, like the presence of
the case.                                                            other terms in the same shard, to limit false positives.
                                                                               9.0499
                   V. STRESS ATTACKS
                                                                               9.0498
A. Attack Goals and Notation




                                                                       Score
                                                                               9.0497
   We consider services that allow an adversary to write data
and also use a search interface to retrieve relevant documents                 9.0496

with scores. We assume that access control is implemented                               0   20          40   60   0   3,600   7,200
properly, meaning that other users’ private documents are                                        Time                 Time

not returned to the adversary, or otherwise leaked directly        Figure 2: Example relevance scores returned by the GitHub
through the interface.                                             API when searching for the same term several times. Left
   Our adversary’s intermediate goal will be to determine the      shows the score variations in 60 seconds, and right shows
DF of some given terms t1 , . . . , tq . (Later we will discuss    the score variations in 2 hours. The time intervals for left
attacks built on this capability.) We start from simplest case,    and right are 2 s and 60 s respectively. Y-axis does not start
where each df(ti , D) is either 0, meaning no one has a            from zero.
document containing ti , or is positive, meaning that it appears
at least once. The document set D is changing constantly due
to bystander activity, but we assume that the terms ti are not
written or deleted in a short period for the attack, and also      term weight decreases. In the case of basic TF-IDF, the term
that the size of the shard does not change dramatically.           weight is idf(t, D), but this is true for all of the variants we
   In a system with a single shard, the DF of a term               have encountered. Indeed it is intentional: A more common
is well-defined. But in a multi-shard system, each term            term should be given less weight in multi-term queries. An
will have a shard-specific DF. To define the attack, we            adversary that does not know the scoring function can still
model the document set D as being partitioned into sets            take advantage of this property.
D1 , . . . , DnSHRDS , where nSHRDS is the number of shards. In
                                                                   Score-dipping. We use this property to build what we call
this case, our adversary should determine, for each shard,
                                                                   the score-dipping attack to determine if a term t appears
the tuple (df(ti , Dj ))qi=1 where the shard holds documents
                                                                   somewhere in a shard of a system that uses an unknown
Dj . That is, on each of the shards, it should determine an
                                                                   scoring function. For now, assume that our attack owns a
estimate of DF of each term on that shard. We note that
                                                                   document d on the shard of interest. The attack first writes
this attack will allow an adversary to detect that, say, t1 and
                                                                   two terms t and r to d by invoking WRITE(d, {t, r}), where
t2 happen to occur together on the same shard, which is
                                                                   r is a long random term (not present in another document).
stronger than simply detecting that they occur somewhere in
                                                                   Then it requests searches for t and r. The search for t returns
the larger system.
                                                                   only d with some score s, and the search for r returns only
Notation. In this section, we fix a term-sampling algorithm        d with some score s0 . The attack checks if s < s0 , and if so
RNDTERM that outputs a fresh random term that is assumed           it guesses that t is present in the shard.
to never appear in bystander documents. In our experiments
                                                                      If t was not present in the system originally, then after
choosing a uniformly random 16-character alphabetic string
                                                                   writing to d, we have both df(t, D) = df(r, D) = 1 (where
was sufficient.
                                                                   D is the document set in the shard) and the searches should
   We also fix some notation for documents, terms, and the
                                                                   return the same score. But if t was already present, then
interface into the search service. Documents will be treated
                                                                   df(t, D) > 1 and thus s should be lower.
as sets of terms in our notation. In reality they are strings of
text but the order of terms does not matter for scoring. We           To work on a real system this attack must be extended
assume the service provides the ability to write documents,        to tolerate noise in the scores returned. Due to bystander
which we formalize as WRITE(d, S), where d is a reference          activity, we will observe differences in s and s0 even when
to a document and S is a set of terms. This operation will         the terms t, r have the same DF. (Indeed just searching for the
overwrite the entire document to consist of exactly S. Next        same term twice will produce different scores. See Figure 2.)
we will write score(t, d) to mean the score of document d          Bystander activity that incidentally decreases s or increases
returned by the service for a search for the term t (note that     s0 may cause the attack to output a false positive.
multiple calls to score(t, d) may return different scores, and        To mitigate this effect, we observed that the effect of
we are not fixing a document set D — score(t, d) is defined        changing a DF from 0 to 1 (or some larger number) caused
according to the service’s response).                              a noticeably larger change in the relevance score than
                                                                   background bystander activity. In our attack, we perform
B. Basics of Exploiting the Side channel                           several measurements on a shard to compute the typical
   All of our attacks will be built on a fundamental property      variation when searching for terms with DF equal to 1 and
of all in-use relevance scoring functions we are aware of: As      2. We can then determine a threshold for when the score is
a term t becomes more common (i.e. its DF increases), the          small enough to indicate that a term’s DF is larger than 0.
C. Plan for the Attacks                                             Algorithm 1: C O S HARD T EST
   We now begin building towards an attack on a multi-shard          Input       : Document d1 and document set M
                                                                     Output : True iff ∃d ∈ M : d1 , d on same shard
system. In all multi-shard systems, the mapping of documents         Parameter: Integer δ > 0
to shards is handled by some load balancing strategy that is                            0
                                                                   1 r ← RNDTERM ; r ← RNDTERM ;
                                                                                      0
                                                                   2 WRITE (d1 , {r, r });
not directly exposed in the interface. (To an outside user,
                                                                   3 foreach d ∈ M do WRITE (d, r);
sharding is meant to be transparent, though it does result         4 SLEEP ;
in variation of relevance scores for the same query across         5 s ← score(r, d1 );
                                                                       0           0
                                                                   6 s ← score(r , d1 );
shards.) Thus an adversary cannot directly see in which                   0
                                                                   7 if (s − s) > δ then return True;
shards its documents reside, or directly control the shard on      8 else return False;
which a newly-created document is placed.
   The hidden layer of load-balancing creates several difficul-
ties. If we try to repeat the score-dipping attack several times
without considering which shard we are on in each run, we          (but not which one). It also uses a service-specific constant δ
will not know when we have explored all of the shards. Some        that we set by hand (once for each service). The attack starts
systems might have hundreds of shards, and it may take a           by selecting two random terms r and r0 . Then it writes r and
minute or more for a write to possibly change a relevance          r0 to d1 , and only r to the other documents. After waiting for
score. API rate-limiting can further slow naive attacks.           the writes to propagate, the algorithm issues two searches for
   A more serious problem is that naively repeating the            r and r0 , and records the score of d1 in the searches as s and
single-shard attack is not even a correct strategy when a          s0 respectively. Finally it outputs true if s0 is greater than s
service processes deletions lazily, meaning it only reduces        by more than δ.
DFs when expunging. In this setting, naive repetition will            This attack works based on the principles described. If d1
detect its own documents, which artificially increase the DF       was not co-sharded with any other document, then we have
of terms of interest, during the attack. Concretely, suppose       df(r, Dj ) = df(r0 , Dj ) = 1, where Dj is the shard containing
one stage of the attack writes a document d = {t, r}               d1 . But if d1 and one (or more) d ∈ M are on the same shard
containing the term of interest, and that deleting d, or           Dj , then df(r, Dj ) ≥ 2 and df(r0 , Dj ) = 1, resulting in a
removing t from d does not reduce the DF of t in the shard         noticeable change in the score.
holding d. Then later stages of the attack that happen to return      In this algorithm, most of the time is spent in SLEEP on
to the same shard will detect that the DF of t is non-zero, but    line 4. This is why we have chosen a fast version of co-shard
this will be due to d and not victim documents.                    testing, where we can test if a new document d1 was co-
   Below we show how to mitigate the difficulty of attacking       sharded with some d ∈ M without spending extra time to
without deleting via a technique we call shard mapping             determine which document it was.
that reverse-engineers the number of shards in the service            The final detail is fixing δ, which must be set so that
and also places an adversary-controlled document on each           we distinguish larger changes in the score from random
shard. In addition to giving interesting information about a       variation. We experimented with each service by repeating
backend, shard mapping helps avoid the issues above, and           several queries over a period of time, and setting δ to more
also improves the efficiency of attacks.                           than the maximum observed variation (see Figure 2 for an
   We build two families of attacks using shard mapping:           example of observed random variation).
First we show how to quickly test for the presence of              Co-shard testing on stable services. On some services
terms in other users’ documents, allowing for what we call         we noticed that searching for two terms with DF exactly
brute force term extraction. Second, we present a totally          1 would return results with exactly the same score. On
different approach called DF prediction that learns the            such stable services we can save time when co-shard testing
scoring function on a shard and then attempts to predict DFs       many documents via the following strategy: create many
using the learned function.                                        documents, all containing the same random term r. Then
                                                                   request a search for r, which returns all of the created
D. Tool: Co-Shard Testing
                                                                   documents, and partition the documents returned by their
   We first build a tool that we will use a sub-routine: co-       scores. If the service is stable, the documents on the same
shard testing. This will efficiently determine if an adversary-    shard will have the same scores, and otherwise their scores
owned document d1 resides on the same shard as another             will likely differ. Thus our test can immediately filter to
adversary-owned document.                                          a subset of documents that are likely co-sharded, and then
   Our strategy uses a technique similar to the score-dipping      perform the co-shard test to verify correctness.
attack and the details are given in Algorithm 1. The routine
C O S HARD T EST takes as input references to document             E. Tool: Shard Mapping
d1 , and a set of documents M (not containing d1 ), and              Our multi-shard attacks will start with a pre-computation
determines if d1 was co-sharded with any documents in M            phase that we call shard mapping, which aims to place
exactly one adversary-owned document on each shard in the            Algorithm 2: M AP S HARDS
system. We call a set M of documents with this property                Parameter: Integer nmax > 0
a shard map, and the goal of this subsection is to compute             Output : Shard map M
                                                                     1 Create an empty document d1 ;
a shard map efficiently. Recall that this is non-trivial since       2 M ← {d1 };
the mapping of documents to shards is hidden by the                  3 for j = 2, . . . , nMAX do
interface. After this somewhat slower pre-computation set            4      Create new empty document dj ;
                                                                     5      if C O S HARD T EST(dj , M ) = False then
the adversary will be able to build attacks efficiently as we        6           M ← M ∪ {dj };
describe below.                                                      7      else
   Our method for computing a shard map M is as follows:             8           Discard dj ;
                                                                     9      end
Initialize a set M consisting of a single document d1 (on           10 end
some shard). Then create another document d2 , and use the          11 return M

co-shard test to check if d1 and d2 are on the same shard.
If they are, then the attack discards d2 . If d1 and d2 are on
different shards, then it adds d2 to the map M . The attack         Optimizations and multi-mapping. We also implemented
continues creating further documents, except this time it tests     a slightly more complicated, but faster, variant of shard
for co-sharding with its documents in M before deciding that        mapping. In each iteration of the main loop on line 3, we
it has found a new shard and adding the new document to S.          changed the algorithm to create two new empty documents
After some large number of runs that do not find a new shard,         (1) (2)
                                                                    dj , dj instead of one. We then execute a version of
the adversary concludes that the set S consists of exactly one                                          (1) (2)
document on each shard of the system.                               C O S HARD T EST to test if either dj , dj (or both) landed on
                                                                    new shards. If neither did, we discard them both. If exactly
   We denote our method by M AP S HARDS and it is given in
                                                                    one did, then we keep it and discard the other. If both landed
detail in Algorithm 2. We repeatedly create a new document
                                                                    on new shards, then we must test if they landed on the same
and test if it has landed in an “unmapped” shard using
                                                                    new shard via another co-shard test. In principle this could
C O S HARD T EST. If not, we discard the document. If, on the
                                                                    be run with more than two new documents in each iteration
other hand, the document is on a new shard, then we add it
                                                                    but we found that mapping was fast enough with two.
to the map M .
                                                                       A second optimization is to apply the faster co-shard test
Run-time analysis. In Algorithm 2 we assume a service-              when the service returns stable scores. On some services this
specific constant nMAX has been fixed. We want to pick an           will increase the speed of the mapping attack substantially.
nMAX large enough to ensure that we eventually find every              Later we show that some attacks can be sped up using
shard without wasting too much time in the attack, since each       multiple shard maps M1 , . . . , Mm , where the first documents
co-shard test requires a costly sleep to propagate writes.          of all shard maps lie on the same shard, and second lie on the
   To analyze the run-time we assume that each newly created        same shard, etc. On some services like GitHub this will be
document is assigned a uniformly random shard out of nSHRDS         easy to construct due to their sharding policy, which places
possibilities. (Note that the actual shard assignment strategy      all files from a repository on the same shard. On others we
being used by a target service could be more complex, so            can run shard mapping multiple times, and then use co-shard
nSHRDS estimated by M AP S HARDS would only be a lower              testing again to find one document from each map that is on
bound.) Then the expected number of iterations before we            each shard.
have a document on every shard is given by the well-
known coupon collector problem with nSHRDS coupons (see             F. Attack 1: Brute-Force Term Extraction
for example [5]). A classic analysis tell us that the expected         We now build our brute-force term extraction attack using
number of tries is close to nSHRDS · (ln(nSHRDS ) + 1.6), with      a pre-computed shard map M . Our attack will use M to
tight tail bounds on deviations from the expectation.               quickly determine the DF of given terms on every shard of
   Thus one can set nMAX to be slightly larger than                 the system. More precisely, let B be a (potentially large) set
the coupon-collector prediction when one knows nSHRDS ,             of terms that we are interested in testing for, in a system with
say, from technical information the service has released.           nSHRDS shards. Our attack will return a tuple (B1 , . . . , BnSHRDS )
Alternatively, one can simply guess nSHRDS and run the attack       of sets of terms, where Bi ⊆ B consists of the terms from B
until many iterations fail to find a shard. Let nFIND be the        that are in the i-th shard of the system.
number of shards found after k iterations, and nFAIL be the            Our attack is given in Algorithm 3. It starts by initializing
number of consecutive iterations fail to find a shard after         the sets Bi to be empty, and then iterates over each document
the k th iteration. The probability of seeing nFAIL iterations      in the shard map, writing a random term and all of the
of failing can be calculated as (nFIND /nSHRDS )nFAIL . Then, one   terms in B to the document. After waiting for the writes to
can stop if the probability is smaller than a certain threshold.    propagate, it then tests for the presence of each t ∈ B on
We took the latter approach in our attacks.                         the shards using score-dipping again with some threshold δ.
 Algorithm 3: T ERM E XTRACT                                       Algorithm 4: DFP RED
   Input : Shard map M = {d1 , . . . , dnSHRDS }, term set B         Input : Documents d1 , . . . , dnDFE on same shard
   Output: (B1 , . . . , BnSHRDS )                                   Output : Score-to-DF model f
   Param : δ > 0                                                     Params: nDFE , training algorithm T RAIN
 1 Initialize all Bi ← ∅;                                          1 Lscrs ← φ;
 2 for i = 1, . . . , nSHRDS do                                    2 for i = 1 . . . nDFE do
 3       ri ← RNDTERM;                                             3      r ← RNDTERM;
 4       WRITE(di , {ri } ∪ B)                                     4      for j = 1 . . . i do WRITE(dj , r);
 5 end                                                             5      SLEEP ;
                                                                          si ← ij=1 score(r, dj )/i;
                                                                                 P
 6 SLEEP ;                                                         6
 7 foreach t ∈ B do                                                7      Append {hi, si i} to Lscrs
 8       for i = 1, . . . , nSHRDS do                              8 end
 9            si ← score(ri , di );                                9 f ← T RAIN (Lscrs );
10            s0i ← score(t, di );                                10 return f
11            if (s0i − si ) > δ then
12                  Bi ← Bi ∪ {t}
13            end
14       end
15 end                                                            target shard and then search and record the score as s. Finally,
16 return (B1 , . . . , BnSHRDS )                                 we produce an estimated DF by computing
                                                                                               [f −1 (s)] − 1

This approach minimizes the number of costly sleep times          where [x] denotes the closest integer to x. We subtract 1 to
by writing many terms to each file.                               account for the document added by the attack that contains t.
   This technique crucially depends on the shard map to avoid     Comparison to Brute-Force Term Extraction. Once we
incorrectly dipping the score for a term t with the attacker’s    have computed the model f we can also use it for brute-force
own write operations. Also we note that if we have multiple       term extraction to get an attack with essentially the same
shard maps then we can partition B and run independent            complexity by using f to predict when terms have DF equal
instances of T ERM E XTRACT in parallel.                          to zero. We opted for the first attack above because it does not
                                                                  require the training phase. Note that DF prediction actually
G. Attack 2: DF Prediction via Score Extrapolation
                                                                  recovers more, as it guesses the DF of a term rather than only
   Natural extensions of our first attack to estimate DFs         detecting if the DF is non-zero. As mentioned above, using
appeared to work correctly but were slow, as they had             T ERM E XTRACT to decide the DF of a term would be slow.
to measure and test if the DF was 0, 1, 2, 3, . . . before
finding the correct value. Our second attack estimates how        H. Attack 3: Rank-only Attacks
many documents contain a given term on each shard of a
                                                                     Our attacks above assumed that the search interface returns
search service (that is, we estimate df(t, Dj ) for each shard
                                                                  relevance scores. Some services however only return the list
document set Dj ). We call this DF prediction which is
                                                                  of ranked results without scores, and here we sketch how to
denoted as DFP RED.
                                                                  adapt our techniques to this case.
   At a high level, DF prediction works by collecting data on
the behavior of the score function when the DF of a term             We assume that the service supports multi-term search
is known, and then training a model that predicts DF from         queries, and that the relevance scoring function assigns
relevance scores alone. In our attacks we can speculatively       weights to terms that decrease with their DF. For now, we
guess the class of scoring functions based on knowledge of        also assume there is no noise in the scores on a shard.
common implementations, but we still assume that constants           When there is no noise in scores, scores will often result
and custom modifications to the function are hidden.              in ties, and we start by reverse-engineering how the service
   The algorithm DFP RED is described in Algorithm 4. It          breaks ties. In our experience this was done by sorting on the
assumes it is given input several documents on the same shard     document name, creation time, or some other easily-noticed
of the service (either from several shard maps or from some       property of the documents.
other method). Then it performs a data collection step in the     Rank-only term extraction. Our rank-only term extraction
loop that estimates the score of a search when a term has         attack is given in Algorithm 5. It takes as input two
DF equal to 1, . . . , nDFE , where nDFE is a parameter of the    documents d1 and d2 on the same shard, and a target term
system (see Figure 3 for example data). After this step it uses   set B. Without loss of generality we assume that d1 is ranked
a training algorithm to fit a curve f (from some class) that      higher than d2 in the case of a tie.
maps integers to reals. This f intuitively is a guess for the        The algorithm will compute the subset B 0 ⊆ B of terms
mapping from DFs to relevance scores induced by the system.       present on the shard with d1 and d2 . The algorithm iterates
   After computing f we can apply it in attacks. Given a term     over each t ∈ B. It writes t into the document d1 , and it
t of interest, an attack can write t to the document on the       writes fresh random terms ri into the document d2 .
 Algorithm 5: ROT ERM E XTRACT                                          of the service be D1 , . . . , DnSHRDS . Term extraction gives us
  Input      : Documents d1 , d2 , term set B                           abstractly an oracle OTE that takes input (t, i) and returns 0
  Output : Terms B 0 ⊆ B present on the shard.                          if df(t, Di ) = 0 and otherwise returns 1. DF estimation
1 foreach t ∈ B do
2     r ← RNDTERM
                                                                        provides a richer oracle ODF that takes the same inputs (t, i)
3      WRITE(d1 , t)                                                    but returns (approximately) df(t, Di ) itself.
4      WRITE(d2 , r)
                                                                           In this view any abuse will have some fundamental
5          SLEEP
6          R ← ROS EARCH({t, ri })                                      limitations. Short terms are likely to appear by chance in
7          if d1 is ranked below d2 in R then                           documents, so the first oracle will likely return 1 most of the
8               B 0 ← B 0 ∪ {t}                                         time. Also, since terms are extracted by a tokenizer, if some
9          end
10   end                                                                text happens to contain periods or hyphens (like a URL, SSN,
                                                                        phone number), then the text will be separated into small
                                                                        terms which may have high false positive rates. Neither of
                                                                        these oracles allows one to test for substrings of terms, so
   After waiting for the writes to propagate to the index, the          very high-entropy terms like cryptographic keys are, without
attacker issues a two-term search query for {ri , t}, which             some side information about them, intractable to guess. We
returns a ranked list R of two results. This list is either             nevertheless identify two types of attack scenarios that are
d1 > d2 or d2 > d1 . If it is the latter, the algorithm infers          possible within these limitations.
that t is on the i-th shard and adds it to B 0 .
   To see why this attack works, we consider the cases where            Medium-entropy terms. The first is brute-forcing medium-
df(t, D) is zero or is positive before the attack starts (where         entropy terms that are rare enough to avoid false positives
D is the document set on the shard). If it is zero, then d1             yet drawn from a brute-forcible space. As examples of
and d2 will have the same score and hence d1 will be ranked             sensitive medium-entropy data that may be stored within a
higher. If however df(t, D) is positive, then d2 will have a            search service, consider SSNs and phone numbers in the
higher idf since the DF of r is exactly 1 and the DF of t is            United States. In these cases, and assuming no hyphenation
at least 2 after we write the files. Thus, d2 has a higher score        is used (which is desirable for search), an adversary could in
and be ranked first.                                                    principle use the first oracle OTE to produce a list of all such
                                                                        numbers and SSNs stored in the shards of the service. This
Optimizations. This attack can be generalized to test for
                                                                        is already a severe violation of the confidentiality expected
several terms in each iteration of the main loop instead of 1
                                                                        by users.
(thus reducing the number of sleep operations). This version
requires several documents d1 , . . . , dm on the same shard,              A second type of medium-entropy data are (relatively
and we assume that ties are broken in the order d1 > d2 >               strong) passwords. Note that very weak passwords such as
· · · > dm . The attack writes r into the last document dm ,            “123456” are likely to generate false positives. An attacker
and the terms of interest t1 , . . . , tm−1 in the first m − 1          may test a dictionary of common passwords (or their hashes)
documents d1 , . . . , dm−1 . Then it issues a search query for         using OTE to determine which ones occur in the services’
{t1 , . . . , tm , r} and looks at the position of dm in the list. If   document set of terms. Passwords could be stored in search
a document di appears below dm , then the attack infers that            services when used as application backends, and there have
ti appears on the shard for the same reasons as before.                 also been well-publicized incidents of passwords being stored
                                                                        on GitHub repositories. In either case, an attacker could use
            VI. C ASE S TUDIES OF M ODERN S ERVICES                     access to OTE to filter the password dictionary to a smaller
   In this section we discuss how an adversary might abuse              set that it then uses for online password guessing attacks.
the attacks we constructed in the previous section. Then we                Medium-entropy data targets may also arise when an
explore three services against which the score-based attacks            adversary has partial knowledge on an a priori piece
are effective: GitHub, Orchestrate.io and Xen.do. We report             of high-entropy data. For instance, someone may store
on the performance of our attacks on the services, such as              documents that contain terms with adversary-known high-
how long they took, how much they would cost to mount at                entropy prefixes followed by lower entropy suffixes. The
scale, and how often they might fail. Finally, we examine               prefixes will lower or remove false positives, allowing for
rank-only attacks against GitHub and Orchestrate.io, who                brute-forcing of the rest via the oracle OTE .
provide web interfaces for performing multi-term search                    A final type of medium-entropy data may occur when
without returning relevance scores.                                     high-entropy data is tokenized into medium-entropy terms.
                                                                        Consider a hypothetical 24-character API key that consists of
A. Scenarios                                                            four 6-character chunks separated by hyphens. These may be
   To understand possible threats let us abstract the ability           tokenized into 6-character terms that could then be found via
that is implied by our brute force term extraction and DF               the oracle OTE , along with some false positives. This would
prediction attacks. Let the document sets stored on the shards          vastly reduce the space of possible API keys for an attacker
who only needs to try keys formed by combinations taken            how to extrapolate from our experiments to attackers with
from the set of 6-character terms found in the index.              no qualms about submitting as many queries as possible per
Term trending. A second class of attacks uses the richer           unit time.
ability of the ODF oracle to estimate DFs rather than simply       C. GitHub
detect if they are positive. Unlike the previous settings,
                                                                      GitHub is one of the most popular source code hosting
an attack may profitably query ODF for even low-entropy
                                                                   platforms, with 14 million users and 35 million repositories
terms to learn about how commonly they are included in
                                                                   as of April 2016 according to Wikipedia. GitHub has
documents. For instance, on GitHub, one can use the side
                                                                   two types of repositories: public repositories and private
channel to learn about the popularity of certain libraries or
                                                                   repositories. Users can register for a free plan and set up
packages. Or, if separate source code documents include
                                                                   unlimited numbers of public repositories, but no documents
unique identifiers associated to a particular victim (e.g., AWS
                                                                   or repositories can be marked as private. To enable use of
account IDs), then the ODF oracle can be used to count the
                                                                   private repositories, one can choose a 7 USD per month
number of documents in that victim’s private repositories.
                                                                   plan. In a private repository, documents can be accessed
Since we are able to extract per-shard DF estimations, an
                                                                   and searched by their owner or authorized users. Non-
adversary may be able to guess if it has found the shard of
                                                                   authorized users should not be able to learn anything about
a particular user by looking for a shard that contains, with
                                                                   the repository’s contents, such as the number and type of
high DFs, terms associated with that user. One can then focus
                                                                   documents, the contents of those documents, etc.
searches on that shard in order to reduce false positive rates
in, e.g., a brute-force attack.                                    GitHub search API and basic experiments. GitHub
                                                                   uses ES (hosted by Elastic.co) as its search engine for full-
B. Performing Responsible Experiments                              text search [8]. A user could use a web-based interface or
   We would like to validate the feasibility of attack scenarios   RESTful APIs to search for a term of interest. A search
as discussed above. However, the nature of the side channel        request will return with all the documents containing this
is such that we could, if careless, end up spying on actual        term in both the public repositories as well as in private
user data in these services (e.g., if we simply started querying   repositories to which the requesting user has access. The
for passwords). We therefore took care to ensure that our          RESTful search API returns relevance scores to facilitate
experiments would not expose private information about their       application development, which our attacks will exploit,
users or otherwise cause undue burdens on services.                while the web-interface returns ranked results without scores
   Our experiments will only target simulated victims, i.e.,       (we discuss attacking this setting in the Appendix). Based
accounts under our control with documents that we generate.        on public documentation [8, 19], we know that GitHub load
This will give us ground truth. Except for estimating false        balances across shards at the granularity of an individual
positive rates, we apply the DF side channel only to long,         repository: at the time the repository is created it is assigned
random unstructured terms that are exponentially unlikely          to a shard. All documents in that repository are indexed
to appear in any bystander’s document (given the number            within the assigned shard.
of such terms we use the side channel upon). Put another              We first performed some manual experimentation using
way, we explicitly avoid learning anything about other users’      our score-dipping attack to both confirm the DF side channel
data from the side channel. We refer to users other than           and reverse engineer some undocumented aspects of the
our simulated attack and victim users as bystanders (i.e.,         GitHub search service. We found that public repositories
everyone is a bystander except for our accounts).                  and private repositories use the same indexes. This means
   False positive rates caused by bystander data are important     that, looking ahead, a malicious user could use (free) public
for understanding the efficacy of possible attacks, as we          repositories and the search API to extract sensitive terms
expect false positives to be a significant limitation to the       from a victim’s private repositories. We also observed that
attacks in practice. The rates however depend on bystanders’       the index update time, i.e., the time between inserting a
potentially private data. We therefore perform carefully           document into a repository and it being added to an index,
limited false positive measurements in which we infer only         is less than 1 minute in most cases.
whether or not we get the right answer from our side channel          Search queries emanating from a particular user account
for random terms of given lengths. Even here we minimize           are limited to 5,000 per hour. There is a public interface
any perceived risk to other users, only searching for random       for search as well, which does not require an account,
unstructured data with no semantic value. We only report           and only searches public documents (which suffices for our
summary statistics and never what random values may have           attacks should an attacker use public repositories). This is
resided in one or more bystander’s documents, and we will          rate limited to 60 per IP per hour. The GitHub search API
not make these false-positive datasets public.                     allows queries with size less than or equal to 128 bytes.
   Attacks could involve making a large number of queries to       In our experiments, we primarily used private repositories
the service. We rate-limit our queries appropriately and show      for our simulated attacker, and found that pausing at least
two seconds between two consecutive API requests avoids                                  9       9.04
triggering rate limits. Therefore, in all our experiments, we




                                                                           score(t, d)
                                                                                                 8.84
pause for 2 seconds after search query and 60 seconds                                    8
after creating/updating a document. Using longer pause times                             7
might be better for handling outliers (i.e., the index update
time can be up to 2 minutes in rare cases), but would                                    6
significantly increase the experiment running time.                                          0   200    400   600   800 1,000
Shard mapping. As mentioned GitHub hosts millions of                                                     DF(t)
repositories across many users, and therefore uses a large
number of ES shards. We apply our shard mapping tool to            Figure 3: The changes of score(t, d) as df(t, D) increases.
determine how many, and to place an attacker document on           The scores when df(t, D) = 1 and df(t, D) = 2 are
each of the discovered shards.                                     highlighted. Y-axis does not start from zero.
   We ran the shard mapping algorithm variant as described in
§V-E, creating two new repositories each with one document
over 513 rounds for a total of 1,026 repositories. The δ
in C O S HARD T EST was set to 0.05. We stopped after 50           DFP RED. During the training, we use OriginLab [37] to
consecutive rounds (100 repositories) failed to find a new         test the data against all the functions provided, and find
shard. It took 104 hours and we discovered 191 shards.             without exception the best-fit function is in the form of
We might have missed some small number of shards. For              f (x) = a − b ∗ ln(x + c), where x is the variable representing
example, assuming random assignment of repositories to             the unknown DF and a, b, c are coefficients. This function is
shards, the probability of 100 consecutive failings if there       consistent with the standard Elasticsearch scoring function
were in fact 200 shards is 1%. Nevertheless, our shard map         in [28].
ends up sufficient for all experiments — all subsequent               Using AcctV we generate nDF victim documents in a single
simulated victims ended up on one of the 191 shards that we        repository, each document containing the single term {t∗ }
discovered. We note an Elastic.co use-case description states      which is chosen as a random 16-byte alphabetic string. We
that GitHub has 128 shards [19], suggesting this information       vary nDF and test the accuracy of the attack. We run the
is out of date.                                                    C O S HARD T EST attack to place a document d = {t∗ } from
   After creating one repository on each shard at GitHub, we       AcctA on the same shard with the documents of AcctV. We
can generate many shard map sets M1 , M2 , . . . simply by         then measure and record the score score(t∗ , d) by making
creating one document on each repository.                          a search query from AcctA. Then, we calculate dfest (t∗ ) =
   We note that using shard mapping it would seem possible         f −1 (score(t∗ , d)) − 1 as an approximation of DF(t∗ ) and
to track, over time, the number of shards used by GitHub.          measure the relative error rate (in percentage) and absolute
This could already be a hypothetical confidentiality issue         error in order to evaluate estimation accuracy. The relative
for services that want to keep their infrastructure configura-     error rate is calculated as |df(t∗ ) − dfest (t∗ )|/df(t∗ ) ∗ 100
tion secret.                                                       and the absolute error is calculated as |df(t∗ ) − dfest (t∗ )|.
   Note that the consistency issues mentioned in §IV might           We perform experiments for each nDFE , nDF pair for nDFE ∈
produce false positives in C O S HARD T EST; i.e., the differ-     {1, 5, 10, . . . , 250} and nDF ∈ {0, 1, . . . , 999}. Figure 3
ence in scores for two documents is greater than a threshold       shows the changes of the relevance score of score(t∗ , d) as
even though the documents are not on the same shard. To            DF(t∗ ) increases from 1 to 1,000.
handle this issue, we double check after C O S HARD T EST             As shown in Table 4, the average relative errors (across
returns a positive result: we run C O S HARD T EST again and       all nDF ) for any nDFE are all less than 0.5%, and average
accept the result if both rounds of tests give positive results.   absolute errors are less than 3. We find that when nDFE ≥ 50,
We adopt this false positive identification method in the          the average relative errors and the average absolute errors
C O S HARD T EST on all examined services.                         under different nDFE are similar, i.e., the estimations do not
DF prediction. As mentioned above, the documents in the            become more accurate as we use more data points during
same repository are assigned to the same shard. Doing more         regression analysis. Figure 5 shows a histogram of the errors
manual tests, we confirmed this, and leverage it in the design     for the 1,000 experiments (for the 1,000 different nDF values)
of our experiments. We use one account AcctA as the account        and for nDFE = 50. As can be seen, the performance of the
for a simulated attacker and another account AcctV for a           DF prediction is very good: about 10% of the estimations
simulated victim.                                                  are correct; less than 14 of the estimations have absolute
   We tested the accuracy of DF prediction as follows. For         errors of 5. We note that the attack performs differently on
a given value of nDFE , we create nDFE training documents          alphabetic and numeric terms, likely due to boosting in the
in a repository under the attacker’s account AcctA and run         score function.
                                 Relative error   Absolute error
                               Min Avg Max        Min Avg Max                                100                             GitHub-numeric




                                                                        False-postive rate
                                                                                                                            GitHub-alphabetic
                   Alphabetic 0.07% 0.38% 0.53%   0.52 1.93 2.83
                                                                                                                           Orchestrate-numeric
                   Numerical 0.13% 0.43% 0.58%    0.59 2.15 3.03
                                                                                                                          Orchestrate-alphabetic
Figure 4: An overview of the average relative and absolute                                   50
errors for DF prediction for all nDFE on GitHub. The first row
targets estimation for a random 16-byte alphabetic string and
the second row is for random 16-byte number.
                                                                                               0
                                                                                                   4   5   6     7    8       9     10     11
                          16-byte alphabetic      16-byte number
                                                                                                               Term length
              40
              35                                                   Figure 6: The average false-positive rates for different lengths
              30                                                   of alphabetic-character-only term and numeric-character-
 Percentage




              25                                                   only terms across three shards in GitHub and Orchestrate.io.
              20
              15
              10
               5                                                   number of tries (i.e., number of shards examined before
               0                                                   finding the target index) is 98.
                         0      1     2      3          4      5      The attack achieves a true-positive rate of 100% and a
                                    Absolute error                 false-positive rate of 0%. Since we also chose long random
                                                                   terms, excluding any noise due to bystanders, we conclude
Figure 5: The distribution of the absolute errors when nDFE =      that the attack solved the experiment perfectly.
50 (GitHub).
                                                                   False positives on GitHub. The brute-force term extraction
                                                                   attack will encounter false positives due to bystander data.
                                                                   To understand how often terms happen to be contained
   We repeat the experiments again on two further shards and       on GitHub, we estimate the false-positive rate associated
get similarly small error rates: when nDFE = 50, the average       with low-entropy terms. We also test two types of terms:
relative errors are 0.65% and 0.27%, and the average absolute      alphabetic-character-only terms and numeric-character-only
errors are 3.9 and 1.2, respectively.                              terms. For a given length `, we generate 20,000 terms of
   One important factor that can affect the estimation             length ` (` ≥ 5) and of a given type (104 terms for numeric-
accuracy is the time we wait between updating a document           character-only term when ` = 4) to construct B, and randomly
and relevance score measurement. We find if waiting only           select 5% of these terms as B 0 . We set ` to each of 4, 5, ..., 16.
30 seconds, there is so much noise in the data that we             We repeat the test on three different shards, and report on
cannot even do a reasonable curve fit to the scoring function.     the average false-positive rates across 3 rounds in Figure 6.
However, sometimes 60 seconds might still not be long              We can see when ` = 4, 5, the false-positive rates are 100%
enough for an index to reach a stable state: we indeed             or near 100% in both services. The false-positive rates are
observed unusual score variations during data collection.          relatively high even when ` = 8, but drops to a very small
While the DF estimation already works well despite this            value (< 0.5%) when ` ≥ 9 and zero when ` ≥ 11. We can
noise, we believe the performance could be improved further        also clearly see that numeric-character-only terms involve
with more effort on data collection and processing.                more false positives than alphabetic-character-only terms.
Term extraction attacks. We start by confirming that               Feasibility of brute-force attacks. According to GitHub,
term extraction works correctly in a controlled setting. We        developers sometimes leave CCN information in source
generate a set of 50 victim terms B and a set of 50 control        code [18], and users might also store their own personal
terms B 0 . We create a victim document d = B, and then run        information on GitHub [52]. We argue that it is sometimes
our term extraction attack on all the terms in B ∪ B 0 to see      feasible for an attacker with partial information to harvest this
if it can properly identify the victim terms. We repeated the      (and other) information via the DF side channel.
experiment 50 times.                                                  Recall that in GitHub one account can send 5,000 requests
   To save time, once T ERM E XTRACT finds the target shard        per hour. Our brute-force attack will write large files
containing d (i.e., a shard containing any of the terms form       containing terms to test and then issue one API call per term.
B ∪B 0 ) we ignore the other shards and only do term exaction      Since writing the file requires a wait time for propagation to
on the target shard. The average time for finding the target       the index, one would pipeline the writes while performing the
shard is 1,149 seconds, while the minimum time is 698              search queries. Assuming this is implemented, in the limit our
seconds and the maximum time is 1,607 seconds. The median          term extraction needs one API request per term guess (using
a modified version of T ERM E XTRACT that uses one random            To perform DFP RED, we need to put multiple documents
term ri to generate a score si that is then compared against      on the same shard. Unfortunately, unlike GitHub, no features
the scores of many victim terms). Each guess checks if the        in Orchestrate.io directly facilitate creating documents on
term is on a particular shard. This gives a rough estimate        the same shard. One solution is to create many documents
of 120,000 guesses on a shard per day with one account.           and use C O S HARD T EST to discover the documents that
Creating n additional accounts increases the brute-forcing        are on the same shard with a target document. However,
power by a factor n as the guessing algorithm can be run          this is very time-consuming. To speed this process up, we
in parallel.                                                      use the aforementioned ad-hoc score-based co-shard test
   For a concrete example, if one knows the BIN (bank             in §V. More specifically, we create 30,000 documents that
identification number) and last four digits of a CCN then         have the same content in AcctV, which is a unique 16-byte
there are about 106 possible CCNs. If an attack has focused       term, and measure the relevance scores of these documents.
on a particular shard the rest of the CCN could be brute-         We group the documents by their relevance scores, and
forced with one account in under a day. If the attacker is        keep 500 documents from the largest group. To eliminate
unsure of the shard, it could create one free account per shard   false positives, we use C O S HARD T EST to confirm these
and execute the attack in parallel (which, nicely, would be       documents are indeed on the same index. We repeat these
perfectly load-balanced on GitHub’s backend).                     procedures in AcctA and keep 100 documents.
                                                                     We perform experiments for each nDFE , nDF pair for nDFE ∈
D. Orchestrate.io
                                                                  {1, 5, 10, . . . , 100} and nDF ∈ {0, 1, . . . , 499}. The scoring
   Orchestrate.io is a database-as-a-service platform for         function in Orchestrate.io is still in the form of a − b ∗ ln(x +
developing web and mobile applications. The information           c). The average relative and absolute error rates decrease
stored on Orchestrate.io is likely different than in GitHub       as nDFE increases. When nDFE = 100, the average relative
since it is a generic key-value database and is being used to     errors are about 2.2% and the average absolute errors are
store all types of data. It seems likely that application back-   less than 6.0 for terms being tested. As df(t∗ ) increases, the
ends store sensitive customer information in Orchestrate.io.      estimations become less accurate. The maximum absolute
   According to Orchestrate.io’s official blog, it uses ES        errors are 15. However, when df(t∗ ) ≤ 250, the attack still
as its search engine [36], and has made efforts to secure         performs well, with the maximum absolute error less than or
its search API. However, we found its search API also             equal to 2.
expose the relevance scores of returned documents. Further
                                                                  Feasibility of brute-force attacks. In Orchestrate.io, a free-
tests suggested that the DF side channel also exists in
                                                                  plan user can only send 50,000 requests every month. So to
Orchestrate.io.
                                                                  search 109 terms, the attacker needs 20,000 accounts. Though
   The Orchestrate.io API does not restrict the number of
                                                                  this sounds costly, the process can be automated due to the
operators in the query but enforces a maximum query
                                                                  fact that the account registration is very simple — the attacker
size of 6 KB. The service does not have a specific rate-
                                                                  just needs to fill in an email address and a password — and
limiting policy but will throttle a user if her API requests
                                                                  no captchas are being used.
affect their servers’ performance. The index update time
                                                                     Another choice is to use Orchestrate.io’s professional plan,
on Orchestrate.io is faster than GitHub. To avoid burdening
                                                                  which is $499 per month, that allows one to send 5 M requests
on the target server, we decide to pause 30 seconds after
                                                                  per month and pay $0.01 for 10 K additional requests.
creating/updating a document and 2 seconds after each
                                                                  Sending 109 requests costs an attacker $1,500, but the gain
search query.
                                                                  of the attacks could be more than the cost. Of course, smaller
Attack results. In Orchestrate.io, we use the same                spaces can be brute forced much more cheaply and quickly.
experiments as in GitHub to test M AP S HARDS and
T ERM E XTRACT. M AP S HARDS collects 50 shards in 12             E. Xen.do
hours, using 128 rounds with 256 documents being cre-                Xen.do is a hosted search service which aggregates data
ated. The δ in C O S HARD T EST was set to 0.08. In               from a user’s accounts on multiple third-party services, builds
T ERM E XTRACT, the average time for locating the target          full-text indexes over the data, and provides interfaces to
shard is 324 seconds and the median number of tries is 15.        search the aggregated data. Xen.do supports more than 35
The term extraction attack also achieves a true-positive rate     services, including, but not limited to, Google Apps (Gmail,
of 100% and a false-positive rate of 0%.                          Contacts, Drives, etc.), cloud storage services (Dropbox,
   We also conduct the same false-positive tests in Orches-       OneDrive, etc.), customer relationship management (CRM)
trate.io. The average false-positive rates across three rounds    systems (Salesforce, ZohoCRM, etc.), and other services
are shown in Figure 6. As the term length increases, the false-   (Evernote, Office 365, etc.).
positive rates drop to zero more quickly than on GitHub;             Sensitive information harvesting is particularly threatening
when 7 ≤ l ≤ 9, we only find very few false positives (1          on Xen.do since the data are collected from users’ personal
to 3) for a given length.                                         accounts. Xen.do makes an best effort to guarantee data
security and privacy, and has received high ratings in various    documents on the same shard (recall that creating several
security tests such as Skyhigh Networks CloudTrust [56].          co-resident documents is easy because GitHub shards based
Unfortunately, we also find the DF side channel in Xen.do.        at the repository level). Using the web interface for GitHub
We found the all the supported services in Xen.do share the       search (which ranks but does not report scores), we observed
same multi-tenant indexes. Therefore, a malicious user can        that our attack returned a true negative (i.e. the order of
extract the sensitive terms in other users’ documents from        the two attacker documents did not change). Next we added
different sources at the same time.                               the term t (in this case a long random string) to the victim
   For Xen.do, its API access is not public and the API key       document and re-ran the attack, which swapped the order of
can be only obtained on request. We only obtain a 30-day          the attack documents in the web interface, confirming that
trial to the beta-test version of the API, which currently        the attack works.
only provides basic operations such as full-text search and          Interestingly our attack failed on Orchestrate.io. This
authentication. One operation — connecting Xen.do to a            appears to be due to their using a non-standard scoring
service — in the attacks must be done manually via the            function for multi-term queries. We found that for multi-
web interface.                                                    term queries, Orchestrate.io computed relevance scores that
   The indexes updates on Xen.do are very slow, often taking      weight terms based on their order in the query. So, for
about 20 to 30 minutes. In our attacks, after creating or         instance, “t1 t2 ” will give different term weights from
updating a document, we query every 10 minutes to see if          “t2 t1 ” while TF-IDF and common variants will treat these
the document has been indexed. We still pause 2 seconds after     terms equivalently.
each API request.
                                                                  G. Conclusions
Attacks results. Using C O S HARD T EST, we confirm that all
the services supported by Xen.do are using the same set of          The results demonstrate that our score-based attacks can
shards. We create a document d1 on a service serv1 (e.g.,         work on the three targets and can be used to extract sensitive
Gmail), and connect AcctA to serv1; then, we create a             data from other tenants’ documents. Without relevance
document d2 on another service serv2 (e.g., Dropbox), and         scores, one can still exploit the DF-side channel using rank-
connect AcctV to serv2. We then use C O S HARD T EST to test      only attacks. All the services we tested claim protecting
if d1 and d2 are on the same shard. If not, we disconnect         data security and data privacy as a priority. Indeed, they
AcctA from serv1 and reconnect it again, which forces             make efforts to secure their physical infrastructures, systems,
Xen.do to assign d1 to a new shard. We did two tests:             and APIs. However, the DF side channels, hidden in their
(1) randomly chose 5 different pairs of serv1 and serv2,          underlying search engines for years, make the services
and (2) fix serv1 as Dropbox, and 17 different serv2. In          vulnerable to sensitive data leakage via side-channel attacks.
both tests, C O S HARD T EST usually succeeded in between 4                        VII. C OUNTERMEASURES
and 10 tries. The success of C O S HARD T EST indicates that
                                                                     Perhaps the most obvious idea for a countermeasure is to
Xen.do uses the same set of shards for all services. The δ in
                                                                  simply not return relevance scores in response to searches,
C O S HARD T EST was set to 0.08.
                                                                  instead just providing an ordered list of documents. This
   In M AP S HARDS, we stop the attack if we can’t find more
                                                                  might be a hindrance to applications that make use of
shards in 10 rounds. After 20 rounds, we found 4 shards.
                                                                  the API’s relevance scoring. But more importantly, while
   Due to the restrictions of the Xen.do API and slow index
                                                                  removing relevance scores would prevent our score-based
propagation, we only collected a small amount of data. We
                                                                  attacks, as shown in §VI, it does not prevent exploitation of
use the ad-hoc score-based method again to put 50 documents
                                                                  the DF side channel via rank-only attacks.
on the same shard. Since the index updates are slow, it took
us longer to run DFP RED (dominated by waiting). We had           Previously proposed countermeasures. One can remove the
the best results fitting the scoring function to a curve of the   side channel by isolating each users’ documents within in-
form f (x) = a − b ∗ ln(x + c). We use first the 15 data points   dependent indexes. Received wisdom suggests this approach
to approximate the scoring function and the other data points     is unsuitable for large-scale systems with many users due
for evaluation. The absolute errors of 40%, 49%, and 14% of       to poor performance [12]. Some Elasticsearch deployments
the estimations are 0, 1, and 2, respectively. This preliminary   have successfully used this architecture via careful tuning and
assessment suggests that our attacks will work on Xen.do.         optimization, but it may be too expensive for, e.g., Github to
                                                                  use [25]. Search functionality degradation is also a concern
F. Rank-only Attacks on GitHub and Orchestrate.io.                here, since users with small document sets may not provide
   We briefly checked if our rank-only attack works cor-          enough data on their own to have good DF estimates.
rectly against GitHub and Orchestrate.io, who provide web            Another approach is to retain a multi-tenant index, but
interfaces for performing multi-term search without returning     compute relevance scores in a way that matches what
relevance scores. On GitHub we started with a control             would have been computed in the independent index
experiment with an empty victim document and two attack           case. Büttcher and Clarke were the first to suggest this
countermeasure [7] and called their particular realization         list, the DF is stored to speed up searching. Typically the DF
of it “query integration”. It works by inserting a security        value is equal to the length of the list.
manager between the components of the system responsible              To implement blind DFs, one augments each posting entry
for query processing and index management. When a user             to contain a binary attribute indicating if the document is
issues a query, the security manager recomputes a user-            public (i.e. world readable) or not. We then modify the
specific view of the index (and relevance scores) that is          mechanisms for adding and deleting to maintain a count that
consistent with the user’s access rights. Subsequent work          we call the blind DF, which is now the number of public
provided different realizations of this approach [31, 39, 46],     postings in the postings list. This can be achieved, say, by
focusing on performance improvements by partially pre-             only incrementing or decrementing a posting lists’ DF when
computing views.                                                   adding or deleting a public document. Of course one may also
   These approaches were suggested in the context of local         store the (true) DF for purposes other than relevance scoring.
file system search. In the multi-tenant cloud services we have     This metadata must be stored for each document so document
primarily focused on, maintaining access control information       deletions can properly decrement the DF.
at every shard will incur a large storage overhead.                   To process a (public or private) search with blind DFs,
   Another countermeasure that has been proposed in the            one modifies the system to use the blind DFs in place of
literature takes a statistical approach, attempting to add noise   true DFs, but otherwise leaves it unchanged. In particular,
or otherwise change the IDF distribution so that an individual     one could compute relevance scores exactly as before, but
user’s private information is hidden. Zerr et al. [58] give        with a blind DF. To enforce access control one could use the
a countermeasure using a “relevance score transformation           post-processing filtering mechanism as is currently deployed.
function” meeting an ad-hoc statistical notion of confiden-        Since the relevance scores are not a function of private
tiality. It is unclear what guarantee this actually provides.      documents, the DFs will contain only public information.
                                                                   Comparison of the two approaches. Both approaches
A. New Countermeasures                                             increase the amount of storage space needed for the index.
   All the approaches discussed above seem to have inherent        For blind DFs, the amount of extra space required is on the
limitations which will impede their usability in large-scale       order of the number of documents in the index, since the
multi-tenant search indexes. We observe that they all preserve     public/private attributes for each document must be stored.
the exact functionality of TF-IDF scoring (or a slightly           For public-corpus DFs, the amount of extra space needed
noisy variant) over a user’s view of the system. This may          is only on the order of the number of unique terms in
be unnecessary: approximations that result in similar, but         the index. The amount of space needed for public-corpus
slightly different, scores are likely acceptable in practice.      DFs does not change as more documents are added to the
   Below we outline two approaches that eliminate DF side          index, whereas the space overhead of blind DFs does increase
channels more efficiently. We also implement and evaluate          over time. Unlike public-corpus DFs, blind DFs can be
one approach. We plan to open-source the relevant code. In         implemented without any preprocessing. Both approaches
both approaches, the searches are no longer scored strictly        will also potentially diminish the utility of DFs because
according to TF-IDF. Instead, the relevance score of a             private documents will no longer inform relevance scoring,
document d is computed as a function only of the public            even when a user is searching her own private documents.
documents and of d. In particular, it is no longer a function of   Edge cases, such as making a public document private, may
other private documents, whether or not d is public or private.    be difficult to handle. The main benefit of both approaches
                                                                   is that they are relatively simple to implement. The relevance
Public-corpus DFs. The first approach is called public-
                                                                   scoring and other portions of the system would be largely
corpus DFs. The idea is to train a DF model using public
                                                                   unchanged, including the access control filtering.
data. In GitHub, for example, this would mean computing
a DF model on a subset of public repositories. The model           B. Evaluation of Public-corpus DFs
itself would be stored as an auxiliary index in Elasticsearch,        Of the two approaches described above, we believe public-
enabling nodes to efficiently fetch the current public DF value    corpus DFs will likely be better for large-scale search systems
for a term they have not seen. A default DF (of one) could         like Github’s due to its low space complexity. Here we report
be used for terms which do not appear in the public data. In       on initial experiments to assess the potential practicality
settings like Xen.do and Orchestrate where there is no notion      of the countermeasure. All experiments were performed on
of “public” and “private” information, this approach will not      an Ubuntu 16.04 desktop, using Lucene 6.3.0 and Java 8.
work with data on the service. Instead, one could train on         The machine was equipped with a 512 GB NVMe SSD
suitable public file corpuses, should they exist.                  and 16 GB of DRAM. Microbenchmarks revealed a small
Blind DFs. We call the second approach blind DFs. Recall           latency increase of about 1% due to the countermeasure. We
that the search system we consider stores an inverted index        therefore focus our evaluation of public-corpus DFs on two
that consists of per-term postings lists. At the head of each      axes: space overhead and search quality.
     Corpus     #Docs   #Terms    Size (GB)    TD size (MB)                                     Real DFs    Enron DFs
      Reuters     0.8       1.0          0.6             8.7                           MAP           0.17         0.17
    Wikipedia     3.6      14.5         33.0           200.0                           P@5           0.43         0.43
                                                                              TF-IDF
       Enron     0.54       0.6          3.0             5.7                           P@20          0.31         0.31
                                                                                       P@100         0.17         0.17
Figure 7: The “#Docs” and “#Terms” columns are the total                               MAP           0.17         0.17
number (in millions) of documents and terms in the corpus                              P@5           0.44         0.43
                                                                              BM25
                                                                                       P@20          0.31         0.31
respectively. “Size” and “TD size” are the size and the size                           P@100         0.17         0.17
of the terms dictionary of the corpus respectively. Statistics
for the Reuters dataset refer to the pre-processed LYRL2004        Figure 8: Results of search quality experiment. MAP is
version [26].                                                      “mean average precision”. P@n is the precision only
                                                                   considering the top n documents returned for the search,
                                                                   averaged across all queries. Higher scores are better.
Space overhead. The space overhead of public-corpus DFs
comes from storing the auxiliary index of DFs for each
term. It is straightforward to evaluate this by indexing a         index was not stemmed, but common stopwords were
document corpus using Elasticsearch and measuring the size         removed. We used the relevance judgments from the “ad hoc”
of the term dictionary in the resulting index. Asymptotically,     track of the sixth, seventh, and eighth sessions of NIST’s
the term dictionary’s size is on the order of the number of        Text Retrieval Conference (TREC). There were 150 total
unique terms in the index, but we will still measure its size      labeled queries.
empirically to account for the effect of Elasticsearch’s term
                                                                      Our experiment consisted of a few concrete steps. We
dictionary compression.
                                                                   performed queries on two versions of the NIST index: an
    We tested with three datasets: the Reuters RCV1 cor-
                                                                   unmodified ‘insecure” one which used the actual DFs of
pus [26], a dump of the English Wikipedia from April
                                                                   the NIST corpus and one which used public DFs from the
2015 [15], and the Enron email dataset [24]. Each was
                                                                   Enron corpus. For both, we recorded the top 1,000 most
parsed, tokenized, stemmed, filtered to remove stop words,
                                                                   relevant documents returned for each query. Finally, with the
and indexed using Lucene. Finally, the statistics in Figure 7
                                                                   relevance judgments as ground truth, we computed quality
were collected by inspecting the resulting index. The term
                                                                   metrics to measure the degradation in quality (if any) caused
dictionary size is measured as the sum of the on-disk file sizes
                                                                   by our countermeasure.
of the .tim and .tip files of the Lucene index. These two
files store the compressed term dictionary and an index into          We used two metrics from information retrieval: “preci-
it, respectively. Note that the auxiliary data structure would     sion” and “mean average precision”. Intuitively, precision is
also store the DFs of each term. The size of the DFs in bytes      the fraction of returned documents that were relevant to the
would be about four times the number of unique terms for           query. If the number of relevant documents returned for a
each corpus.                                                       query is r and the total number of returned documents is s,
    These results are quite promising: even for the entire         the precision is defined as r/s. The metric P@n is defined
English Wikipedia, the public-corpus DFs would only require        as the precision when only considering the top n documents
about 250 MB of storage (the fifth column of Figure 7 plus         returned for the search. The numbers given in Figure 8 are
four times the third column). This is small enough that it         averaged over all 150 queries.
could be held entirely in memory on each shard, minimizing            Mean average precision is a related metric, defined simply
the number of slow disk I/O operations.                            as the mean over all queries of the per-query “average
                                                                   precision”. The average precision is, importantly, not simply
Search quality. Since the storage overhead of public-corpus
                                                                   the average of an arbitrary set of precision scores. Average
DFs is minimal, we can turn our attention to evaluating its
                                                                   precision is defined in our case by measuring the precision at
impact on search quality. We will use a standard methodology
                                                                   every cutoff point (i.e. n in P@n above) from 1 to 1,000, then
from information retrieval: queries with human-labeled
                                                                   summing and dividing by the number of relevant documents.
relevance judgments. This measures search quality for a set of
synthetic queries on a standard corpus by using human judges          The results of the experiment are in Figure 8. The results
to label documents as relevant or non-relevant for each query,     using relevance scores computed with the default implemen-
then evaluating a search engine’s performance in retrieving        tation is in the column of Figure 8 labelled “Real DFs”.
relevant documents. We built our experiment by modifying           The results with the public-corpus DFs countermeasure
Ian Soboroff’s trec-demo project [47].                             enabled (using the Enron email corpus) are in the column
   Our corpus for the experiment was a pre-built Lucene            labeled “Enron DFs”.
index consisting of volumes 4 and 5 from NIST’s Text                  The results show that using the Enron DFs in place of the
Research Collection. These two volumes contain about               real DFs for the corpus has negligible effect on the precision
530,000 total documents and 4.1 M unique keywords. The             of the searches. Most values are identical when rounded to
the hundredths place. This is true both for TF-IDF and the         and Swifttype would lead to a DF side channel. Some
more modern BM25 scoring function.                                 of these search-as-a-service systems are in turn used by
Limitations and future work. We believe our evaluation             other cloud services, such as Heroku, which may therefore
presents good evidence of the practicality of the public-          inherit any side channel. We have not yet performed in-depth
corpus DF countermeasure. Nevertheless, it is limited in a         experimentation with applications using these services, so it
few important ways. First, we only evaluate unstructured           may be that noise or other subtleties prevent, e.g., brute-force
English text corpora and queries, and it is unclear if the         term recovery attacks or accurate DF estimation. That said,
results generalize to code repositories like Github. Obtaining     services would do well to revisit their use of shared search
labeled relevance judgments and corpora for code search is         indexes in order to prevent STRESS attacks.
an interesting direction for future work. Since the quality           Along another dimension, we have focused on attacks
of the search results above is, in an absolute sense, quite        whose search queries include a single term. But many search
low to begin with, an experiment on a better-tuned search          services allow more sophisticated queries such as phrase or
system which uses modern IR techniques to increase search          wildcard queries. We began thinking about how to exploit
quality may yield different results. The final limitation is the   these, but have not yet seen how they could provide attacks
small sample size of our experiment. Due to the difficulty         better than our single-term ones. Future work may do better.
of finding appropriate data sets and relevance judgments, we          Based on our experiments we recommend that the imple-
only evaluated search quality for one dataset, and leave a         mentations move away from the simple filter-based approach
more thorough evaluation as an open problem.                       to multi-tenancy. We suggested possible countermeasures,
                                                                   such as using document frequencies taken only from public
                 VIII. V ENDOR R ESPONSE                           documents, and our preliminary evaluation suggests this
   We disclosed via email to the three services investigated.      approach will be very practical for deployments.
Xen.do immediately removed relevance scores from API re-
sponses as a preliminary mitigatition. GitHub forwarded the                             ACKNOWLEDGMENTS
issue to Elastic.co, their search service provider. Elastic.co        We would like to thank all the anonymous reviewers for
suggested several countermeasures in their response. To            their comments and suggestions. We would also like to thank
mitigate our attacks, Elastic.co suggested small deployments       the employees at Elastico, GitHub, and Xen.do for their
could use an index-per-tenant, but they admitted that this         helpful discussions during our disclosure process. This work
could be cost prohibitive for large deployments. In some           was supported in part by NSF grants CNS-1558500, CNS-
cases, services can disable scoring and ranking if the resulting   1330308, CNS-1453132, the Defense Advanced Research
functionality loss is acceptable. Another approach is to put       Projects Agency (DARPA) and Space and Naval Warfare
sensitive terms in the fields that are not used for ranking,       Systems Center, Pacific (SSC Pacific) under contract No.
an approach suggested by Alex Brasetvik of Elastic.co. This        N66001-15-C-4070, and a generous gift from Microsoft.
will prevent the side channel being exploited for those terms,        Ristenpart and Grubbs have large financial stakes in
though some services might find reliably identifying sensitive     Skyhigh Networks.
information within tenants’ data challenging. We believe the
public-corpus DFs countermeasure presented in section VII                                    R EFERENCES
is the best approach due to its scalability and deployability.      [1] Index Aliases. https://www.elastic.co/guide/en/elasticsearch/
Orchestrate.io’s parent company, CenturyLink, announced                 reference/current/indices-aliases.html#filtered, 2016.
that the service vulnerable to our attack will be shut down         [2] Amazon. Amazon Cloudsearch. https://aws.amazon.com
                                                                        /cloudsearch.
on March 17th, 2017.
                                                                    [3] Amazon. Amazon Elasticsearch service. https://aws.amazon.
                     IX. C ONCLUSION                                    com/elasticsearch-service.
                                                                    [4] D. J. Bernstein. Cache-timing attacks on AES, 2005.
   We presented STRESS attacks. These demonstrate that              [5] J. K. Blitzstein and J. Hwang. Introduction to Probability.
the industry-standard method for multi-tenant search leads              Chapman and Hall/CRC, 2014.
to an exploitable side channel, even in complex distributed         [6] Bonsai – Hosted Elasticsearch. https://bonsai.io, 2016.
systems. We developed efficient attacks on two services,            [7] S. Büttcher and C. L. A. Clarke. A security model for full-text
                                                                        file system search in multi-user environments. In Proceedings
GitHub and Orchestrate, and verified exploitability of another          of the 4th Conference on USENIX Conference on File and
service Xen.do. Using our side channel we estimated the time            Storage Technologies - Volume 4, FAST’05, 2005.
and cost required to extract information like phone and credit      [8] A. Cholakian.           Elasticsearch at GitHub.           http:
card numbers from private files stored in these services.               //exploringelasticsearch.com/github interview.html, 2014.
   Our case studies only hint at the scope of affected              [9] Couchbase – NoSQL database. http://www.couchbase.com.
                                                                   [10] Cratedb. https://crate.io.
systems. As mentioned, we also confirmed that following            [11] elastic.co. Updating a whole document. https://www.elastic.
best practice guides for building multi-tenant search on top            co/guide/en/elasticsearch/guide/current/update-doc.html,
of AWS ElasticSearch, AWS CloudSearch, Searchly, bonsai,                2016.
[12] Elasticsearch. Discovering the need for an indexing strategy in   [38] D. A. Osvik, A. Shamir, and E. Tromer. Cache attacks and
     multi-tenant applications. https://www.elastic.co/blog/found-          countermeasures: the case of AES. In Cryptographers” Track
     multi-tenancy, 2015.                                                   at the RSA Conference, pages 1–20. Springer, 2006.
[13] Elasticsearch. Term Filter query. https://www.elastic.co/         [39] A. Parker-Wood, C. Strong, E. L. Miller, and D. D. Long.
     guide/en/elasticsearch/reference/current/query-dsl-filtered-           Security aware partitioning for efficient file system search. In
     query.html, 2016.                                                      2010 IEEE 26th Symposium on Mass Storage Systems and
[14] Elasticsearch. https://www.elastic.co/products/elasticsearch,          Technologies (MSST), pages 1–14. IEEE, 2010.
     2016.                                                             [40] C. Percival. Cache missing for fun and profit, 2005.
[15] W. foundation. Wikipedia Dump download. https://dumps.            [41] PostgreSQL. https://www.postgresql.org.
     wikimedia.org/enwiki/.                                            [42] Lucene’s practical scoring function.         https://www.elastic.
[16] A. Futoransky, D. Saura, and A. Waissbein. The ND2DB                   co/guide/en/elasticsearch/guide/current/practical-scoring-
     attack: Database content extraction using timing attacks on the        function.html.
     indexing algorithms. In WOOT, 2007.                               [43] T. Ristenpart, E. Tromer, H. Shacham, and S. Savage. Hey,
[17] N. Gelernter and A. Herzberg. Cross-site search attacks.               you, get off of my cloud: exploring information leakage in
     In Proceedings of the 22nd ACM SIGSAC Conference on                    third-party compute clouds. In Proceedings of the 16th ACM
     Computer and Communications Security, pages 1394–1405.                 conference on Computer and communications security, pages
     ACM, 2015.                                                             199–212. ACM, 2009.
[18] GitHub. Sensitive data exposure. https://bounty.github.com        [44] Searchify. https://www.searchify.com.
     /classifications/sensitive-data-exposure.html, 2016.              [45] Searchly – Elasticsearch as a service. https://http://www.
[19] GitHub on Elastic.co case study. https://www.elastic.co/use-           searchly.com, 2016.
     cases/github, 2014.                                               [46] A. Singh, M. Srivatsa, and L. Liu. Efficient and secure search
[20] Google.       Google app engine.      https://cloud.google.com         of enterprise file systems. In IEEE International Conference
     /appengine.                                                            on Web Services (ICWS 2007), pages 18–25. IEEE, 2007.
[21] Add-ons - Heroku Elements. https://elements.heroku.com            [47] I. Soboroff. Information retrieval evaluation demo. https://
     /addons#search, 2016.                                                  github.com/isoboroff/trec-demo.
[22] Hibernate commmuity documentation, chapter 10.9: Multi-           [48] Apache Solr. http://lucene.apache.org/solr/, 2016.
     tenancy. https://docs.jboss.org/hibernate/search/5.3/reference/   [49] Swiftype. Customer case studies. https://swiftype.com/custom
     en-US/html/ch10.html#section-multi-tenancy.                            ers, 2016.
[23] M. S. Inci, B. Gülmezoglu, G. I. Apecechea, T. Eisenbarth,       [50] Swiftype - site search and enterprise search. https://swiftype.
     and B. Sunar. Seriously, get off my cloud! cross-vm rsa key            com, 2016.
     recovery in a public cloud. IACR Cryptology ePrint Archive,       [51] V. Varadarajan, Y. Zhang, T. Ristenpart, and M. M. Swift. A
     2015:898, 2015.                                                        placement vulnerability study in multi-tenant public clouds. In
[24] B. Klimt and Y. Yang. The enron corpus: A new dataset                  USENIX Security, pages 913–928, 2015.
     for email classification research. In European Conference on      [52] Vulnerability.ch. Creative commons: Donors data leak. https:
     Machine Learning, pages 217–226. Springer, 2004.                       //vulnerability.ch/tag/github/, 2014.
[25] K. Kluge. Personal communication.                                 [53] Wikipedia. Okapi BM25. https://en.wikipedia.org/wiki/
[26] D. D. Lewis, Y. Yang, T. G. Rose, and F. Li. Rcv1: A new               Okapi BM25.
     benchmark collection for text categorization research. Journal    [54] Wikipedia. Term frequency-inverse document frequency.
     of machine learning research, 5(Apr):361–397, 2004.                    https://en.wikipedia.org/wiki/Tf-idf, 2016.
[27] Lucene. https://lucene.apache.org/, 2016.                         [55] Z. Wu, Z. Xu, and H. Wang. Whispers in the hyper-space:
[28] Lucene Practical Scoring function.         https://www.elastic.        High-speed covert channel attacks in the cloud. In USENIX
     co/guide/en/elasticsearch/guide/current/practical-scoring-             Security symposium, pages 159–173, 2012.
     function.html, 2016.                                              [56] Xendo. Xendo security blog. https://help.xen.do/hc/en-us/
[29] Lucene’s scoring function. http://lucene.apache.org/core/3 5           sections/200689704-Security, 2016.
     0/api/core/org/apache/lucene/search/Similarity.html.              [57] Y. Xu, M. Bailey, F. Jahanian, K. Joshi, M. Hiltunen, and
[30] C. D. Manning, P. Raghavan, and H. Schütze. Introduction              R. Schlichting. An exploration of l2 cache covert channels
     to Information Retrieval. Cambridge University Press, New              in virtualized environments. In Proceedings of the 3rd ACM
     York, NY, USA, 2008.                                                   workshop on Cloud computing security workshop, pages 29–
                                                                            40. ACM, 2011.
[31] E. C. Micheli, G. Margaritis, and S. V. Anastasiadis. Ef-
                                                                       [58] S. Zerr, D. Olmedilla, W. Nejdl, and W. Siberski. Zerber+
     ficient multi-user indexing for secure keyword search. In
                                                                            r: Top-k retrieval from a confidential index. In Proceedings
     EDBT/ICDT Workshops, pages 390–395, 2014.
                                                                            of the 12th International Conference on Extending Database
[32] Microsoft. Multi-tenant data architecture. https://msdn.
                                                                            Technology: Advances in Database Technology, pages 439–
     microsoft.com/en-us/library/aa479086.aspx, 2006.
                                                                            449. ACM, 2009.
[33] How Mingle built its Elasticsearch cluster on AWS.
                                                                       [59] B. Zhang. A new, experimental approach to implement
     https://www.thoughtworks.com/mingle/news/scaling/2015/
                                                                            multi-tenancy with Lucene 4. https://community.jivesoftware.
     01/06/How-Mingle-Built-ElasticSearch-Cluster.html, 2015.
                                                                            com/community/developer/blog/2013/06/24/a-new-experim
[34] Elasticsearch: the definitive guide. https://www.elastic.co/
                                                                            ental-approach-to-implement-multi-tenancy-with-lucene-4.
     guide/en/elasticsearch/guide/current/shared-index.html, 2016.
                                                                       [60] Y. Zhang, A. Juels, M. K. Reiter, and T. Ristenpart. Cross-
[35] MySQL full text search. http://dev.mysql.com/doc/refman/5.             tenant side-channel attacks in PaaS clouds. In Proceedings
     7/en/fulltext-search.html, 2011.                                       of the 2014 ACM SIGSAC Conference on Computer and
[36] Orchestrate.      How we improved elasticsearch indexing.              Communications Security, pages 990–1003. ACM, 2014.
     https://www.ctl.io/developers/blog/post/improved-
     elasticsearch-indexing, 2014.
[37] OriginLab. http://originlab.com/, 2016.
