Docker Approaching Multi Container Applications WP PDF
Docker Approaching Multi Container Applications WP PDF
TABLE OF CONTENTS
Table of Contents 1
Introduction 3
Motivation 3
Prior Work 4
Concept 5
Malware 5
Exploitation 5
Containerization 6
Concept 6
Setup 8
Motivation 15
Introduction 18
TABLE OF CONTENTS
Value in Lab Environments 19
Introduction 20
Attacker Setup 24
Exploitation 25
Identifying Containerization 26
Conclusions 34
Bibliography 35
INTRODUCTION
The goal of this white paper, and its associated talk, is to provide a hacker experienced in exploitation and post-
exploitation of networks of systems with an exposure to containerization and the implications it has on offensive
operations. Docker is used as a concrete example for the case study. As a tool for enabling service-oriented
architectural styles of development, the rise in popularity of using containers is relatively recent. While exploitation
and manipulation of monolithic applications might require specialized experience and training in the target
languages and execution environment, applications made up of modular services distributed amongst multiple
containers can be effectively explored and exploited “from within” using many of the system- and network-level
techniques in which attackers, such as penetration testers, are more commonly trained. A hacker can expect
to leave this presentation with a practical exposure to multi-container application post-exploitation that is as
lightweight in buzzwords as is possible with such a trendy topic among developers.
MOTIVATION
Containerization, the decomposition of applications into multiple independent containers that interact with each
other over standard protocols, is becoming a more common and popular way of building large-scale applications
that deal with big data. Cloud-based container services and microservice architectures are commonly used for
large-scale services that make use of personal identity data.
The approach to hacking described in this work involves moving from attacking accessible interfaces of monolithic
applications to leveraging vulnerabilities in components of multi-container microservice-based applications to
explore the otherwise-inaccessible insides. Over the past decade and a half, attackers have embraced, used, and
learned how to attack virtualization technologies to the point that the use of virtualization has become nearly muscle
memory. The same adaptation will soon have to occur for containerization as more and more attractive targets and
clients of penetration tests deploy large-scale applications that make use of Docker and similar platforms.
PRIOR WORK
David Mortman presented a talk at DEF CON 23, Docker, Docker, Give Me the News, I Got a Bad Case of Securing
You. Mortman’s talk provided an overview of Docker’s underlying implementation and architecture, current and
planned security features, and presented advice for developers interested in taking positive action to make their
containerized applications more secure[1]. Mortman linked to a Gotham Digital Science set of Docker Secure
Deployment Guidelines that provides more guidance to those interested in development and deployment[2]. Also
at DEF CON 23, Aaron Grattafiori went into even more detail on the Linux kernel’s capabilities for containerization
and platforms (such as Docker) that are built to take advantage of those capabilities[3]. Grattafiori’s white paper,
Understanding and Hardening Linux Containers, also provides interesting low-level security advice[4].
The Docker documentation also discusses security issues[16], and over time has addressed vulnerabilities
described in some of the other prior works discussed here. While there are recommendations for more secure
deployment of container-based and multi-container applications, there are two main points that attackers will
need to keep in mind. First, unless a security measure or feature is on by default and does not represent an
inconvenience, there will be a significant number of target application deployments that will not implement that
feature. Second, application-level vulnerabilities may allow attackers into application-specific container networks,
regardless of platform-level mitigations, meaning that attackers should remain very interested in post-exploitation
tactics as applied to containers. In short, admirable progress has been made, but developers have yet to be saved
from themselves.
On the offense-oriented side of things, at Black Hat Europe 2015, Anthony Bettini presented Vulnerability
Exploitation in Docker Containers, that focused on a set of vulnerabilities in the Docker platform itself[5]. At Black
Hat USA 2017, Michael Cherney and Sagie Dulce presented a set of vulnerabilities in the Docker platform that
targeted the development environments of workstations[6].
The majority of information found on Docker security either has a target audience of those that defend Docker
deployments or involve specific vulnerabilities that can or have been patched or mitigated. This work intends to cater
to an audience of attackers, including penetration testers, that are interested in the implications and mechanics of
attacking multi-container applications. The focus is on exposure to the topic in a form (in terminology, approach,
and style) useful to that audience, and the presentation of strategies and “tips” for how to approach larger-scale
applications that are made up of containers.
The concept and approach for this work is strongly influenced by HD Moore and Valsmith’s DEF CON 15 talk,
Tactical Exploitation. That talk is an old favorite of this work’s author, and it had a significant impact on the way a
lot of penetration testers approached their work[7].
MALWARE
Outside of the realm of live attacks, this advantage can be seen in the analysis of malicious software, where
analysts allow “packed” binaries to “unpack” themselves in the normal course of execution, before dumping the
unpacked image in memory off to disk for analysis. Frequently, strings are encoded in a way that subverts basic
static analysis. Rather than spend time in cryptanalysis of the encoded strings or in understanding the details
of the algorithm, the analyst can often simply identify the decoder function and call it, in the same way as the
malware, for each encoded string. A deeper understanding of the code may be unnecessary, if the code itself can
be leveraged towards the end goal (in this case, of understanding an undocumented binary).
EXPLOITATION
In a live attack on an application, this same technique can be used. Attacks on binary, native-code applications
often use return-oriented programming (ROP) as a matter of necessity when attacker-controlled memory is not
marked as executable. This exploitation technique can be used to string together segments of executable code
already existing in the memory of the target application to achieve a goal, such as the elevation of privilege for
an application user, or the execution of a shell[8]. It has been shown that this technique often results in a wide
enough variety of code “gadgets” to allow for Turing-complete execution. Even if the advantages of a fully-featured
execution environment are not possible or taken advantage of by an attacker, it can be straightforward to call
functions in the target application to accomplish the attacker’s goal without a traditional “shell pop” [9].
Application security experts are more likely to identify creative ways of exploiting the internals of applications
than those tasked with the tactical exploitation of networks and systems. Penetration testers are typically trained
to be “users” of exploits, rather than developers, and are therefore limited in their ability to move around within
applications using the methods discussed so far. “Creative” control over execution within a monolithic binary
application is rarely exercised in the context of attacks carried out in the context of penetration testing.
Motivated, funded, and organized attackers are more likely to have “in-house” talent for developing exploits and
payloads that are specific to their mission. A payload that calls target application functions to extract and exfiltrate
data is more likely to evade detection and accomplish its goal with less live interaction than a general-purpose
“back door” (such as Meterpreter). This is behavior more closely associated with nation-state and criminal threat
actors than with typical penetration testers.
CONTAINERIZATION
CONCEPT
Containerization technology like Docker allows for the design of applications that are composed of many independent
single-purpose services, each with a minimal set of supporting system software and libraries[11]. Each service
represents a node on a network that has been created specifically for the application’s use. What would normally
be a call to a local function or a linked library might now be implemented as a communication across a network,
with a standard protocol, to another host[12].
Applications that have been developed using a Service-Oriented Architecture or microservice approach democratize
post-exploitation manipulation and instrumentation of the application. With monolithic applications, specialist
knowledge of the target application’s programming language, or its application binary interface, is needed to
successfully explore and instrument the application during post-exploitation. That is the domain of application
security and exploit development experts. In contrast, applications made up of multiple independent containers
communicating over standard networking protocols can be easily understood and manipulated by attackers, such
as penetration testers, that are trained in tactical exploitation of networked systems.
The additional layer of abstraction present in an application made up of independent containers is a boon for
attackers not specifically trained in-depth on application security. Where such an attacker would otherwise be
limited to treating each application or service on target hosts as a black box into which pre-made exploits are
launched, a containerized, SOA/microservice application allows for an exploit of an external-facing surface to act
as a looking glass into a wholly separate network of targets with which to interact.
Exploits for the attack surface of a multi-container application will exploit software running within a specific
container of the application. The exploit will likely take advantage of a web application vulnerability or memory
corruption bug in the same way as it would against a normal host running the same vulnerable application. Once
exploitation is successful, however, the attacker now has access to a system that is connected to an internal
network of systems and services that make up the rest of the multi-container application. Traditional attack/
penetration-testing tools, tactics, and procedures that are normally used against internal target networks can then
be leveraged, with small modification, to explore and exploit the internals of an application. The abstraction that
allows for loose coupling of independent application components now serves as a useful abstraction for attackers
otherwise unfamiliar with application security analysis.
Attacking a monolithic container application will work in a similar way as attacking a traditional host operating
system based installation of the same application, and code execution will give similar access to the container’s
environment. Exploitation will be limited to that environment and not necessarily lead to exploitation of the
container’s host.
Even monolithic container applications may provide an attacker with more post-exploitation opportunities than
an attacker might see on a traditional network. By default (if networks are not specifically configured otherwise),
Docker will place multiple containers on the same private network “behind” the host, regardless of the applications’
dependence (or lack of dependence) on each other. While you must specify which container ports are exposed to
the outside world through the host, each of those containers on the host may talk to each other freely in the default
configuration.
FROM ubuntu:16.04
EXPOSE 22
CMD [“/usr/sbin/sshd”, “-D”]
The second Dockerfile is nearly identical, but does not expose port 22:
FROM ubuntu:16.04
---> 38bc2b2faac1
Step 9/9 : CMD [“/usr/sbin/sshd”, “-D”]
---> Running in ae56588d210a
Removing intermediate container ae56588d210a
---> 01f5762d52fa
Successfully built 01f5762d52fa
Successfully tagged eg_sshd_noport:latest
Given these images, eg_sshd and eg_sshd_noport, we can now launch two containers, test_sshd_1 and
test_sshd_2. For test_sshd_1, we will pass the -P flag in order to forward the exposed TCP port 22 to the
host. For test_sshd_2, we will not pass that flag.
},
“Internal”: false,
“Attachable”: false,
“Ingress”: false,
“ConfigFrom”: {
“Network”: “”
},
“ConfigOnly”: false,
“Containers”: {
“2853974e9b1cccc23b35d05950362c96302850bd0b103ccfce57687eb2cf9894”: {
“Name”: “test_sshd_2”,
“EndpointID”:
“b42b28e23d20c3151b5c9ef446af4c0a08ea2283f5370b2e98ed092f8fb4546c”,
“MacAddress”: “02:42:ac:11:00:03”,
“IPv4Address”: “172.17.0.3/16”,
“IPv6Address”: “”
},
“819e5ea650079c67395d5b79b4fb095d474c284ca09313a3bc217d927cf55bcf”: {
“Name”: “test_sshd_1”,
“EndpointID”:
“94c4f6fe1f4266370020b2f5f3bf94f8710ab1947079c701eea199206cdd6664”,
“MacAddress”: “02:42:ac:11:00:02”,
“IPv4Address”: “172.17.0.2/16”,
“IPv6Address”: “”
}
},
“Options”: {
“com.docker.network.bridge.default_bridge”: “true”,
“com.docker.network.bridge.enable_icc”: “true”,
“com.docker.network.bridge.enable_ip_masquerade”: “true”,
“com.docker.network.bridge.host_binding_ipv4”: “0.0.0.0”,
“com.docker.network.bridge.name”: “docker0”,
“com.docker.network.driver.mtu”: “1500”
},
“Labels”: {}
}
]
wes@br:~/demo/monolithic_2_monolithic/ssh2$ docker port test_sshd_1
22/tcp -> 0.0.0.0:32770
(Identifying this information from within a container without access to the host docker commands will be
addressed later in this white paper.)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
root@819e5ea65007:~#
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
Last login: Sat Jan 27 21:23:42 2018 from 172.17.0.1
root@2853974e9b1c:~#
A host external to the Docker host, however, has no way to directly connect to the second SSH container, nor
would it be able to directly connect to any other non-exported ports on either container. Once access has been
gained to one container (in this example, test_sshd_1), there is nothing preventing connections to other non-
exported ports. We can demonstrate this by SSH’ing from test_sshd_1 to test_sshd_2:
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
Last login: Sat Jan 27 21:26:38 2018 from 172.17.0.1
root@2853974e9b1c:~#
If you try to run through this SSH example without the “inside knowledge” provided by the Docker network and
Docker port commands on the host, you will get a taste of some of the difficulties an attacker might have “living
off the land” on compromised container hosts. Containers need only contain the binaries, libraries, and code
needed to accomplish their goal, usually that of running one application or service.
Often, common command-line tools administrators and attackers alike rely on are not necessary and are omitted
from Docker images. Attackers with experience in post-exploitation on embedded systems may already be
experienced in working with minimal available tools in compromised targets.
root@819e5ea65007:~# ifconfig
-bash: ifconfig: command not found
root@819e5ea65007:~# ip a
-bash: ip: command not found
If your container has network access, and you don’t mind increasing your footprint considerably, you could
install packages you need. In this case, we add the package containing the “ip” command:
If this isn’t an option, you can also extract the information from the /proc file system:
This output presents TCP connections and routing information in little-endian hexadecimal values. In the above
output, the values that have been marked in bold can be decoded to identify network information:
Interestingly, while the base Ubuntu container does not contain ifconfig or ip, Alpine does include ifconfig.
To accomplish much else, however, you’ll need to install from the “apk” repositories or transfer in binaries/
scripts yourself. As an example of the former, the following two commands will allow you to install an SSH client:
/ # apk update
fetch http://dl-cdn.alpinelinux.org/alpine/v3.7/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.7/community/x86_64/APKINDEX.
tar.gz
v3.7.0-56-g2e8e7a0d34 [http://dl-cdn.alpinelinux.org/alpine/v3.7/main]
v3.7.0-58-g26701b74f8 [http://dl-cdn.alpinelinux.org/alpine/v3.7/community]
OK: 9044 distinct packages available
/ # apk add openssh
(1/6) Installing openssh-keygen (7.5_p1-r8)
(2/6) Installing openssh-client (7.5_p1-r8)
(3/6) Installing openssh-sftp-server (7.5_p1-r8)
(4/6) Installing openssh-server-common (7.5_p1-r8)
(5/6) Installing openssh-server (7.5_p1-r8)
(6/6) Installing openssh (7.5_p1-r8)
Executing busybox-1.27.2-r7.trigger
OK: 8 MiB in 17 packages
/ #
For transferring your own tools, there is a BusyBox version of wget available in the base Alpine container. Other
distributions commonly used to build Docker images do not contain easy-to-use tools for file transfer in their
bare-bones forms. For these systems (including Ubuntu, Debian, and CentOS), there are at least three options
for bootstrapping execution of arbitrary binaries:
• Update package repositories and install the needed tools. This requires network access to the repositories
and a willingness to have that specific impact/footprint on the running container.
• Utilize the language tools that have been installed to support the application/module/service that the Docker
container is running. For example, if the purpose of the Docker container is to run Python code, the standard
Python libraries can be used from a script or the interactive Python console to download and run arbitrary
binaries.
• Encode and paste in a statically-linked (or correctly dynamic linked, if you create it specifically for the target
container) binary that will either accomplish the task or bootstrap more transfers.
We can demonstrate the last option using a statically compiled version of the “ncat” netcat variant, available
from a useful repository of statically compiled binaries (https://github.com/andrew-d/static-binaries). All of the
base distribution images discussed so far have the Base-64 command installed, which allows us to translate a
binary into printable ASCII characters that we can then copy and paste into a file on the target container, and
decode back into an executable binary.
If we open the binary in a text editor, we see many lines of Base-64 encoded text:
f0VMRgIBAQAAAAAAAAAAAAIAPgABAAAAkilAAAAAAABAAAAAAAAAAHh0LAAAAAAAAAAAAEAAOAAD
AEAAEAAPAAEAAAAFAAAAAAAAAAAAAAAAAEAAAAAAAAAAQAAAAAAA1DcrAAAAAADUNysAAAAAAAAA
…<SNIP>…
AAAAAAAAAAEAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAF0LAAAAAAAcQAAAAAAAAAAAAAAAAAAAAEA
AAAAAAAAAAAAAAAAAAA=
We can select this text, copy it, and paste it into a file on the target container from a shell running on that
container. We then mark the file as executable and demonstrate that we have a working ncat binary on the target
container:
On the publicly-accessible Docker Hub, images are frequently “tagged” by version number, and it is often
possible to find an image that bundles up everything necessary to get a specific version of an application up
and running very quickly. Sometimes these exist in the tags of “official” Docker images for an application.
Sometimes it is possible to identify “one-off” unofficial images created and made public by ordinary Docker
users. In the case of this section’s example, we have pulled and followed setup instructions for an unofficial
(and vulnerable) version of Joomla[14], then committed the configured and running copy to the local image list
as “joomla_target”.
We can test exploitation by running our committed, vulnerable image of Joomla as follows, on the default
“bridge” network. TCP port 80 on the target container is forwarded to port 80 on the host, and after this
command we can access the installed Joomla instance at http://localhost/ :
In this demonstration, we’ll use Metasploit’s joomla_http_header_rce exploit against the target
container:
Because Docker has become popular primarily within the past few years, an image is likely to have been
created during that time, drastically reducing the chances of an older, known vulnerability being present in a
containerized application/service. While this property limits the selection of exploits that might show promise
against container-based applications, it should be noted that the “front-end” of multi-container applications
are likely to be parts written by internal or contracted teams for the end customer, and thus more likely to
be unaudited and contain typical web application vulnerabilities than widely used services that support that
code. In the experiences of the author’s penetration testing teams, the team members are always excited about
the prospect of attacking “custom”, “internal”, “contracted”, or “niche” web applications found on client
networks. At any rate, vulnerabilities in open source and commonly used supporting services/frameworks are not
likely to stop being discovered and exploited either. The movement of an operation from the outside a multi-
container application to the insides of that application should not be surprising to anyone involved in attacking
or defending those applications.
Now that we have discussed an approach to attacking multi-container applications and demonstrated some of
the mechanics in isolation, we can mock up a more complete operation.
EXAMPLE: POST-EXPLOITATION OF A
MULTI-CONTAINER APPLICATION
INTRODUCTION
The Docker Example Voting App is often used in demonstration and tutorials of Docker and Docker Compose.
The application is made up of multiple containers that provide services for each other with the overall goal
of providing interfaces for voting and viewing results in a simple poll. The individual containers contain code
written in a variety of languages and using a couple off-the-shelf open source services. The containers include:
While this a simplified and contrived example application, it illustrates the concept of developing a larger
application as a collection of smaller services. The individual services are so loosely coupled that they can be
written in completely different languages and environments, as long as they can communicate with each other
in standard and common protocols. It’s also a simple application that we can more completely examine in this
context of this work[15].
There are many advantages to this approach and architectural design, but for the purposes of this paper and
associated talk, we are more concerned with how an attacker might view the application after having compromised
some aspect of it. For our mock operation, we will modify the voting application to include the vulnerable Joomla
instance we spun up and tested previously in this paper. Once we gain access to the networks contained within
the multi-container application, we’ll look at how it can then be explored and manipulated.
version: “3”
services:
vote:
build: ./vote
command: python app.py
volumes:
- ./vote:/app
ports:
- “5001:80”
networks:
- front-tier
- back-tier
result:
build: ./result
command: nodemon server.js
volumes:
- ./result:/app
ports:
- “5002:80”
- “5858:5858”
networks:
- front-tier
- back-tier
joomla:
image: joomla_target
ports:
- “80:80”
networks:
- front-tier
- back-tier
worker:
build:
context: ./worker
depends_on:
- “redis”
networks:
- back-tier
redis:
image: redis:alpine
container_name: redis
ports: [“6379”]
networks:
- back-tier
db:
image: postgres:9.4
container_name: db
volumes:
- “db-data:/var/lib/postgresql/data”
networks:
- back-tier
volumes:
db-data:
networks:
front-tier:
back-tier:
The voting application has two networks, and like the other front-end containers, we give the Joomla container
access to both networks, and expose a port to the host for interaction. Port numbers for the voting and results
applications have been shifted from the version on GitHub in order to avoid a conflict with a locally-running
Docker registry container. The “docker-compose up” command can be used to build and bring the entire
multi-container application up, and we can see the exposed interfaces.
ATTACKER SETUP
We can position the attacker outside of the voting application by creating a separate network in which we will
run a Kali Linux container that has the Metasploit Framework installed. Ports on the external attack surface of
the voting application will be accessible by the attacker on the attacker’s network’s default gateway. The internal
networks of the target application will only be accessible via pivoting through the initial compromise of the
Joomla container that we’ve inserted.
EXPLOITATION
We can now set up the attack on the Joomla target:
In this demonstration, the PHP Meterpreter listener is set to forward to and listen on the host operating system
on port 4000. Once the options are configured, we can launch the exploit and gain access to the target container:
IDENTIFYING CONTAINERIZATION
An attacker might not know they are attacking a containerized application until the initial compromise is
successful and there is an opportunity to take a look inside. Containers are typically minimal and have very few
processes running within their context. Dead giveaways include the presence of a .dockerenv file in the root
directory, and indications of docker in /proc/1/cgroup:
ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group
default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
115: eth1@if116: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue
state UP group default
link/ether 02:42:ac:14:00:03 brd ff:ff:ff:ff:ff:ff
inet 172.20.0.3/16 brd 172.20.255.255 scope global eth1
valid_lft forever preferred_lft forever
123: eth0@if124: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue
state UP group default
link/ether 02:42:ac:15:00:06 brd ff:ff:ff:ff:ff:ff
inet 172.21.0.6/16 brd 172.21.255.255 scope global eth0
valid_lft forever preferred_lft forever
As a non-root user (www-data) running the PHP Meterpreter, we are somewhat limited in what we can do post-
exploitation. We can, however, at least transfer in a statically compiled nmap that we can use to map out the
rest of the application’s containers.
In the above output, we have scanned the first ten IP addresses in each of the two networks. Docker seems to
assign IP addresses incrementally, so scanning both /16 networks completely isn’t necessary in this specific
case. We see a number of ports (including the externally forwarded ports) on the host on the “.1” IP address of
both networks.
Also, we see each of our containers, helpfully with descriptive hostnames that indicate their name (and network
names) in the docker-compose.yml file:
• examplevotingapp_result_1.examplevotingapp_front-tier (172.20.0.2)
• a3f280146222 (172.20.0.3) (the Joomla target we inserted)
• examplevotingapp_vote_1.examplevotingapp_front-tier (172.20.0.4)
• db.examplevotingapp_back-tier (172.21.0.2)
• redis.examplevotingapp_back-tier (172.21.0.3)
• examplevotingapp_result_1.examplevotingapp_back-tier (172.21.0.4)
• a3f280146222 (172.21.0.5)
• examplevotingapp_worker_1.examplevotingapp_back-tier (172.21.0.6)
examplevotingapp_vote_1.examplevotingapp_back-tier (172.21.0.7)
Note that, as described in the Compose file, the Joomla target (which we have compromised), the voting
container, and the results container are all on both networks (172.20 and 172.21).
The default username for the official PostgreSQL image being used is “postgres”, with no default password. We
can attempt to connect to the database, examine the tables, and modify the voting results.
postgres=# \dt
List of relations
Schema | Name | Type | Owner
--------+-------+-------+----------
public | votes | table | postgres
postgres=# select * from votes;
id | vote
------------------+------
6318cb4c0b00af50 | a
postgres=# INSERT INTO votes (id, vote) VALUES (‘1’,’b’), (‘2’,’b’),
(‘3’,’b’), (‘4’,’b’);
postgres=# \q
The Redis server is similarly wide open by default, requiring no authentication. We can telnet into its open
TCP port and use the MONITOR command to begin watching the output of commands being issued to it. The
following shows the “worker” container continuously polling for new commands, and a vote being submitted by
the front-end.
With this information, we can insert our own votes via Redis, that will eventually wind up in the PostgreSQL
container (by way of the worker).
We’re currently a relatively unprivileged user within the container we’ve compromised, though it has given us a
high degree of leverage across the multi-container application.
CONCLUSIONS
Applications made up of multiple containers have the potential to provide “extra” internal networks that attackers
can interact with after the initial compromise of an application’s external attack surface. In this work, we have
explored the fundamentals of the Docker platform, as an attacker would see them on typical applications. An
attacker trained in exploitation of systems and networks, but not necessarily on the instrumentation of monolithic
application internals, can use this information and their existing training to easily explore and manipulate the
internals of multi-container applications that they gain a foothold on. This paper and its associated talk should
get attackers, otherwise unfamiliar with containerization platforms, a jump start on experimenting with them
and allow them to identify and more effectively attack them on real-world offensive engagements.
BIBLIOGRAPHY
1. David Mortman, Docker, Docker, Give Me the News, I Got a Bad Case of Securing You, DEF CON
23,
https://media.defcon.org/DEF%20CON%2023/DEF%20CON%2023%20presentations/DEFCON-
23-David-Mortman-Docker-UPDATED.pdf
5. Anthony Bettini, Vulnerability Exploitation in Docker Containers, Black Hat Europe 2015,
https://www.blackhat.com/docs/eu-15/materials/eu-15-Bettini-Vulnerability-Exploitation-In-Docker-
Container-Environments.pdf
6. Michael Cherney and Sagie Duce, Well, That Escalated Quickly! How Abusing Docker API Led
to Remote Code Execution, Same Origin Bypass and Persistence in The Hypervisor via Shadow
Containers, Black Hat USA 2017,
https://www.blackhat.com/docs/us-17/thursday/us-17-Cherny-Well-That-Escalated-Quickly-How-
Abusing-The-Docker-API-Led-To-Remote-Code-Execution-Same-Origin-Bypass-And-Persistence_
wp.pdf
8. Erik Buchanan, Ryan Roemer, and Stefan Savage, Return-Oriented Programming: Exploits Without
Code Injection, Black Hat USA 2008,
http://cseweb.ucsd.edu/~hovav/talks/blackhat08.html
10. Wesley McGrew, Secure Penetration Testing Operations: Demonstrated Weaknesses in Learning
Materials and Tools, DEF CON 24 and Black Hat USA 2016,
https://media.defcon.org/DEF%20CON%2024/DEF%20CON%2024%20presentations/DEFCON-
24-Wesley-McGrew-Secure-Penetration-Testing-Operations-WP.pdf
BIBLIOGRAPHY
11. The Docker Platform,
https://www.docker.com/