fuzzssh.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-"
  3. """
  4. FuzzSSH (Simple SSH Fuzzer) - 2022 - by psy (epsylon@riseup.net)
  5. You should have received a copy of the GNU General Public License along
  6. with FuzzSSH; if not, write to the Free Software Foundation, Inc., 51
  7. Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  8. ----------
  9. See following RFCs for more info:
  10. rfc4251 - The SSH Protocol Architecture
  11. rfc4252 - The SSH Authentication Protocol
  12. rfc4253 - The SSH Transport Layer Protocol
  13. rfc4254 - The SSH Connection Protocol
  14. ----------
  15. Current [01/22][Paramiko] tested parameters:
  16. username, password, pkey, key_filename, timeout, allow_agent,
  17. look_for_keys, compress, sock, gss_auth, gss_kex, gss_deleg_creds,
  18. gss_host, banner_timeout, auth_timeout, gss_trust_dns, passphrase,
  19. disabled_algorithms
  20. """
  21. import sys, time, os
  22. try:
  23. import paramiko
  24. except:
  25. print("\nError importing: paramiko lib. \n\n To install it on Debian based systems:\n\n $ 'sudo apt-get install python3-paramiko'\n")
  26. sys.exit()
  27. VERSION = "v:0.1beta"
  28. RELEASE = "12012022"
  29. SOURCE1 = "https://code.03c8.net/epsylon/fuzzssh"
  30. SOURCE2 = "https://github.com/epsylon/fuzzssh"
  31. CONTACT = "epsylon@riseup.net - (https://03c8.net)"
  32. try:
  33. import payloads.payloads # import payloads
  34. except:
  35. print ("\n[Info] Try to run the tool with Python3.x.y... (ex: python3 fuzzssh.py) -> [EXITING!]\n")
  36. sys.exit()
  37. def progressbar(it, prefix="", size=60, file=sys.stdout):
  38. count = len(it)
  39. def show(j):
  40. x = int(size*j/count)
  41. file.write("%s[%s%s] %i/%i\r" % (prefix, "#"*x, "."*(size-x), j, count))
  42. file.flush()
  43. show(0)
  44. for i, item in enumerate(it):
  45. yield item
  46. show(i+1)
  47. file.write("\n")
  48. file.flush()
  49. def payloading():
  50. print("\n"+"="*50 + "\n")
  51. payloads_numbers = payloads.payloads.numbers # load 'numbers' payloads
  52. num_payloads_numbers = len(payloads_numbers)
  53. payloads_overflows = payloads.payloads.overflows # load 'overflows' payloads
  54. num_payloads_overflows = len(payloads_overflows)
  55. payloads_strings = payloads.payloads.strings # load 'strings' payloads
  56. num_payloads_strings = len(payloads_strings)
  57. payloads_bugs = payloads.payloads.bugs # load 'bugs' payloads
  58. num_payloads_bugs = len(payloads_bugs)
  59. return payloads_numbers, num_payloads_numbers, payloads_overflows, num_payloads_overflows, payloads_strings, num_payloads_strings, payloads_bugs, num_payloads_bugs
  60. def send_payload(client, payload, parameter, verbosity, num_payloads, method):
  61. try: # FUZZED PARAMETERS
  62. if parameter == "USERNAME":
  63. client.connect(hostname=str(target),port=int(port),username=payload, password=None, pkey=None, key_filename=None, timeout=None, allow_agent=True, look_for_keys=True, compress=False, sock=None, gss_auth=False, gss_kex=False, gss_deleg_creds=True, gss_host=None, banner_timeout=None, auth_timeout=None, gss_trust_dns=True, passphrase=None, disabled_algorithms=None)
  64. elif parameter == "PASSWORD":
  65. client.connect(hostname=str(target),port=int(port),username=None, password=payload, pkey=None, key_filename=None, timeout=None, allow_agent=True, look_for_keys=True, compress=False, sock=None, gss_auth=False, gss_kex=False, gss_deleg_creds=True, gss_host=None, banner_timeout=None, auth_timeout=None, gss_trust_dns=True, passphrase=None, disabled_algorithms=None)
  66. elif parameter == "PKEY":
  67. client.connect(hostname=str(target),port=int(port),username=None, password=None, pkey=payload, key_filename=None, timeout=None, allow_agent=True, look_for_keys=True, compress=False, sock=None, gss_auth=False, gss_kex=False, gss_deleg_creds=True, gss_host=None, banner_timeout=None, auth_timeout=None, gss_trust_dns=True, passphrase=None, disabled_algorithms=None)
  68. elif parameter == "KEY_FILENAME":
  69. client.connect(hostname=str(target),port=int(port),username=None, password=None, pkey=None, key_filename=payload, timeout=None, allow_agent=True, look_for_keys=True, compress=False, sock=None, gss_auth=False, gss_kex=False, gss_deleg_creds=True, gss_host=None, banner_timeout=None, auth_timeout=None, gss_trust_dns=True, passphrase=None, disabled_algorithms=None)
  70. elif parameter == "TIMEOUT":
  71. client.connect(hostname=str(target),port=int(port),username=None, password=None, pkey=None, key_filename=None, timeout=payload, allow_agent=True, look_for_keys=True, compress=False, sock=None, gss_auth=False, gss_kex=False, gss_deleg_creds=True, gss_host=None, banner_timeout=None, auth_timeout=None, gss_trust_dns=True, passphrase=None, disabled_algorithms=None)
  72. elif parameter == "ALLOW_AGENT":
  73. client.connect(hostname=str(target),port=int(port),username=None, password=None, pkey=None, key_filename=None, timeout=None, allow_agent=payload, look_for_keys=True, compress=False, sock=None, gss_auth=False, gss_kex=False, gss_deleg_creds=True, gss_host=None, banner_timeout=None, auth_timeout=None, gss_trust_dns=True, passphrase=None, disabled_algorithms=None)
  74. elif parameter == "LOOK_FOR_KEYS":
  75. client.connect(hostname=str(target),port=int(port),username=None, password=None, pkey=None, key_filename=None, timeout=None, allow_agent=True, look_for_keys=payload, compress=False, sock=None, gss_auth=False, gss_kex=False, gss_deleg_creds=True, gss_host=None, banner_timeout=None, auth_timeout=None, gss_trust_dns=True, passphrase=None, disabled_algorithms=None)
  76. elif parameter == "COMPRESS":
  77. client.connect(hostname=str(target),port=int(port),username=None, password=None, pkey=None, key_filename=None, timeout=None, allow_agent=True, look_for_keys=True, compress=payload, sock=None, gss_auth=False, gss_kex=False, gss_deleg_creds=True, gss_host=None, banner_timeout=None, auth_timeout=None, gss_trust_dns=True, passphrase=None, disabled_algorithms=None)
  78. elif parameter == "SOCK":
  79. client.connect(hostname=str(target),port=int(port),username=None, password=None, pkey=None, key_filename=None, timeout=None, allow_agent=True, look_for_keys=True, compress=False, sock=payload, gss_auth=False, gss_kex=False, gss_deleg_creds=True, gss_host=None, banner_timeout=None, auth_timeout=None, gss_trust_dns=True, passphrase=None, disabled_algorithms=None)
  80. elif parameter == "GSS_AUTH":
  81. client.connect(hostname=str(target),port=int(port),username=None, password=None, pkey=None, key_filename=None, timeout=None, allow_agent=True, look_for_keys=True, compress=False, sock=None, gss_auth=payload, gss_kex=False, gss_deleg_creds=True, gss_host=None, banner_timeout=None, auth_timeout=None, gss_trust_dns=True, passphrase=None, disabled_algorithms=None)
  82. elif parameter == "GSS_KEX":
  83. client.connect(hostname=str(target),port=int(port),username=None, password=None, pkey=None, key_filename=None, timeout=None, allow_agent=True, look_for_keys=True, compress=False, sock=None, gss_auth=False, gss_kex=payload, gss_deleg_creds=True, gss_host=None, banner_timeout=None, auth_timeout=None, gss_trust_dns=True, passphrase=None, disabled_algorithms=None)
  84. elif parameter == "GSS_DELEG_CREDS":
  85. client.connect(hostname=str(target),port=int(port),username=None, password=None, pkey=None, key_filename=None, timeout=None, allow_agent=True, look_for_keys=True, compress=False, sock=None, gss_auth=False, gss_kex=False, gss_deleg_creds=payload, gss_host=None, banner_timeout=None, auth_timeout=None, gss_trust_dns=True, passphrase=None, disabled_algorithms=None)
  86. elif parameter == "GSS_HOST":
  87. client.connect(hostname=str(target),port=int(port),username=None, password=None, pkey=None, key_filename=None, timeout=None, allow_agent=True, look_for_keys=True, compress=False, sock=None, gss_auth=False, gss_kex=False, gss_deleg_creds=True, gss_host=payload, banner_timeout=None, auth_timeout=None, gss_trust_dns=True, passphrase=None, disabled_algorithms=None)
  88. elif parameter == "BANNER_TIMEOUT":
  89. client.connect(hostname=str(target),port=int(port),username=None, password=None, pkey=None, key_filename=None, timeout=None, allow_agent=True, look_for_keys=True, compress=False, sock=None, gss_auth=False, gss_kex=False, gss_deleg_creds=True, gss_host=None, banner_timeout=payload, auth_timeout=None, gss_trust_dns=True, passphrase=None, disabled_algorithms=None)
  90. elif parameter == "AUTH_TIMEOUT":
  91. client.connect(hostname=str(target),port=int(port),username=None, password=None, pkey=None, key_filename=None, timeout=None, allow_agent=True, look_for_keys=True, compress=False, sock=None, gss_auth=False, gss_kex=False, gss_deleg_creds=True, gss_host=None, banner_timeout=None, auth_timeout=payload, gss_trust_dns=True, passphrase=None, disabled_algorithms=None)
  92. elif parameter == "GSS_TRUST_DNS":
  93. client.connect(hostname=str(target),port=int(port),username=None, password=None, pkey=None, key_filename=None, timeout=None, allow_agent=True, look_for_keys=True, compress=False, sock=None, gss_auth=False, gss_kex=False, gss_deleg_creds=True, gss_host=None, banner_timeout=None, auth_timeout=None, gss_trust_dns=payload, passphrase=None, disabled_algorithms=None)
  94. elif parameter == "PASSPHRASE":
  95. client.connect(hostname=str(target),port=int(port),username=None, password=None, pkey=None, key_filename=None, timeout=None, allow_agent=True, look_for_keys=True, compress=False, sock=None, gss_auth=False, gss_kex=False, gss_deleg_creds=True, gss_host=None, banner_timeout=None, auth_timeout=None, gss_trust_dns=True, passphrase=payload, disabled_algorithms=None)
  96. elif parameter == "DISABLED_ALGORITHMS":
  97. client.connect(hostname=str(target),port=int(port),username=None, password=None, pkey=None, key_filename=None, timeout=None, allow_agent=True, look_for_keys=True, compress=False, sock=None, gss_auth=False, gss_kex=False, gss_deleg_creds=True, gss_host=None, banner_timeout=None, auth_timeout=None, gss_trust_dns=True, passphrase=None, disabled_algorithms=payload)
  98. except paramiko.SSHException as e: # https://docs.paramiko.org/en/stable/api/ssh_exception.html
  99. exception = str(e)
  100. if not os.path.exists('exceptions.log'):
  101. os.mknod('exceptions.log')
  102. if not exception in open('exceptions.log').read():
  103. f = open("exceptions.log", "a")
  104. f.write("Exception error: %s\n\n" % exception)
  105. f.close()
  106. client.close() # close SSH client
  107. def exploit(target, port, user, pw, verbosity, payloads_numbers, num_payloads_numbers, payloads_overflows, num_payloads_overflows, payloads_strings, num_payloads_strings, payloads_bugs, num_payloads_bugs):
  108. try:
  109. client = paramiko.SSHClient()
  110. client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
  111. client.load_system_host_keys()
  112. paramiko.util.log_to_file("/dev/null", level="INFO") # logs + bypass -> paramiko.SSHException issue (https://github.com/paramiko/paramiko/issues/1752)
  113. print("[Info] Trying SSH [NORMAL] connection...\n")
  114. client.connect(hostname=str(target),port=int(port),username=str(user),password=str(pw),timeout=10,banner_timeout=200,look_for_keys=False,allow_agent=False)
  115. print("\n[Info] [NORMAL] Connection established -> OK!")
  116. if verbosity is True:
  117. b = client.get_transport().remote_version
  118. print ("\n -> [*] Banner:")
  119. print(" -> "+str(b))
  120. so = client._transport.get_security_options()
  121. print ("\n -> [*] Ciphering algorithms:")
  122. for c in so.ciphers:
  123. print(" -> "+str(c))
  124. print ("\n -> [*] Key exchange algorithms:")
  125. for k in so.kex:
  126. print(" -> "+str(k))
  127. print("\n[Info] [NORMAL] Connection closed -> OK!")
  128. print("\n"+"="*50)
  129. except:
  130. print("="*50)
  131. print ("\n[Error] [NORMAL] Connection failed! -> [PASSING!]")
  132. client.close() # close SSH client
  133. print("\n -> [*] Starting to test SSH (protocol)...")
  134. parameters = ("USERNAME", "PASSWORD", "PKEY", "KEY_FILENAME", "TIMEOUT", "ALLOW_AGENT", "LOOK_FOR_KEYS", "COMPRESS", "SOCK", "GSS_AUTH", "GSS_KEX", "GSS_DELEG_CREDS", "GSS_HOST", "BANNER_TIMEOUT", "AUTH_TIMEOUT", "GSS_TRUST_DNS", "PASSPHRASE", "DISABLED_ALGORITHMS") # FUZZED PARAMETERS
  135. for parameter in parameters:
  136. print("\n -> [SSH] -> ["+str(parameter)+"]...\n")
  137. method = " [*] Numbers "
  138. for i in progressbar(range(num_payloads_numbers),method+" ", 40):
  139. time.sleep(0.7)
  140. for number in payloads_numbers:
  141. send_payload(client, number, parameter, verbosity, num_payloads_numbers, method)
  142. time.sleep(0.2)
  143. method = " [*] Overflows "
  144. for i in progressbar(range(num_payloads_overflows),method+" ", 40):
  145. time.sleep(0.7)
  146. for overflow in payloads_overflows:
  147. send_payload(client, overflow, parameter, verbosity, num_payloads_overflows, method)
  148. time.sleep(0.2)
  149. method = " [*] Format Strings"
  150. for i in progressbar(range(num_payloads_strings),method+" ", 40):
  151. time.sleep(0.7)
  152. for string in payloads_strings:
  153. send_payload(client, string, parameter, verbosity, num_payloads_strings, method)
  154. time.sleep(0.2)
  155. method = " [*] Known bugs "
  156. for i in progressbar(range(num_payloads_bugs),method+" ", 40):
  157. time.sleep(0.7)
  158. for bug in payloads_bugs:
  159. send_payload(client, bug, parameter, verbosity, num_payloads_bugs, method)
  160. time.sleep(0.2)
  161. print("\n"+"-"*15)
  162. def set_target():
  163. target = input("\n + Enter TARGET (ex: '100.0.0.1'): ")
  164. if target == "": # exit when no 'target' set
  165. print("\n"+"="*50)
  166. print("\n[Error] Not ANY target detected... Exiting!\n")
  167. sys.exit()
  168. port = input("\n + Enter PORT (ex: '22'): ")
  169. try: # check port as integer num
  170. port = int(port)
  171. except:
  172. port = 22
  173. if port == "": # default when no 'port' set
  174. port = 22
  175. user = input("\n + Enter USER (ex: 'root'): ")
  176. if user == "": # default when no 'user' set
  177. user = "root"
  178. pw = input("\n + Enter PASSWORD (ex: '12345'): ")
  179. verbosity = input("\n + Enter VERBOSITY (ex: 'true'): ")
  180. if verbosity == "True" or verbosity == "true": # default when no 'verbosity' set
  181. verbosity = True
  182. else:
  183. verbosity = False
  184. return target, port, user, pw, verbosity
  185. def print_banner():
  186. print("\n"+"="*50)
  187. print(" _____ __________ _ _ ")
  188. print("| ___| _|__ /__ /___ ___| | | |")
  189. print("| |_ | | | | / / / // __/ __| |_| |")
  190. print("| _|| |_| |/ /_ / /_\__ \__ \ _ |")
  191. print("|_| \__,_/____/____|___/___/_| |_| by psy")
  192. print('\n"Simple SSH Protocol Fuzzing Tool"')
  193. print("\n"+"-"*15+"\n")
  194. print(" * VERSION: ")
  195. print(" + "+VERSION+" - (rev:"+RELEASE+")")
  196. print("\n * SOURCES:")
  197. print(" + "+SOURCE1)
  198. print(" + "+SOURCE2)
  199. print("\n * CONTACT: ")
  200. print(" + "+CONTACT+"\n")
  201. print("-"*15+"\n")
  202. print("="*50)
  203. # sub_init #
  204. print_banner() # show banner
  205. print("\n"+"="*50)
  206. target, port, user, pw, verbosity = set_target()
  207. payloads_numbers, num_payloads_numbers, payloads_overflows, num_payloads_overflows, payloads_strings, num_payloads_strings, payloads_bugs, num_payloads_bugs = payloading()
  208. exploit(target, port, user, pw, verbosity, payloads_numbers, num_payloads_numbers, payloads_overflows, num_payloads_overflows, payloads_strings, num_payloads_strings, payloads_bugs, num_payloads_bugs)