From ffbbc6704477497366bd92bb4a5f3630da2c0043 Mon Sep 17 00:00:00 2001 From: Harry James Hall Date: Fri, 17 Feb 2023 12:45:30 +0000 Subject: [PATCH 1/2] Add rancher module --- .../unix/misc/rancher/files/configure.py | 7 ++++ .../unix/misc/rancher/files/setup-rancher.py | 37 +++++++++++++++++++ .../unix/misc/rancher/manifests/flags.pp | 13 +++++++ .../unix/misc/rancher/manifests/install.pp | 35 ++++++++++++++++++ .../unix/misc/rancher/rancher.pp | 3 ++ .../unix/misc/rancher/secgen_metadata.xml | 34 +++++++++++++++++ 6 files changed, 129 insertions(+) create mode 100644 modules/vulnerabilities/unix/misc/rancher/files/configure.py create mode 100644 modules/vulnerabilities/unix/misc/rancher/files/setup-rancher.py create mode 100644 modules/vulnerabilities/unix/misc/rancher/manifests/flags.pp create mode 100644 modules/vulnerabilities/unix/misc/rancher/manifests/install.pp create mode 100644 modules/vulnerabilities/unix/misc/rancher/rancher.pp create mode 100644 modules/vulnerabilities/unix/misc/rancher/secgen_metadata.xml diff --git a/modules/vulnerabilities/unix/misc/rancher/files/configure.py b/modules/vulnerabilities/unix/misc/rancher/files/configure.py new file mode 100644 index 000000000..25d5e198d --- /dev/null +++ b/modules/vulnerabilities/unix/misc/rancher/files/configure.py @@ -0,0 +1,7 @@ +import requests + +def main(): + requests.put("http://localhost:8080/v2-beta/settings/api.host", data='{"id":"api.host","type":"activeSetting","baseType":"setting","name":"api.host","activeValue":null,"inDb":false,"source":null,"value":"172.22.6.76"}') + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/modules/vulnerabilities/unix/misc/rancher/files/setup-rancher.py b/modules/vulnerabilities/unix/misc/rancher/files/setup-rancher.py new file mode 100644 index 000000000..51477fde0 --- /dev/null +++ b/modules/vulnerabilities/unix/misc/rancher/files/setup-rancher.py @@ -0,0 +1,37 @@ +import requests +import socket +import os +import time + +s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) +s.connect(("8.8.8.8", 80)) +ip = (s.getsockname()[0]) +s.close() + +proxies = { + "http": None, + "https": None, +} + +data = {"type":"setting","name":"telemetry.opt","value":"in"} +response = requests.post("http://localhost:8080/v2-beta/setting", json = data, proxies=proxies) +print(response) + +null = None +false = False +data = {"id":"api.host","type":"activeSetting","baseType":"setting","name":"api.host","activeValue":null,"inDb":false,"source":null,"value":"http://" + ip + ":8080"} +response = requests.put("http://localhost:8080/v2-beta/settings/api.host", json=data, proxies=proxies) +print(response) + +data = {"type":"registrationToken"} +response = requests.post("http://localhost:8080/v2-beta/projects/1a5/registrationtoken", json=data, proxies=proxies) +#link = response.json()["actions"]["activate"] +link = response.json()["links"]["self"] +print(link) + +time.sleep(2) + +response = requests.get(link, proxies=proxies) +command = response.json()["command"] +print(command) +os.system(command) diff --git a/modules/vulnerabilities/unix/misc/rancher/manifests/flags.pp b/modules/vulnerabilities/unix/misc/rancher/manifests/flags.pp new file mode 100644 index 000000000..66d28bb63 --- /dev/null +++ b/modules/vulnerabilities/unix/misc/rancher/manifests/flags.pp @@ -0,0 +1,13 @@ +class rancher::flags { + # this is how secgen +## $secgen_parameters = secgen_functions::get_parameters($::base64_inputs_file) + $leaked_filenames = ["flagsecret"] ##$secgen_parameters['leaked_filenames'] + $strings_to_leak = ["flag message"] ##$secgen_parameters['strings_to_leak'] + + ::secgen_functions::leak_files { 'root-home-folder': + storage_directory => "/root", + leaked_filenames => $leaked_filenames, + strings_to_leak => $strings_to_leak, + leaked_from => 'rancher', + } +} diff --git a/modules/vulnerabilities/unix/misc/rancher/manifests/install.pp b/modules/vulnerabilities/unix/misc/rancher/manifests/install.pp new file mode 100644 index 000000000..e45a00bb0 --- /dev/null +++ b/modules/vulnerabilities/unix/misc/rancher/manifests/install.pp @@ -0,0 +1,35 @@ +class rancher::install { + Exec { + path => ['/bin', '/usr/bin', '/usr/local/bin', '/sbin', '/usr/sbin'] + } + + ensure_packages(['apt-transport-https', 'ca-certificates', 'curl', 'gnupg2', 'software-properties-common']) + + exec {'remove-all-containers': + command => 'docker stop $(docker ps -a -q); docker rm $(docker ps -qa)' + } -> + docker::run {'rancher-server': + image => 'rancher/server', + ports => ['8080:8080'], + extra_parameters => '--restart=unless-stopped', + } -> + exec {'wait-for-rancher-server': + command => 'sleep 360', + timeout => 365, + } -> + file {'/root/setup-rancher.py': + source => 'puppet:///modules/rancher/setup-rancher.py', + mode => '0755', + } -> + exec {'configure-rancher': + command => 'python3 /root/setup-rancher.py', + environment => [], + } -> + docker::image {'alpine': + image_tag => 'latest', + } -> + exec {'wait-for-rancher-host-agent': + command => 'sleep 60', + timeout => 65, + } +} diff --git a/modules/vulnerabilities/unix/misc/rancher/rancher.pp b/modules/vulnerabilities/unix/misc/rancher/rancher.pp new file mode 100644 index 000000000..caa24e226 --- /dev/null +++ b/modules/vulnerabilities/unix/misc/rancher/rancher.pp @@ -0,0 +1,3 @@ +include docker +include rancher::install +include rancher::flags diff --git a/modules/vulnerabilities/unix/misc/rancher/secgen_metadata.xml b/modules/vulnerabilities/unix/misc/rancher/secgen_metadata.xml new file mode 100644 index 000000000..0c96f104a --- /dev/null +++ b/modules/vulnerabilities/unix/misc/rancher/secgen_metadata.xml @@ -0,0 +1,34 @@ + + + + Rancher + Harry J. Hall + MIT + This exploit allows users of the rancher server to gain access to the hosts running docker that are managed by rancher. + It can be mitigated by limiting permissions of rancher users to read only for untrusted users. + + docker + root_rwx + remote + linux + medium + + server_name + strings_to_leak + leaked_filenames + ports + + + + + + + + + + + https://github.com/rapid7/metasploit-framework/blob/master/modules/exploits/linux/http/rancher_server.rb + + \ No newline at end of file From 6d7ead3c1fb98433560a080c2f39daf65b15bc2c Mon Sep 17 00:00:00 2001 From: Harry James Hall Date: Tue, 28 Feb 2023 21:34:00 +0000 Subject: [PATCH 2/2] Update rancher module to latest version --- .../unix/misc/rancher/files/setup-rancher.py | 75 +++++++++++-------- .../unix/misc/rancher/manifests/install.pp | 32 ++++---- 2 files changed, 62 insertions(+), 45 deletions(-) diff --git a/modules/vulnerabilities/unix/misc/rancher/files/setup-rancher.py b/modules/vulnerabilities/unix/misc/rancher/files/setup-rancher.py index 51477fde0..dc21b5d25 100644 --- a/modules/vulnerabilities/unix/misc/rancher/files/setup-rancher.py +++ b/modules/vulnerabilities/unix/misc/rancher/files/setup-rancher.py @@ -2,36 +2,47 @@ import socket import os import time +import debinterface -s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) -s.connect(("8.8.8.8", 80)) -ip = (s.getsockname()[0]) -s.close() - -proxies = { - "http": None, - "https": None, -} - -data = {"type":"setting","name":"telemetry.opt","value":"in"} -response = requests.post("http://localhost:8080/v2-beta/setting", json = data, proxies=proxies) -print(response) - -null = None -false = False -data = {"id":"api.host","type":"activeSetting","baseType":"setting","name":"api.host","activeValue":null,"inDb":false,"source":null,"value":"http://" + ip + ":8080"} -response = requests.put("http://localhost:8080/v2-beta/settings/api.host", json=data, proxies=proxies) -print(response) - -data = {"type":"registrationToken"} -response = requests.post("http://localhost:8080/v2-beta/projects/1a5/registrationtoken", json=data, proxies=proxies) -#link = response.json()["actions"]["activate"] -link = response.json()["links"]["self"] -print(link) - -time.sleep(2) - -response = requests.get(link, proxies=proxies) -command = response.json()["command"] -print(command) -os.system(command) +def get_ip(): + adapters = debinterface.Interfaces().adapters + for adapter in adapters: + if "ens" in adapter.attributes['name'] and adapter.attributes['source'] == 'static': + return adapter.attributes['address'] + raise Exception("Could not find address") + +def setup_rancher(): + ip = get_ip() + + proxies = { + "http": None, + "https": None, + } + + data = {"type":"setting","name":"telemetry.opt","value":"in"} + response = requests.post("http://localhost:8080/v2-beta/setting", json = data, proxies=proxies) + print(response) + + null = None + false = False + data = {"id":"api.host","type":"activeSetting","baseType":"setting","name":"api.host","activeValue":null,"inDb":false,"source":null,"value":"http://" + ip + ":8080"} + response = requests.put("http://localhost:8080/v2-beta/settings/api.host", json=data, proxies=proxies) + print(response) + + data = {"type":"registrationToken"} + response = requests.post("http://localhost:8080/v2-beta/projects/1a5/registrationtoken", json=data, proxies=proxies) + #link = response.json()["actions"]["activate"] + link = response.json()["links"]["self"] + print(link) + + time.sleep(2) + + response = requests.get(link, proxies=proxies) + command = response.json()["command"] + print(command) + os.system(command) + +if not os.path.exists("/root/ran"): + time.sleep(10) + setup_rancher() + os.system("touch /root/ran") \ No newline at end of file diff --git a/modules/vulnerabilities/unix/misc/rancher/manifests/install.pp b/modules/vulnerabilities/unix/misc/rancher/manifests/install.pp index e45a00bb0..3bcba5c3d 100644 --- a/modules/vulnerabilities/unix/misc/rancher/manifests/install.pp +++ b/modules/vulnerabilities/unix/misc/rancher/manifests/install.pp @@ -3,11 +3,8 @@ path => ['/bin', '/usr/bin', '/usr/local/bin', '/sbin', '/usr/sbin'] } - ensure_packages(['apt-transport-https', 'ca-certificates', 'curl', 'gnupg2', 'software-properties-common']) + ensure_packages(['apt-transport-https', 'ca-certificates', 'curl', 'gnupg2', 'software-properties-common', 'python3-pip']) - exec {'remove-all-containers': - command => 'docker stop $(docker ps -a -q); docker rm $(docker ps -qa)' - } -> docker::run {'rancher-server': image => 'rancher/server', ports => ['8080:8080'], @@ -17,19 +14,28 @@ command => 'sleep 360', timeout => 365, } -> +# docker::image {'rancher/net': } -> +# docker::image {'rancher/network-manager': } -> +# docker::image {'rancher/dns': } -> +# docker::image {'rancher/healthcheck': } -> +# docker::image {'rancher/metadata': } -> +# docker::image {'rancher/scheduler': } -> + docker::image {'rancher/agent': + tag => 'v1.2.11', + } -> + docker::image {'alpine': } -> file {'/root/setup-rancher.py': source => 'puppet:///modules/rancher/setup-rancher.py', mode => '0755', } -> - exec {'configure-rancher': - command => 'python3 /root/setup-rancher.py', - environment => [], - } -> - docker::image {'alpine': - image_tag => 'latest', + exec {'install-debinterface': + command => 'pip3 install debinterface' } -> - exec {'wait-for-rancher-host-agent': - command => 'sleep 60', - timeout => 65, +# exec {'configure-rancher': +# command => 'python3 /root/setup-rancher.py', +# environment => [], +# } -> + exec {'set-rancher-configuration-file-to-run-at-boot-via-crontab': + command => 'echo "@reboot root /usr/bin/python3 /root/setup-rancher.py >> /root/rancher_config_log.txt 2>> /root/rancher_config_log.txt" >> /etc/crontab; chmod 644 /etc/crontab' } }