Pyronia: Intra-Process Access Control for IoT Applications
PPyronia: Intra-Process Access Control for IoT Applications
Marcela S. Melara, David H. Liu, Michael J. Freedman
Princeton University
Abstract
Third-party code plays a critical role in IoT applications,which generate and analyze highly privacy-sensitive data.Unlike traditional desktop and server settings, IoT devicesmostly run a dedicated, single application. As a result,vulnerabilities in third-party libraries within a processpose a much bigger threat than on traditional platforms.We present Pyronia, a fine-grained access control sys-tem for IoT applications written in high-level languages.Pyronia exploits developers’ coarse-grained expectationsabout how imported third-party code operates to restrictaccess to files, devices, and specific network destinations,at the granularity of individual functions . To efficientlyprotect such sensitive OS resources, Pyronia combinesthree techniques: system call interposition, stack inspec-tion, and memory domains. This design avoids the needfor application refactoring, or unintuitive data flow analy-sis, while enforcing the developer’s access policy at runtime. Our Pyronia prototype for Python runs on a customLinux kernel, and incurs moderate performance overheadon unmodified Python applications.
Concerns about data security in the Internet of Things(IoT) have been mounting in the wake of private dataleaks in safety-critical technologies (e.g., [26, 27, 68])and large-scale malware attacks exploiting vulnerable de-vices [12, 22, 56]. These concerns have driven applicationdevelopers to deploy measures that secure data in-transitto cloud platforms [6, 18, 42], or that detect unauthorizedcode on devices [32, 49].However, these safeguards cannot prevent vulnerableor malicious third-party libraries within
IoT applicationsfrom leaking sensitive information. Once a developerimports a vulnerable library, it runs with the application’sprivileges and has full access to the application’s resources(e.g, files, devices and network interfaces). For example,a facial recognition library with a vulnerability in the recognize_face() function could allow an attacker to stealthe application’s private authentication token by uploadthis file to an unauthorized remote server. Meanwhile, theapplication developer only expected recognize_face() toaccess the image file face.jpg .This is an especially serious problem for IoT becausemost devices run a single, dedicated application that hasaccess to all sensors on the device. In other words, third-party code does not run with least privilege [48].Now, these threats are not IoT-specific. A large body ofprior research has sought to restrict untrusted third-partycode in desktop, mobile, and cloud applications (e.g., [10,11,14,19,21,24,36,41,54,55,59,65–67]). However, thesetraditional compute settings face more complex securitychallenges. Mobile devices, desktops, and even IoT hubs,run multiple mutually distrusting applications; further,desktops and cloud servers run in multi-user/multi-tenantsettings. All of these settings require isolation betweenthe different applications and principals.In this paper, we examine the following question (§2):Are traditional approaches suitable for protecting IoTdevice applications against untrusted third-party code?Given the rapid proliferation of IoT devices and the highsensitivity of the data they handle, it is crucial to gain anunderstanding of the IoT-specific security challenges thatdevelopers face, in order to guide the design of systemsthat effectively enforce least privilege in this setting.We conduct, to the best of our knowledge, the first in-depth analysis of third-party code usage in IoT deviceapplications. Specifically, we characterize the IoT librarylandscape, and identify key risks to IoT applications (§3).Informed by our findings, we propose Pyronia, an ac-cess control system for untrusted third-party code in IoTapplications written in high-level languages.In Pyronia, we retain the goal of controlling when anapplication may obtain data from files and devices, andto which remote network destinations an application may Pyronia being a gatekeeper for third-party libraries, is named afterthe genus of butterflies known as gatekeeper butterflies. a r X i v : . [ c s . O S ] N ov xport data. Pyronia enforces a central policy that speci-fies rules for directly imported library functions and thespecific OS resources they may access. For example, toensure that a sensitive image face.jpg is only accessibleby the recognize_face() function, the developer specifiesa read rule for the face.jpg in her policy. Pyronia thenblocks all attempts by any other library functions to ac-cess the image file, as well as attempts by this function toaccess other sensitive resources. Thus, developers neednot reason about third-party dependencies that may be un-familar to them, and application and library source codecan remain unmodified.To enforce such function-granular access control, Py-ronia leverages the following three techniques. ) System call interposition (§5.1) guarantees that ac-cess to OS resources by all application componentscan be controlled, even for native libraries integratedvia a high-level native interface such as the JavaJNI or the Python C API. However, system call in-terposition has traditionally only been realized asa process-level technique, and thus cannot handleintra-process access checks. ) Stack inspection (§5.1) allows Pyronia to identifyall library functions involved in the call chain thatled to a given system call. Thus, Pyronia leveragesthe language runtime call stack to determine whetherto grant access to a requested resource based on thefull provenance of the intercepted system call. ) Memory domains (§5.2) are isolated compartmentswithin a process address space, each with its ownaccess policy. Pyronia enforces boundaries betweencompartments via replicated page tables, protectingthe language runtime call stack against tampering bynative code in the same address space.Pyronia targets popular high-level IoT programminglanguages like Java or Python [18] precisely for their abil-ity to dynamically provide fine-grained execution contextinformation. We implement Pyronia on Linux for Python(§6), although we believe our approach can be applied toother high-level languages. Our prototype acts as a drop-in replacement for the CPython runtime, and includes acustom Linux kernel with support for memory domains.Our function-granular MAC component is a kernel mod-ule built on top of AppArmor [8].We evaluated Pyronia’s security and performance withthree open-source IoT applications. Our security evalua-tion (§7)shows that Pyronia mitigates reported and hypo-thetical OS resource-based vulnerabilities. We also findthat Pyronia incurs moderate performance slowdowns,with a maximum operating overhead of 3x, and modestmemory overheads with an average of 38.6% additionalmemory usage for the entire application.
Prior research on restricting untrusted third-party code andenforcing least privilege in traditional compute settingshas used two main approaches.
Process isolation partitions a monolithic application intomultiple processes and controls their permissions indi-vidually (e.g., [10, 11, 21, 54, 54, 59, 64]). However, pro-cess isolation imposes significant development and run-time overheads. Developers may have difficulty cleanlyseparating components into processes. In addition, inter-process communication is much more expensive thancalling library functions within the same address space.These issues indicate that the process abstraction is toocoarse-grained for the efficient isolation of intra-processcomponents in IoT applications. More recent work in thisarea introduces OS-level abstractions to create privatememory compartments within a single process addressspace [13, 30, 39, 61]. However, these proposals lack built-in access control for OS resources, and still require majordeveloper effort for deployment in high-level applications.Thus, these approaches are insufficient to limit third-party libraries’ access to unauthorized IoT device re-sources. Additionally, given the rapid deployment cyclesof IoT applications, developers are unlikely to prioritizesecurity [3, 4, 9], and spend the time and effort necessaryto refactor their applications. Thus, one key design goalof Pyronia is to support unmodified applications whileenforcing least privilege within a single process.
Information Flow Control attaches policy labels to in-dividual sensitive data objects and track how they flowthrough the system. IFC systems can be divided into twobroad categories. OS-level IFC (e.g., [19, 36, 66, 67])tracks primitives like files or network sockets, whilelanguage-level IFC systems (e.g., [14, 24, 41, 55, 65]) arecapable of controlling access to sensitive data at granular-ities as fine as individual bytes.Yet, much like process isolation, IFC systems introducea considerable amount of cost and complexity: Developersmust manually refactor their source code to specify policylabels around specific sensitive data sources and sinks.Additionally, propagating new labels at run time incurssignificant memory and performance overheads.Since third-party code may contain unexpected vulner-abilities, or a long list of dependencies, we cannot expectIoT developers to be able to perform extensive data flowanalysis a priori to declare a data access policy that mini-mizes data leaks. Thus, access control for IoT should notrequire unintuitive policy specification.
IoT-specific Access Control.
A number of recent worksin the IoT space [29, 33, 45, 50, 58] propose access con-trol systems to enable developers and end-users to defineand enforce more suitable data access policies based on2able 1: Analysis of direct imports and number of depen-dency levels in a set of 85 Python IoT applications and inthe top 50 third-party libraries imported by these applica-tions. Unless noted otherwise, results of per-applicationanalyses are shown. min median mean max applications from accessing sensitive device functionali-ties and resources by executing different IoT device func-tions in separate Linux containers. However, FACT doesnot protect these resources against untrusted third-partycode running as part of the isolated device functionali-ties, as Pyronia would. FlowFence [21] shares the samegoals as Pyronia, but still relies on process isolation forin-application privilege separation, and does not supportunmodified applications.
To design Pyronia, we conducted an in-depth study of 85open-source IoT applications written in Python and theirlibraries, as well as a brief analysis of reported vulnerablePython libraries. Our analyses focus on Python as it is apopular IoT development language [18].
To better understand how third-party libraries influenceIoT application design today, we analyzed 85 open-sourceIoT applications written in Python. We obtained these ap-plications primarily from popular DIY web platforms suchas instructables.com and hackster.io ; our searchfocused on three broad categories of applications—visual,audio, and environment sensing—which we believe arerepresentative of today’s most privacy-sensitive IoT usecases. The four key takeaways of our analysis are:
1. The vast majority of IoT applications import third-party libraries.
All but one of our sampled applications(98.8%) import at least one third-party library, with amean of about 6 direct third-party imports per application.The maximum number of direct imports we found in asingle application was 186 (see Table 1). This demon-strates that attacks from imported libraries within an ap-plication’s process are much more realistic due to thesingle-purpose nature of most IoT devices, as opposed to Table 2: Characteristics of the top 50 IoT Python libraries,including libs exhibiting multiple characteristics.
Library feature % of top 50 libs
Written in Python 12.0%Have Native Deps 82.0%Run external binaries 40.0%Use ctypes 40.0%threats across process boundaries as seen in traditionaldesktop and server settings.
2. The third-party library landscape is very diverse.
Overall we found 331 distinct third-party Python librariesamong the 418 total imports in our sampled set of applica-tions, despite heavily sampling applications targeting theRaspberry Pi single-chip computer (a very popular devel-opment platform for IoT). Thus, providing intra-processaccess control for IoT device applications requires anapplication- and library-agnostic approach.
3. Libraries rely predominantly on native code.
Wefind that 82% of the top 50 libraries in our analysis in-clude a component written in C/C++, among which weidentified 68 distinct native dependencies. Additionally,a large portion of libraries load a native shared libraryvia the ctypes
Python foreign function interface, or ex-ecute external native binaries (including a Python sub-process). These results reveal how exposed applicationsand the Python runtime are to threats from vulnerable ormalicious native code, and underscore the importance ofintra-process memory isolation to protect security-criticaldata against tampering or leaks native code.
4. Dependencies are nested dozens of levels in IoTapplications.
Finally, we analyzed the longest chain ofnested libraries for each application and top-50 library inour sample, and find that across the 85 sampled applica-tions, the median number of nesting levels is 25, whilethe median library has 27 levels of nested dependencies(see Table 1). These numbers indicate the complexity ofsingle applications and libraries, and highlight why de-velopers need more intuitive fine-grained access controlthat does not require separating each library into its ownprocess, or identifying the sensitive data flows within asingle application.
Our survey of reported Python library vulnerabilitiescovers 123 reports created between January 2012 andMarch 2019 in the Common Vulnerabilities and Expo-sures (CVE) List [57]. We identify 78 distinct vulnerablePython libraries, and 9 main attack classes (see Table 3) . For a full list of the CVE reports included in our analysis, seeAppendix A.
Attack class
Arbitrary code execution 28 24 python-gnupg (4)MITM 19 14 urllib* (3)Web attack 18 12 urllib* (4)Denial of service 17 12 Django (3)Direct data leak 12 10 requests (3)Weak crypto 11 10 PyCrypto (2)Authentication bypass 9 6 python-keystoneclient (3)Symlink attack 6 4 Pillow (2)Replay/data spoofing 3 3 python-oauth2We include shell injections under arbitrary code execu-tion, and the majority of web attacks comprise cross-sitescripting and CR/LF injection attacks. We classify vulner-abilities arising from accidental data exposure as directdata leaks. Authentication bypass vulnerabilities arisefrom system misconfiguration or credential verificationbugs. A symlink attack allows an adversary to gain accessto a resource via a specially crafted symbolic link.While direct data leaks account for only about 10%of the reported vulnerabilities, we emphasize that mostother attack classes, most notably arbitrary code execution,man-in-the-middle (MITM), and authentication bypass,lead to information leakage as well. Our analysis alsodemonstrates the diversity of vulnerable libraries, witha small number of libraries having a handful of reportsin each attack class. The two Python packages with themost overall CVE reports are the widely used Django webframework and urllib* HTTP library family, each witheight reports. These findings underscore the degree towhich IoT application developers are exposed to potentialthreats by importing third-party code.In addition, we find that exploiting dynamic languagefeatures is fairly straightforward. In our lab setting, webuilt a Python module and a native library that use in-trospection or monkey patching [53] to replace functionpointers at run time with malicious functions, to leak dataat import time, and to perform various modifications tothe contents of Python runtime’s stack frames.While we have not identified such attacks in the wild,our experiments demonstrate that these dynamic featuresand open APIs place too much trust in third-party librarydevelopers, and can be misused for nefarious purposes.Thus, both dynamic language features and the capabili-ties of native libraries pose threats to the integrity of theapplication itself and the privacy of user data.
We aim to provide intra-process access control, whichallows developers to prevent third-party code included in their IoT applications from leaking data. In particular, Py-ronia protects sensitive OS resources, and restricts accessto remote network destinations.
We assume that IoT device vendor, who usually also de-velop the device software, are trusted. As such, we alsotrust the underlying device hardware, the operating sys-tem, and the language runtime executing the IoT appli-cation. Yet, imported third-party code poses a risk to de-velopers: library code is rarely inspected or readily ac-cessible, so bugs or dynamic language features that leaksensitive data may go unnoticed. We do, however, assumethat application developers do not intentionally includesuch vulnerable or malicious third-party code.While data leak vulnerabilities take many forms, Pyro-nia targets third-party code that aims to access arbitrarysensitive files or devices, or exfiltrate sensitive data to arbi-trary remote network destinations. Pyronia does not seekto prevent any control flow (e.g., ROP [47]) or side chan-nel attacks (e.g., Spectre/Meltdown [35, 38], or physicalvectors [23]). ROP defenses (e.g., [15, 16, 31, 63]) may beused in a complementary fashion. Pyronia also does notprevent network-based attacks such as man-in-the-middleor denial-of-service attacks.
Pyronia provides three main security properties.
P1: Least privilege.
A third-party library function mayonly access those OS resources (i.e., files, devices, net-work) that are necessary to provide the expected func-tionality. Attempts by a third-party function to accessresources that are not relevant to its functionality must beblocked. Pyronia conservatively enforces a default-denypolicy, requiring developers to explicitly grant specificlibrary functions access to OS resources.
P2: No confused deputies.
All access control decisionsare made based on the full provenance of the access re-quest. This prevents confused deputy attacks [28] in which4n underprivileged library function attempts to gain ac-cess to a protected resource via another function that doeshave sufficient privileges. To detect such attempts to by-pass access control checks, Pyronia checks all functionsinvolved in a request for an OS resource.
P3: Verified network destinations.
A third-party li-brary function may only transmit data to remote net-work destinations (e.g., cloud servers or other IoT devices)whitelisted by the developer. Thus, a third-party librarycannot leak legitimately collected data to an untrustedremote server or device. Pyronia prevents such data exfil-tration by intercepting all outgoing network connections.
Non-goals.
While Pyronia automates access control atthe level of in-application components, our design doesnot seek to provide automated execution isolation of thesecomponents (e.g., [10, 11, 59]). We also do not guaran-tee the correctness of the sensitive data they output. Au-tomated code compartmentalization is complementaryto our approach, and could be added to Pyronia to al-low developers to prevent certain cross-library functioncalls. Ensuring the correctness of sensitive outputs, onthe other hand, could provide additional data leak pro-tection. However, formally verifying the functionality ofuntrusted code is beyond the scope of Pyronia, and couldbe performed separately prior to application deployment.
Pyronia enforces intra-process least privilege without par-titioning an application into multiple processes, or propa-gating data flow labels.Developers understand the purpose of imported li-braries and can provide high-level descriptions of theirexpected data access behaviors. Pyronia thus relies ondevelopers to specify all access rules in a single, cen-tral policy file. At run time, Pyronia loads this file intoan application-specific access control list (ACL) that con-tains an entry for each developer-specified library functionand its associated data access privileges. Pyronia imposes default-deny access control semantics, meaning that athird-party library function may only access those files,devices, and whitelisted remote network destinations.To enforce this policy securely, Pyronia requires sup-port both in the language runtime and from the OS. Fig-ure 1 provides an overview of the Pyronia system archi-tecture, and shows the main steps involved in a resourceaccess request (see §5.1).
At first glance, performing access control at library func-tion granularity in the language runtime may seem suffi-cient. The runtime can directly inspect its function callstack when a specific third-party library function uses thelanguage’s high-level interface to access a file or device. K e r n e l U s e r s p a c e Runtime coreMain application Access Control ModuleMemory Domain Manager Third-party librariesAccess Policy
Application/dev/video0 eth0 /home/foo/cert.pem … Kernel
Figure 1: Overview of Pyronia, which enforces function-granular resource access policies via runtime and kernelmodifications (striped boxes). New features are repre-sented by gray boxes. The arrows show the componentsinvolved in an access request to a file such as a certificate.If the a function with insufficient permissions attempts toaccess a resource, the runtime can block the request andthrow an error to notify the application.However, language runtimes also provide an interfaceto native code, such as Java’s JNI or Python’s C API;indeed, our analysis in §3.1 shows that use of this interfacein Python is very common-place. This ability to includenative code in otherwise memory-safe languages exposesapplications to vulnerabilities in native code: as this coderuns outside the purview of the language runtime, thiscode could bypass any runtime-level access control viadirect system calls.Pyronia addresses these issues via system call inter-position (e.g., [25, 34, 44]) enhanced with function callprovenance. Many mandatory access control (MAC) sys-tems in deployment use system call interposition (e.g.,SELinux [51], AppArmor [8], Windows MIC [40]). Theirlimitation, however, is that the security policy is only en-forced at the process level. Pyronia achieves intra-processpolicy enforcement by incorporating runtime call stackinspection (e.g., [17, 52, 60, 62]) to obtain the full prove-nance of the system call.With these two techniques, Pyronia provides function-granular
MAC to enforce least privilege ( P1 ). As weshow in Fig. 1, when the application attempts to accessa sensitive OS resource (e.g., an SSL certificate), the Py-ronia Access Control module in the kernel intercepts theassociated system call (step 1). This kernel module thensends a request to the language runtime via a trusted stackinspector thread, which pauses the runtime. After collect-ing the interpreter’s function call stack in its current state,the stack inspector returns the stack to the kernel (step 2).5 lgorithm 1 Call stack inspection procedure I NSPECT S TACK ( callStack , reqAccess ) rule ← G ET A CL R ULE ( callStack . f uncName ) if rule == nil then return false grantAccess ← H AS P RIVS ( rule , reqAccess ) while grantAccess == true do callStack ← callStack . Next rule ← G ET A CL R ULE ( callStack . f uncName ) if rule == nil then continue grantAccess ← H AS P RIVS ( rule , reqAccess ) return grantAccess The Access Control module maintains the ACL for thedeveloper-supplied policy. To determine whether to grantaccess to the requested OS resource, the module inspectsthe call stack to verify the provenance of the system call.Only if all developer-specified functions identified in thecall stack have sufficient privileges may the applicationobtain data from the requested resource (step 3). That is,to determine the application’s access permissions to therequested resource, Pyronia dynamically computes theintersection of the privileges of each function in the callstack using algorithm 1. This algorithm prevents confuseddeputies ( P2 ), much as in [17, 20, 52]. Untrusted native libraries reside in the runtime’s addressspace, giving them unfettered access to the call stack’smemory region. A malicious native library may tamperwith the runtime call stack in an attempt to bypass Pyro-nia’s function-level MAC.This challenge is not unique to Pyronia; indeed, priorwork in the mobile space [52, 62] recognized the needto protect the Dalvik call stack against native third-partycode in the trusted host app’s address space. To addressthis issue, these proposals either rely on special hardwaresupport [52] to separate the runtime address space fromthe native library address space, or they forgo memoryprotection altogether [62].Pyronia, in contrast, aims to provide a more generallyapplicable solution to this issue, since IoT software runson a very diverse range of hardware platforms. We over-come this challenge with page table replication, a tech-nique that enables us to create strongly isolated memoryregions, or memory domains , within a process’ addressspace. Prior work in this space (e.g., [30, 39, 61]) has in-troduced new primitives for intra-process execution com-partments. Our design for Pyronia’s memory domains, onthe other hand, focuses on data isolation.To protect the language runtime call stack for a broadrange of applications, memory domains in Pyronia meettwo requirements: (1) the size of a domain must be flexi-ble, and (2) the access privileges must be dynamic. The first requirement is important for ensuring that Pyroniacan support applications that make an arbitrary numberof nested function calls. The second requirement allowsPyronia to restrict an application’s access to a memorydomain at run time based on the currently executing code(e.g., interpreter versus third-party library), while still en-abling data sharing between application components.The Pyronia Memory Domain Manager in the kernel(see Fig. 1) maintains a per-process table of domain-protected memory pages, and replicates the correspondingpage table entries (PTEs); each replicated entry is associ-ated with a distinct domain access policy. Policies are en-forced at the granularity of individual native threads, andspecify the access permissions for any thread launchedunder a given policy. Mapping thread contexts to a repli-cated PTE thus allows Pyronia to transparently changepolicy contexts during a context switch.Upon a memory access, the Pyronia kernel performs allregular memory access checks. If the requested addressis domain-protected, the Domain Manager additionallyverifies that the loaded thread context has sufficient per-missions to access the requested memory domain basedon the thread’s policy. Any attempt by an application toaccess unauthorized domain-protected memory results ina memory fault.To ensure the integrity of the runtime call stack, thePyronia runtime allocates all call stack data into a mem-ory domain called the stack domain . Pyronia currentlydefines two access policies to this domain: The runtime’spolicy, which only allows access to the call stack duringstack frame creation and deletion, and the stack inspec-tor’s policy, which allows access to the call stack whileresponding to an upcall from the Access Control module.Pyronia loads the appropriate page table during contextswitches between the main runtime thread and the stackinspector thread automatically.However, to enforce the runtime’s policy, Pyronia re-quires elevated access privileges to the stack domain dur-ing stack frame creation and deletion. Thus, the runtimeinvokes the Domain Manager to temporarily adjust themain runtime thread’s policy and corresponding PTE ac-cess bits during these operations. Otherwise, the languageruntime still provides read access to the stack domain toallow code to make use of shared functions, but prohibits write access to protect this security-critical metadata.We note that while our memory domain mechanism cansupport multi-threading beyond Pyronia’s threads, Pyro-nia currently only targets single-threaded applications. Aswe describe in §9, we leave this enhancement as future re-search due to the small fraction of IoT applications (10%per our analysis in §3.1) that spawn multiple threads.6 .3 Network Destination Verification
Since all IoT applications communicate with remote ser-vices, Pyronia must ensure that authorized third-party li-brary functions may transmit data only to whitelisted des-tinations. That is, when an application attempts to exportdata via the network, Pyronia’s Access Control moduleintercepts all outward-facing socket system calls (e.g., bind() and connect() ) for all socket types, i.e., TCP, UDP,and raw. As with other OS resource accesses, Pyroniathen requests and inspects the runtime call stack.However, network access privileges alone do not im-mediately allow a third-party function to transmit data.Pyronia also verifies the remote endpoint for the requestedsocket. Thus, only if the address of the requested destina-tion is whitelisted for the given third-party function, doesPyronia grant access to the requested socket ( P3 ). We find in §3.1 that a large fraction of applications (46%)and libraries (40%) run external binaries (including newlanguage runtime instances) in subprocesses. This ap-plication characteristic poses a challenge to Pyronia’sfunction-granular MAC since child processes run in anindependent context, losing important provenance infor-mation for system calls. Pyronia addresses this issue byensuring the continued protection of child processes. Thus,upon a fork() system call, the Pyronia kernel propagatesthe parent’s process- and function-level ACLs, as well asthe replicated page tables, to the child process.However, the Access Control module does not requestthe current call stack from the language runtime at a fork() for three reasons. First, the parent process maybe a native binary that is Pyronia-unaware. Second, sinceapplication developers may be unaware of subprocessesspawned by third-party code, using the call stack to blockexternal binaries may break the functionality of the over-all application. Third, using the parent runtime’s call stackfor access control decisions in its children may also un-duly restrict the functionality of the whole application.Thus, Pyronia requires language runtime sub-instances toregister themselves with the Pyronia kernel to transpar-ently enforce the developer’s function-level access policy,and to continue managing the stack domain in the child’saddress space. In the case of a native child process, Pyro-nia does not provide intra-process access control, but stillenforces the developer’s policy at process granularity.
To demonstrate how Pyronia interacts with existing open-source IoT applications, we implemented the Pyronia ker-nel based on Linux Kernel version 4.8.0+, and the Pyronia
Algorithm 2
Pyronia in-kernel access control check procedure C HECK A CCESS ( acl , reqAccess ) grantAccess ← true isDe f ault ← I S D EFAULT A CCESS ( acl . resource ) if isDe f ault == true then return grantAccess recvHash ← R ECV S TACK H ASH ( acl . resource ) hashLog ← S TACK H ASH L OG ( acl . resource ) if recvHash (cid:54) = null AND hashLog . C ONTAINS ( recvHash ) == true then return grantAccess callStack ← G ET S TACK F ROM R UNTIME () return I NSPECT S TACK ( callStack , reqAccess ) runtime as a modified version of Python 2.7.14. We havereleased all components of our prototype on Github. Application developers in Pyronia specify all function-level data access rules for file system resources, and net-work destinations in a single policy file. Table 4 detailsPyronia’s policy rule specification format. In the case ofnetwork access rules specifically, our Pyronia prototypeallows developers to specify IP address prefixes, as thespecific address of a remote destination in a cloud servicemay not be known a priori.Nevertheless, a challenge that arises from having lim-ited knowledge about a library’s implementation is thatit may legitimately require access to other resources thatare unexpected. For example, a library function may needaccess to system fonts, or may write an intermediate re-sult to the file system. Similarly, developers are unlikelyto have a good sense of the system libraries or other filesystem locations a language runtime requires to operateproperly. Thus, Pyronia’s default-deny access control se-mantics alone are too restrictive and may lead to a numberof false negatives.To maintain the functionality of the application andthe language runtime, and reduce the number of falsenegatives, our prototype supports a special default accessrule declaration, which grants application-wide access toa specified resource. While default access rules bypassPyronia’s function-level access control, they still providea baseline level of security as Pyronia also applies default-deny access control semantics at the process-level.
Access Control module.
Our Access Control Module ex-tends the AppArmor [8] kernel module version 2.11.0.AppArmor interposes on all system calls enforcing aprocess-level access policy. Thus, as in vanilla AppArmor,Pyronia denies access to a requested resource if the pro-cess does not have sufficient privileges. To add support for https://github.com/pyroniasys r , and read-write w . Rule type Format
FS resource
Network destination
Pyronia’s stack inspection, we extend the process-levelAppArmor policy data structure with a function-levelACL. This ACL is populated at application initializa-tion (see §6.3), and contains an entry for each developer-specified library function. In addition, the Access Controlmodule registers child processes of the main Pyronia pro-cess, propagating the application’s function-level ACL toall child processes.In an early version of our prototype, Pyronia wouldinspect the runtime call stack on every intercepted sys-tem call. However, given that IoT applications are builtto continuously gather and transmit data in an infiniteloop, we improve the performance of Pyronia’s function-level MAC (by roughly 3x) by avoiding expensive kernel-userspace context switches for already-verified call stacks.Thus, we implement a stack logging mechanism, whichstores and verifies the SHA256 hash for up to 16 func-tions authorized to access a given resource, as part of thefunction-level access control checks, outlined in Alg. 2.The Access Control module first checks the defaultsACL for the application (line 3). If the requested resourceis covered by a default rule, Pyronia grants access withoutinspecting the call stack. Otherwise, the Access Controlmodule checks whether the the Python runtime has in-cluded a call stack hash along with the system call (line5, more details in §6.3). If kernel received a call stackhash, and the received hash matches any of the hashes inthe call stack log for the requested resource (line 8), themodule grants access.Otherwise, our prototype resorts to the full stack in-spection mechanism (lines 9 and 10, see Alg. 1). Once thecall stack has been inspected, and if the application hassufficient privileges to access the requested resource, theAccess Control module logs the SHA256 hash of the call-stack in the resource’s ACL. To support this mechanism,we made minor, backwards-compatible modifications tothe the open() and connect() system call code in orderto to parse the received call stack hash, if any, and store itfor later verification during the MAC checks.
Memory Domain manager.
For Pyronia’s page tablereplication, we modify the SMV [30] kernel module, amemory isolation proposal for enforcing per-page accesscontrol policies via thread-local page tables. Our Mem-ory Domain manager leverages the SMV kernel API formaintaining a list of protected 4-kB domain pages andtheir corresponding access policies for the main runtime and stack inspector threads. Upon a fork() , the kernelcopies the replicated page tables in the child process.
Netlink sockets.
To enable communication between thekernel and the runtime in userspace, Pyronia uses ageneric Netlink socket in the Domain manager, and onein the Access Control module. Netlink sockets offer twoadvantages: (1) they allow bi-directional communicationbetween kernelspace and userspace obviating the needto implement additional ioctls() or system calls, and (2)userspace applications can use the POSIX socket API forNetlink communication.
To allow developers to run completely unmodified appli-cations, the Pyronia runtime acts as a drop-in replacementfor Python. We integrate our Pyronia library, which pro-vides an API for loading the developer’s access policy,and for managing the stack memory domain.
Policy initialization.
The runtime core uses our policyparser API to read the developer’s policy file during inter-preter initialization. All parsed OS resource and networkaccess rules are sent to the Access Control module in thekernel. Loading the policy before the runtime has loadedany third-party code has the advantage of preventing anadversary from “front-running” the interpreter by initial-izing the application’s in-kernel Pyronia ACL before thelegitimate developer-supplied policy can be loaded. Forthis reason, the Pyronia runtime also spawns the stackinspector thread and registers it with the kernel during theinitialization phase.
Stack domain allocation.
As the userspace Pyroniamemory domain management API acts as a drop-in re-placement for malloc, we instrumented the Python stackframe manager to allocate new runtime call stack framesin the stack domain . Because write access to the stackdomain is disabled by default, the runtime temporarilyobtains write access to this domain during frame creationand deletion operations.
Child processes.
Our Pyronia runtime provides continu-ous protection for child processes spawned via standardPython APIs (e.g., os.system() ). As forking preserves theparent process’ memory in the child, Pyronia subpro-cesses automatically inherit the parent’s memory domainlayout as well as the Pyronia interpreter metadata, includ-ing currently writable memory domains. Thus, Pyronia8nitialization in child processes only requires spawningthe child’s stack inspector thread, and resetting the appli-cation’s access permissions to the stack domain disablingwrite access to this domain. This reset is necessary toensure that the child cannot access any runtime stackframes in its own address space that the parent processhad marked as writable at the time of forking.
Stack logging.
As described in §6.2, we implement astack logging mechanism to reduce the overhead of ker-nel upcalls for runtime call stack requests. When the lan-guage runtime requests a resource for the first time, thePyronia performs the full stack inspection mechanism.If the kernel grants access to the requested resource, thePyronia runtime logs the resource as authorized. Then, insubsequent system calls, our prototype first checks thislog; if the requested resource has been logged, the runtimepreemptively collects its current call stack before makingthe system call, computes the SHA256 hash, and embedsthis hash into the input to the upcoming syscall.To enable this optimization, we created system call-specific wrappers (via LD_PRELOAD) for various vari-ants of open() and connect() . These wrappers per-form the preemptive call stack collection, hash serializa-tion, and authorized OS resource logging. These wrapperfunctions are backwards-compatible, and do not affectfunction-level policy specification.
Garbage collection.
Object reference counting used forPython’s garbage collection poses a challenge to protect-ing the stack domain without breaking the functionality ofthe application. Specifically, we found that Python incre-ments or decrements several objects’ reference counts, in-cluding those of stack frames, for practically every Pythoninstruction and internal operation.To address this issue, we temporarily elevate the in-terpreter’s permissions to the stack domain around thoseblocks of the Python runtime code that operate on domain-protected data. Yet, simply granting write access to theentire stack domain is inefficient, since it may cover hun-dreds of pages, each of whose page table entries wouldneed to be modified (requiring TLB flushes at high rates).We optimize these frequent domain access adjustmentsby tracking the addresses of stack domain pages in the Py-ronia runtime, and only modifying the access privileges toa specific page when needed. One exception to this is fornew stack frame allocations: since the runtime is creatinga new buffer with an undetermined memory address, ourprototype enables write access to all domain pages withfree memory chunks.
To examine the effectiveness of Pyronia’s policies andprotections in real applications, we conduct three in-depth Table 5: Summary of case study applications.
App imports Highlights twitterPhoto tweepy integrated OAuth alexa json data marshallingmemcache raw socketsre regex parsingrequests HTTP API plant_watering paho-mqtt MQTT, binary execssl crypto, native depscase studies of Python applications that specifically cap-ture a range of common IoT use cases, and import a varietyof Python libraries. Our goal is to answer the followingquestions about the usability and security of Pyronia: §7.2
How difficult is it to write function-level access poli-cies for Pyronia? §7.3
What reported Python library vulnerability classescan Pyronia mitigate? §7.4
What effect do dynamic language features of Pythonhave on Pyronia’s protections?
We evaluate three open-source Python IoT applicationsthat represent the main categories of applications we stud-ied: visual, audio, and environmental sensing. Each ofthese applications communicates with a cloud service fordata processing or storage, which required that we regis-ter an account to obtain authentication credentials. Theimported libraries in our study implement a broad rangeof common IoT functionalities (see Table 5). Specifically,our goal is to study how Pyronia operates for common IoTauthentication mechanisms, data processing techniques,and communication protocols.Through manual inspection of the source code of eachcase study, we found four distinct direct third-party im-ports, and three standard libraries. While small in number,these direct imports are among top 50 third-party importsin our analysis in §3.1. twitterPhoto takes an image from a connected cameraevery 15 minutes, and sends the picture along with a shortmessage to a specified Twitter account. Before sendingthe tweet, the application authenticates itself to Twittervia OAuth. The tweepy library is used both to authenticatethe app and upload the message. alexa provides an open-source Python implementationof an Amazon Echo smart speaker. This applicationrecords audio via a microphone while a button is pressed,and sends the recorded audio (along with authenticationcredentials) to the Alexa Voice Service (AVS) [7] for pro-cessing. The AVS sends an audio response, if the recordeddata is one of the commands recognized by the service,9or the alexa application to play back. Otherwise, theAVS responds with an empty ACK message. The python-memcache library is used to cache the app’s AVS accesstoken, and the requests library for communicating withthe AVS via HTTP. This app also uses the json libraryto format all messages exchanged with AVS, and the relibrary to parse out any audio file contained in the AVSresponse. To facilitate our security and performance tests,we removed the button press for audio recording, andinstead open a pre-recorded audio file. plant_watering records moisture sensor readings oncea minute, and sends them to the Amazon AWS IoT [5]service via MQTT [2], a widely used IoT communica-tion protocol. MQTT also handles client authenticationwith the AWS IoT service via TLS. We replaced sensorreadings with a randomly generated value to facilitatetesting, and replaced the original MQTT library with onethat supports single-threaded network communications.
To understand whether Pyronia’s policy specificationplaces an undue burden on developers, we analyzed thepolicy specification process for our three case studies.As we describe in §6, one challenge to specifying com-prehensive rules for a MAC system that enforces default-deny semantics is reducing the number of false negatives.In running our case studies, we found that the vast major-ity of false negatives would arise primarily due to Python’sinternal library loading and DNS resolution processes.To examine this challenge, we ran each case study ap-plication, in Pyronia under AppArmor in complain mode:we identified a total of 42 common files that need to beread-accessible, plus 4 network protocols, for the Pythoninterpreter to run unimpeded, and for the applications toconnect to remote network destinations.In addition, each application required explicit access toits parent directory as well as all imported Python mod-ules contained within, which corresponds to up to 6 ad-ditional access rules for the alexa application. Since wecannot expect developers to manually specify around 50access rules needed by their application by default, wedeveloped a policy generation tool that creates an accesspolicy template pre-populated with rules for the 46 com-mon files and network protocols. To further ease policyspecification, our policy generation tool lists all files inthe application’s parent directory and adds rules for allidentified files. Developers may then manually inspect thetemplate and modify any rules that are function-specific.The majority of the manually added access rules forall three applications are multiple network destinationrules for the same library function. Pyronia does not cur-rently support domain name-based access rules as thisfeature requires that all domain names be resolved a priori for Pyronia’s IP-address based network destination ver-ification. Nonetheless, our case studies require no morethan 11 function-level network destination rules in the plant_watering case.
To understand how effective Pyronia’s protections areagainst security vulnerabilities and exploits, we study Py-ronia’s ability to mitigate specific instances of reportedPython library vulnerabilities (recall §3.2). We emphasizethat all of our analyzed vulnerabilities could affect any
IoT use case, so our choice for testing a particular vulner-ability in a specific application does not reflect prevalenceof a vulnerability class in that IoT use case.Since most of the reported vulnerabilities do not affectthe libraries in our case studies, we replicate all analyzedvulnerabilities in a specially crafted adversarial library tar-geting our case studies. We then call individual functionsin our library from our case study applications.We place the 9 reported attack classes into three broadcategories: (1) successfully mitigated vulnerabilities, (2)case-dependent for vulnerabilities that Pyronia may miti-gate in some instances, and (3) beyond scope for attacksthat fall outside Pyronia’s threat model.
Direct data leaks.
We analyze three distinct instances ofOS resource-based data leaks, in which code with insuffi-cient privileges attempts to gain access to a sensitive OSresource. To this end, we craft two adversarial functions,which upload an SSH private key instead of the authorizedphoto file using the legitimate tweepy library call, andwhich upload the authorized photo to an unauthorized re-mote server, respectively. In addition, we also replicate thedata leak bug reported in CVE-2019-9948 [1], in whichthe Python urllib HTTP library exposes an unsafe APIthat allows arbitrary local file opens.We test these vulnerabilities using the twitterPhoto app, and find that Pyronia can successfully mitigate theseproblems. However, we classify direct data leaks mitiga-tion as case-dependent because several reported data leakvulnerabilities arise due to in-memory data exposures. Incontrast, Pyronia currently only ensures the protection ofthe runtime call stack memory, but does not isolate sensi-tive application-level in-memory data objects, or protectagainst control-flow attacks.
Symlink attacks.
A small number of reported vulnera-bilities in Python libraries comprises symlink attacks, inwhich an adversary attempts to access an unauthorizedfile via a specially crafted symbolic link. We analyze thisattack by crafting an adversarial function that attemptsto open plant_watering ’s private key through a sym-link in the \tmp directory. Since our prototype follows allaccessed symbolic links to their source, Pyronia detects10he attempt to access an unauthorized file successfullymitigating this type of attack.
Arbitrary code execution.
A number of reported Pythonlibrary vulnerabilities pertain to shell injection made pos-sible due to unsanitized input. To examine this attackclass, we crafted an adversarial library function that at-tempts to directly exec a shell command as part of the plant_watering moisture sensor reading (i.e., randomnumber generator) call.Pyronia successfully mitigates the exec as the implicitfile open is blocked. Thus, we believe that our analysisdemonstrates that Pyronia could be effective in mitigatingall instances of such shell injection attacks as they allultimately require access to an unauthorized executablebinary file. On the other hand, Pyronia does not mitigatebuffer overflow-based arbitrary code execution attacks.Further research is necessary to determine if Pyronia’smemory domains could mitigate these attacks.
Beyond scope vulnerability classes.
A large portion ofreported Python library vulnerabilities are beyond thescope of Pyronia’s protections. The majority of MITMvulnerabilities in our CVE reports analysis stem from afailure to verify TLS certificates. The weak crypto vulner-abilities in our survey primarily arise because a known-weak algorithm or random number generator was used, orbecause input was not properly validated. Similarly, Pyro-nia cannot prevent replay or data spoofing attacks as thesestem from improper input (i.e., nonce or filename) valida-tion as well. Most of the authentication bypass bugs occurin larger Python-based frameworks that fail to properlyimplement authentication procedures.Interestingly, the majority of the reported DoS attacksin Python libraries stem from improper input handling ormemory management that can cause the application tocrash. While Pyronia does not verify the correctness ofapplication or library code, we see an avenue for usingPyronia to prevent network-based DoS attacks.
Prior proposals have recognized the potential securitythreat posed by dynamic language features such as reflec-tion and native code execution [52, 59]. As we describein §3.2, Python’s dynamic features enabled us to replacefunction pointers (aka monkey patching), leak a sensi-tive file at import time, and modify contents of Pythonstack frames including the value of function arguments.To understand how these dynamic language features affectPyronia’s protections, we analyzed these three cases.Much as in the direct data leak attack analysis, we foundthat Pyronia readily prevented unauthorized file accessesat import time. However, we met several challenges toPyronia’s ability to prevent all forms of stack frame tam-pering and monkey patching. We found that Pyronia’s stack memory domain prevents native code from directlyaccessing arbitrary stack frame memory. Yet, becausePython stores the local variables for each stack frame in aseparate dictionary data structure, pointed to by the stackframe, our implemented stack frame isolation is insuffi-cient to prevent tampering with function arguments bynative code or monkey patching. As part of ongoing re-search, we are exploring more robust countermeasures tothese dynamic language features.
To evaluate the performance of Pyronia, we ran our threecase studies (§7.1) in vanilla Python and Pyronia Python,measuring the execution time and memory overheads.We also took microbenchmarks of the main Pyronia op-erations, as well as common system calls used in IoTapplications to analyze the impact of Pyronia’s call stackinspection-based access control.Our testing system is an Ubuntu 18.04 LTS virtualmachine running our instrumented Pyronia Linux Ker-nel on a single Intel Core i7-3770 CPU, with 1.95 GBof RAM. Though not a dedicated IoT platform, our testVM’s configuration is comparable to recent single-boardcomputers targeting IoT, such as the Raspberry Pi 4 [46]or the NVIDIA Jetson Nano [43].To ensure that the results of our evaluation are consis-tent, we make minor modifications to our case study appli-cations replacing their real-time data collection (e.g., read-ing an image from a camera) with a static data source (e.g.,an image file), and run the applications for a finite numberof iterations. We emphasize that none of these modifica-tions affected policy specification, or were needed to addsupport for Pyronia’s security mechanisms.
To analyze the impact of Pyronia on application executiontime, we measured 25 runs of the end-to-end executiontime for a single iteration, as well as the per-iteration ex-ecution time over 100 iterations. The measurement fora single iteration of the application represents the worst-case scenario as it includes any overhead due to Pyroniainitialization (and teardown), and the kernel’s call stacklog is empty. Measuring the per-iteration execution time,on the other hand, gives an estimate of the long-term op-erating time of the application, and the overhead due toPyronia’s run-time security checks, i.e., call stack inspec-tion and stack domain-related operations.While Pyronia’s mean end-to-end execution time over-head of 2-5x is significant, the mean long-term overheadper iteration is reduced to 2-3x. Nonetheless, in absoluteterms, the worst-case execution time for a single app itera-tion under Pyronia is 1.5 seconds for the twitterPhoto app, which we expect would remain largely imperceptibleto end users in real-world deployments.11
10 20 30 40 50 60 70 80 90 100050100 alexa +Pyroniaapp0 10 20 30 40 50 60 70 80 90 100024 plant_watering +Pyroniaapp0 10 20 30 40 50 60 70 80 90 100050100 twitterPhoto +Pyroniaapp0.0 0.2 0.4 0.6 0.8 1.0number of iterations0.00.20.40.60.81.0 t i m e ( m s ) Figure 2: Mean per-iteration execution time in secondsfor each application with and without Pyronia enabled. open fopen connect020406080100120 t i m e ( u s ) syscall+Pyronia Figure 3: Mean execution time for open, fopen and socketconnect system calls across all tested applications.Figure 2 plots the mean per-iteration execution timeover 5 runs of 100 iterations of our tested applications. De-spite the overall execution time overhead of Pyronia, weobserve that stack logging lowers the long-term overheadof the plant_watering and twitterPhoto apps, as theexecution time mostly levels after about 5 iterations.Nonetheless, stack logging seems to play a little role inreducing the execution time overhead for the alexa app.For an application that requires active user involvement,Pyronia’s long-term overhead of 2x for the alexa appis likely unacceptable in a real-world deployment, evenwith an absolute per-iteration execution time of underone-eighth of a second (113.3 ms).
Pyronia operation microbenchmarks.
Measurementsof nine key Pyronia operations show that stack domaindynamic permissions adjustments greatly dominate theoverall Pyronia overhead, with millions of domain accessgrant/revoke calls in a single iteration in all applications.By comparison, the median number of all stack-relatedoperations, i.e., stack collection and hashing, is only inthe teens. Thus, we attribute the main source of Pyronia’s run-time overheads to stack domain access grant callsrecorded in our experiments.
Access control overhead.
To further characterize the per-formance costs due to Pyronia’s access control checks inthe kernel, we ran microbenchmarks of the libc open() , fopen() and connect() (and their 64-bit variants), for whichwe have implemented our stack logging optimization. Fig-ure 3 shows the mean execution time over 25 runs of asingle iteration of our tested apps. Our results show thatPyronia’s system call interposition imposes at most a 2xoverhead for the open() system call. Summary.
Pyronia’s execution time overhead is not triv-ial, despite our performance optimizations. While someadditional time is spent during each system call, the mainslowdown occurs due to dynamic memory domain pageaccess adjustments. Nonetheless, because the majorityof IoT applications run on devices only passively col-lecting and transmitting data, we expect these overheadswould go largely unnoticed by end users. We plan to in-vestigate further performance optimizations of memorydomain access adjustments, especially for interactive IoTapplications, as part of future work.
Pyronia imposes memory overhead due to the creationand management of the stack memory domain. To eval-uate the impact of this domain on userspace memoryconsumption, we first measure the userspace per-domainpage metadata allocations, i.e., the memory required forthe Pyronia runtime to maintain each domain page andthe associated memory management data structures forthe stack domain. Our analysis shows that the mean per-domain pagemetadata memory usage for all tested applications is be-tween 0.31 and 0.38 KB; the fact that the page metadataallocations varies this little across all tested applicationsdemonstrates that the majority of domain pages containa similar number of allocated blocks (i.e., runtime stackframes), regardless of the total number of allocated do-main pages. Table 6 further shows that the median mem-ory usage of the whole Pyronia subs-system in the Pythonruntime remains under 200 KB, even for applications withover 100 stack domain pages. These results are a strongindication that Pyronia’s domain memory consumptionscales linearly with the number of allocated domain pages.Furthermore, Pyronia’s memory domains have a smallimpact on the overall memory consumption of our testedapplications. Table 7 shows the median peak memoryusage and overhead over 5 100-iteration runs. For the twitterPhoto application with a peak memory usage of We do not evaluate the actual data allocation overhead per domainpage as Pyronia does not change the amount of data the runtime allocates,only where in the runtime’s address space this data is placed. twitterPhoto
176 151.2 KB alexa
141 147.9 KB plant_watering
54 68.4 KBTable 7: Peak memory overhead under Pyronia. peak usage (in MB) overhead twitterPhoto alexa plant_watering
Summary.
Pyronia incurs low memory overhead, evenfor IoT applications that allocate over 100 domain pages.For instance, domain metadata only consumes a total of151 KB for the twitterPhoto application with 176 al-located domain pages. For applications with a greaternumber of domain pages, our results indicate that themetadata memory overhead would likely grow linearly.While the increase to application-wide memory usage isthe highest for the plant_watering application at 70%,a peak memory consumption of under 30 MB is still rathermodest. Therefore, Pyronia’s memory overhead wouldnot place an excessive burden on IoT devices with moreconstrained resources than our testing system.
Multi-threading.
While Pyronia currently targets single-threaded IoT applications, we discovered in §3.1 as wellas during our experiments that a small number of IoT ap-plications and libraries (about 10%) spawn pthreads. Thisprogramming pattern introduces one key security chal-lenge: since threads execute independently of the mainthread. In other words, a vulnerability could still cause aconfused deputy attack (violating P2 ).To address this issue, upon pthread_create() or thread_start() calls, Pyronia could automatically savethe state of the “parent” call stack, so as to provide theAccess Control module with the full provenance when thechild thread makes a system call. Nonetheless, accuratelymapping “parent” stacks to child stacks, especially in thescenario of nested multi-threading, would be an additionaldesign challenge. Improving policy specification.
As we discuss in §7.2,Pyronia aims to reduce the burden of defining fine-grainedaccess policies, and lower false negatives. However, due toour reliance on AppArmor, Pyronia currently expects path- based access rules, which are often difficult to determinefor resources such as sensors.Designing a more developer-friendly and rigorouspolicy specification model is beyond the scope of Py-ronia. One interesting approach may be to supportsimple mobile-style resource access capabilities (e.g.,
READ_CAM ), which Pyronia could then automatically mapto the corresponding low-level system resources.More short-term improvements include adding supportfor domain-based network whitelisting, and maintaininga list of the most critical default rules within the kernel,allowing developers to remain agnostic to the runtimedefaults. The number of required rules could be furtherreduced by adding support for rule grouping. That is, forresources accessible by multiple functions with the sameprivileges, Pyronia could support allowing developers toexpress these policies as a single rule.While we believe that the risks of completely auto-mated policy generation (e.g., as in [11, 44]) outweigh thebenefits, we see an opportunity for the library developercommunity to ease the policy specification process further.For instance, library developers could contribute resource“manifests”, i.e., a list of required files and network destina-tions, and package these manifests along with their sourcecode or binaries. With support from Pyronia, applicationdevelopers could then automatically load these manifestsas part of their application-specific access policy, allowingapplication developers to focus on their high-level policy.
10 Conclusion
We have presented Pyronia, an intra-process access con-trol system for IoT device applications written in high-level languages. Pyronia enforces function-granular MACof third-party code via a three-pronged approach: sys-tem call interposition, stack inspection, and memory do-mains. Unlike prior approaches, Pyronia runs unmodi-fied applications, and does not require unintuitive policyspecification. We implement a Pyronia kernel and Pyro-nia Python runtime. Our evaluation of three open-sourcePython IoT applications demonstrates that Pyronia mit-igates OS resource-based data leak vulnerabilities, andshows that Pyronia’s performance overheads are accept-able for the most common types of IoT applications.
References [1] CVE-2019-9948. Retrieved Aug. 2 2019, from https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-9948 .[2] MQTT.org. Retrieved Feb. 9, 2019, from https://mqtt.org .[3] Y. Acar, M. Backes, S. Fahl, D. Kim, M. L. Mazurek,and C. Stransky. You Get Where You’re Looking13or: The Impact of Information Sources on CodeSecurity. In
Proc. IEEE Symposium on Security andPrivacy , May 2016.[4] Y. Acar, S. Fahl, and M. L. Mazurek. You are NotYour Developer, Either: A Research Agenda for Us-able Security and Privacy Research Beyond EndUsers. In
Proc. IEEE Cybersecurity Development ,pages 3–8, 11 2016.[5] Amazon Web Services, Inc. AWS IoT. RetrievedFeb. 9, 2019, from https://aws.amazon.com/iot/ .[6] Amazon Web Services, Inc. Security and identityfor AWS IoT. AWS IoT Devloper Guide.[7] Amazon.com, Inc. Alexa Voice Service. RetrievedFeb. 9, 2019, from https://developer.amazon.com/alexa-voice-service .[8] AppArmor maintainers. AppArmor security projectwiki. Accessed Dec. 30, 2018, https://gitlab.com/apparmor/apparmor/wikis/home/ .[9] R. Balebako and L. Cranor. Improving App Privacy:Nudging App Developers to Protect User Privacy.In
Proc. IEEE Symposium on Security and Privacy ,July 2014.[10] A. Bittau, P. Marchenko, M. Handley, and B. Karp.Wedge: Splitting Applications into Reduced-Privilege Compartments. In
NSDI , 2008.[11] A. Blankstein and M. J. Freedman. AutomatingIsolation and Least Privilege in Web Services. In
IEEE Symposium on Security and Privacy , 2014.[12] J. Bort. For The First Time, Hackers Have Used ARefrigerator To Attack Businesses. Business Insider,Jan. 2014.[13] Y. Chen, S. Reymondjohnson, Z. Sun, and L. Lu.Shreds: Fine-Grained Execution Units with PrivateMemory. In
IEEE Symposium on Security and Pri-vacy (S&P) , 2016.[14] W. Cheng, D. R. K. Ports, D. Schultz, V. Popic,A. Blankstein, J. Cowling, D. Curtis, L. Shrira, andB. Liskov. Abstractions for usable information flowcontrol in aeolus. In
ATC , 2012.[15] Y. Cheng, Z. Zhou, M. Yu, D. Xuhua, and R. Deng.ROPecker: A Generic and Practical Approach ForDefending Against ROP Attacks. In
NDSS , 2014. [16] L. Davi, A.-R. Sadeghi, and M. Winandy. ROPde-fender: A Detection Tool to Defend Against Return-oriented Programming Attacks. In
Proc. ACM Sym-posium on Information, Computer and Communica-tions Security , 2011.[17] M. Dietz, S. Shekhar, Y. Pisetsky, A. Shu, and D. S.Wallach. Quire: Lightweight Provenance for SmartPhone Operating Systems. In
USENIX SecuritySymposium , 2011.[18] Eclipse Foundation. IoT Developer Sur-veys. https://iot.eclipse.org/iot-developer-surveys/ , 2019. Accessed 3Nov 2019.[19] P. Efstathopoulos, M. Krohn, S. VanDeBogart,C. Frey, D. Ziegler, E. Kohler, D. Mazières,F. Kaashoek, and R. Morris. Labels and event pro-cesses in the asbestos operating system. In
SOSP ,2005.[20] A. P. Felt, H. J. Wang, A. Moshchuk, S. Hanna, andE. Chin. Permission re-delegation: Attacks and de-fenses. In
USENIX Security Symposium , 2011.[21] E. Fernandes, J. Paupore, A. Rahmati, D. Simion-ato, M. Conti, and A. Prakash. FlowFence: Prac-tical Data Protection for Emerging IoT Applica-tion Frameworks. In
USENIX Security Symposium .USENIX Association, 2016.[22] S. Gallagher. How one rent-a-botnet army of cam-eras, DVRs caused Internet chaos. Ars Technica,Oct. 2016.[23] D. Genkin, L. Pachmanov, I. Pipman, E. Tromer,and Y. Yarom. ECDSA Key Extraction from MobileDevices via Nonintrusive Physical Side Channels.In
Proc. ACM SIGSAC Conference on Computerand Communications Security , 2016.[24] D. B. Giffin, A. Levy, D. Stefan, A. Russo, D. Terei,D. Mazières, and J. C. Mitchell. Hails: Protectingdata privacy in untrusted web applications. In
OSDI ,2012.[25] I. Goldberg, D. Wagner, R. Thomas, and E. Brewer.A secure environment for untrusted helper appli-cations (confining the wily hacker). In
USENIXSecurity Symposium , 1996.[26] D. Goodin. 9 baby monitors wide open to hacks thatexpose users’ most private moments. Ars Technica,Sep. 2015.[27] A. Greenberg. Hackers Remotely Kill a Jeep on theHighway – With Me in It. Wired, Jul. 2015.1428] N. Hardy. The confused deputy: (or why capabilitiesmight have been invented).
ACM Operating SystemsReview , 22(4), 1988.[29] W. He, M. Golla, R. Padhi, J. Ofek, M. Dürmuth,E. Fernandes, and B. Ur. Rethinking access controland authentication for the home internet of things(iot). In
Proc. USENIX Security Symposium , 2018.[30] T. C.-H. Hsu, K. Hoffman, P. Eugster, and M. Payer.Enforcing Least Privilege Memory Views for Multi-threaded Applications. In
CCS , 2016.[31] H. Hu, C. Qian, C. Yagemann, S. P. H. Chung, W. R.Harris, T. Kim, and W. Lee. Enforcing Unique CodeTarget Property for Control-Flow Integrity. In
Proc.CCS , 2018.[32] Intel Corporation. Intel IoT platform reference ar-chitecture white paper.[33] Y. J. Jia, Q. A. Chen, S. Wang, A. Rahmati, E. Fer-nandes, Z. M. Mao, and A. Prakash. Contexlot:Towards providing contextual integrity to appifiediot platforms. In
NDSS . Internet Society, 2017.[34] M. B. Jones. Interposition agents: transparentlyinterposing user code at the system interface. In
SOSP , 1993.[35] P. Kocher, J. Horn, A. Fogh, , D. Genkin, D. Gruss,W. Haas, M. Hamburg, M. Lipp, S. Mangard,T. Prescher, M. Schwarz, and Y. Yarom. Spectreattacks: Exploiting speculative execution. In ,2019.[36] M. Krohn, A. Yip, M. Brodsky, N. Cliffer, M. F.Kaashoek, E. Kohler, and R. Morris. Informationflow control for standard os abstractions. In
SOSP ,2007.[37] S. Lee, J. Choi, J. Kim, B. Cho, S. Lee, H. Kim, andJ. Kim. FACT: Functionality-centric Access ControlSystem for IoT Programming Frameworks. In
Proc.ACM Symposium on Access Control Models andTechnologies , 2017.[38] M. Lipp, M. Schwarz, D. Gruss, T. Prescher,W. Haas, A. Fogh, J. Horn, S. Mangard, P. Kocher,D. Genkin, Y. Yarom, and M. Hamburg. Meltdown:Reading kernel memory from user space. In ,2018.[39] J. Litton, A. Vahldiek-Oberwagner, E. Elnikety,D. Garg, B. Bhattacharjee, and P. Druschel. Light-Weight Contexts: An OS Abstraction for Safety andPerformance. In
OSDI , 2016. [40] Microsoft Windows Dev Center. Manda-tory Integrity Control. Accessed Feb. 11,2019, https://docs.microsoft.com/en-us/windows/desktop/SecAuthZ/mandatory-integrity-control .[41] A. C. Myers and B. Liskov. Protecting privacy usingthe decentralized label model.
ACM Transactions onSoftware Engineering and Methodology , 9(4), 2000.[42] Nest Labs. Keeping data safe at Nest.[43] Nvidia Corporation. Jetson Nano. Retrieved Jul. 24,2019, from .[44] N. Provos. Improving host security with system callpolicies. In
USENIX Security Symposium , 2003.[45] A. Rahmati, E. Fernandes, K. Eykholt, andA. Prakash. Tyche: A Risk-Based PermissionModel for Smart Homes. In
IEEE CybersecurityDevelopment (SecDev) , 2018.[46] Raspberry Pi Foundation. Raspberry Pi 4Tech Specs. Retrieved Jul. 24, 2019, from .[47] R. Roemer, E. Buchanan, H. Shacham, and S. Sav-age. Return-oriented programming: Systems, lan-guages, and applications.
ACM Trans. Inf. Syst. Se-cur. , 15(1), Mar. 2012.[48] J. H. Saltzer and M. D. Schroeder. The protectionof information in computer systems.
Proceedings ofthe IEEE , 63(9), 1975.[49] SAMSUNG. Device Protection and Trusted CodeExecution.[50] R. Schuster, V. Shmatikov, and E. Tromer. Situa-tional access control in the internet of things. In
Proc. ACM SIGSAC Conference on Computer andCommunications Security , 2018.[51] SELinux maintainers. SELinux Project wiki. Ac-cessed Feb. 11, 2019, https://selinuxproject.org/page/Main_Page .[52] J. Seo, D. Kim, D. Cho, T. Kim, I. Shin, and X. Jiang.FlexDroid: Enforcing In-App Privilege Separationin Android. In
NDSS , Feb. 2016.[53] S. Shankar. Monkey Patching in Python: Ex-plained with Examples. Retrieved 11 Nov,2019, from https://thecodebits.com/monkey-patching-in-python-explained-with-examples/ .1554] S. Shekhar, M. Dietz, and D. S. Wallach. AdSplit:Separating smartphone advertising from applica-tions. In
USENIX Security Symposium . USENIXAssociation, 2012.[55] D. Stefan, E. Z. Yang, P. Marchenko, A. Russo,D. Herman, B. Karp, and D. Mazières. Protectingusers by confining javascript with cowl. In
OSDI ,2014.[56] Symantec Security Response. IoT devices beingincreasingly used for DDoS attacks. Symantec Offi-cial Blog, Sep. 2016.[57] The MITRE Corporation. Common Vulnerabilitiesand Exposures (CVE) List. https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=python .Accessed 10 Aug 2019.[58] Y. Tian, N. Zhang, Y.-H. Lin, X. Wang, B. Ur,X. Guo, and P. Tague. SmartAuth: User-centeredAuthorization for the Internet of Things. In
Proc.USENIX Security Symposium , 2017.[59] N. Vasilakis, B. Karel, N. Roessler, N. Dautenhahn,A. Dehon, and J. Smith. BreakApp: Automated,Flexible Application Compartmentalization. In
NDSS , 2018.[60] D. S. Wallach and E. W. Felten. Understanding JavaStack Inspection. In
IEEE S&P , 1998.[61] J. Wang, X. Xiong, and P. Liu. Between MutualTrust and Mutual Distrust: Practical Fine-grainedPrivilege Separation in Multithreaded Applications.In
USENIX ATC) , 2015.[62] Y. Wang, S. Hariharan, C. Zhao, J. Liu, and W. Du.Compac: Enforce component-level access controlin android. In
Conference on Data and ApplicationSecurity and Privacy (CODASPY) , 2014.[63] R. Wartell, V. Mohan, K. W. Hamlen, and Z. Lin.Binary Stirring: Self-randomizing Instruction Ad-dresses of Legacy x86 Binary Code. In
Proc. CCS ,2012.[64] Y. Wu, S. Sathyanarayan, R. H. Yap, and Z. Liang.Codejail: Application-transparent Isolation of Li-braries with Tight Program Interactions. In
ES-ORICS , 2012.[65] A. Yip, X. W. andNickolai Zeldovich, and M. F.Kaashoek. Improving application security with dataflow assertions. In
SOSP , 2009.[66] A. R. Yumerefendi, B. Mickle, and L. P. Cox.Tightlip: Keeping applications from spilling thebeans. In
NSDI , 2007. [67] N. Zeldovich, S. Boyd-Wickizer, E. Kohler, andD. Mazières. Making information flow explicit inhistar. In
OSDI , 2006.[68] K. Zetter. It’s Insanely Easy to Hack Hospital Equip-ment. Wired, Apr. 2014.
A CVE Reports for Python Libraries
Our analysis of reported Python library vulnerabilitiesin §3.2 covers Common Vulnerabilities and Exposures(CVE) reports made between January 2012 and March2019. We found 123 reports for a total of 78 differentPython libraries and frameworks in this seven-year timeframe, and we identified nine main attack classes. Ta-ble 8 shows the attack class and affected Python libraryor framework for each analyzed CVE report.16able 8: Reported Python library vulnerabilities between Feb 2012 and June 2019.
CVE Report Vulnerability Class Affected Library/Framework
CVE-2019-9948 Direct data leak urllib*CVE-2019-9947 Web attack urllib*CVE-2019-9740 Web attack urllib*CVE-2019-7537 Arbitrary code execution donfigCVE-2019-6690 Direct data leak python-gnupgCVE-2019-5729 MITM splunk-sdkCVE-2019-3575 Arbitrary code execution sqla-yaml-fixturesCVE-2019-3558 DoS Facebook ThriftCVE-2019-2435 Direct data leak Oracle MySQL ConnectorsCVE-2019-13611 Web attack python-engineioCVE-2019-12761 Arbitrary code execution pyXDGCVE-2019-11324 MITM urllib*CVE-2019-11236 Web attack urllib*CVE-2018-5773 Web attack python-markdown2CVE-2018-20325 Arbitrary code execution definitionsCVE-2018-18074 Direct data leak requestsCVE-2018-17175 Direct data leak marshmallowCVE-2018-10903 Direct data leak python-cryptographyCVE-2018-1000808 DoS pyopensslCVE-2018-1000807 DoS pyopensslCVE-2017-9807 Arbitrary code execution OpenWebifCVE-2017-7235 Arbitrary code execution cloudflare-scrapeCVE-2017-3590 Authentication bypass MySQLCVE-2017-2809 Arbitrary code execution ansible-vaultCVE-2017-2809 Arbitrary code execution tablibCVE-2017-2592 Direct data leak python-oslo-middlewareCVE-2017-16764 Arbitrary code execution DjangoCVE-2017-16763 Arbitrary code execution ConfireCVE-2017-16618 Arbitrary code execution OwlMixinCVE-2017-16616 Arbitrary code execution PyAnyAPICVE-2017-16615 Arbitrary code execution MLAlchemyCVE-2017-1002150 Web attack python-fedoraCVE-2017-1000433 Authentication bypass pysamlCVE-2017-1000246 Weak crypto pysamlCVE-2017-0906 Web attack recurlyCVE-2016-9910 Web attack html5libCVE-2016-9909 Web attack html5libCVE-2016-9015 MITM urllib*CVE-2016-7036 Weak crypto python-joseCVE-2016-5851 Web attack python-docxCVE-2016-5699 Web attack urllib*CVE-2016-5598 Direct data leak MySQLCVE-2016-4972 Arbitrary code execution python-muranoclientCVE-2016-2533 DoS PILCVE-2016-2166 Weak crypto Apache QPid ProtonCVE-2016-1494 Weak crypto python-rsaCVE-2016-0772 Weak crypto smtplibCVE-2015-7546 Authentication bypass python-keystoneclientCVE-2015-5306 Arbitrary code execution ironic-inspectorCVE-2015-5242 Arbitrary code execution swiftonfile17able 8 Continued.
CVE Report Vulnerability Class Affected Library/Framework
CVE-2015-5159 DoS python-kdcproxyCVE-2015-3220 DoS tlsliteCVE-2015-3206 DoS python-kerberosCVE-2015-2674 MITM restkitCVE-2015-2316 DoS DjangoCVE-2015-1852 MITM python-keystoneclientCVE-2015-1326 Arbitrary code execution python-dbusmockCVE-2014-9365 MITM urllib*CVE-2014-8165 Arbitrary code execution powerpc-utils-pythonCVE-2014-7144 MITM python-keystoneclientCVE-2014-4616 Direct data leak simplejsonCVE-2014-3995 Web attack DjangoCVE-2014-3994 Web attack DjangoCVE-2014-3598 DoS PILCVE-2014-3589 DoS PILCVE-2014-3539 Arbitrary code execution ropeCVE-2014-3146 Web attack lxmlCVE-2014-3137 Authentication bypass BottleCVE-2014-3007 Arbitrary code execution PILCVE-2014-1934 Symlink attack eyeD3CVE-2014-1933 Symlink attack PILCVE-2014-1932 Symlink attack PILCVE-2014-1929 Arbitrary code execution python-gnupgCVE-2014-1928 Arbitrary code execution python-gnupgCVE-2014-1927 Arbitrary code execution python-gnupgCVE-2014-1839 Symlink attack logilab-commonCVE-2014-1838 Symlink attack logilab-commonCVE-2014-1830 Direct data leak requestsCVE-2014-1829 Direct data leak requestsCVE-2014-1624 Symlink attack python-xdgCVE-2014-1604 Data spoofing python-rplyCVE-2014-0472 Arbitrary code execution DjangoCVE-2014-0105 Authentication bypass python-keystoneclientCVE-2013-7459 Arbitrary code execution PyCryptoCVE-2013-7440 MITM sslCVE-2013-7323 Arbitrary code execution python-gnupgCVE-2013-6491 MITM python-qpidCVE-2013-6444 MITM pyWBEMCVE-2013-6418 MITM pyWBEMCVE-2013-6396 MITM python-swiftclientCVE-2013-4482 Authentication bypass python-paste-scriptCVE-2013-4347 Weak crypto python-oauth2CVE-2013-4346 Auth token replay attack python-oauth2CVE-2013-4238 MITM sslCVE-2013-4111 MITM python-glanceclientCVE-2013-2191 MITM python-bugzillaCVE-2013-2132 DoS pymongoCVE-2013-2131 DoS python-rrdtoolCVE-2013-2104 Auth token replay attack python-keystoneclientCVE-2013-2013 Direct data leak python-keystoneclientCVE-2013-1909 MITM Apache QPid Proton18able 8 Continued.