fuzzssh.py 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  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): # FUZZED PARAMETERS
  61. if parameter == "USERNAME":
  62. try:
  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. client.close() # close SSH client
  65. except:
  66. pass # keep testing
  67. elif parameter == "PASSWORD":
  68. try:
  69. 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)
  70. except:
  71. pass # keep testing
  72. elif parameter == "PKEY":
  73. try:
  74. 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)
  75. except:
  76. pass # keep testing
  77. elif parameter == "KEY_FILENAME":
  78. try:
  79. 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)
  80. except:
  81. pass # keep testing
  82. elif parameter == "TIMEOUT":
  83. try:
  84. 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)
  85. except:
  86. pass # keep testing
  87. elif parameter == "ALLOW_AGENT":
  88. try:
  89. 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)
  90. except:
  91. pass # keep testing
  92. elif parameter == "LOOK_FOR_KEYS":
  93. try:
  94. 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)
  95. except:
  96. pass # keep testing
  97. elif parameter == "COMPRESS":
  98. try:
  99. 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)
  100. except:
  101. pass # keep testing
  102. elif parameter == "SOCK":
  103. try:
  104. 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)
  105. except:
  106. pass # keep testing
  107. elif parameter == "GSS_AUTH":
  108. try:
  109. 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)
  110. except:
  111. pass # keep testing
  112. elif parameter == "GSS_KEX":
  113. try:
  114. 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)
  115. except:
  116. pass # keep testing
  117. elif parameter == "GSS_DELEG_CREDS":
  118. try:
  119. 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)
  120. except:
  121. pass # keep testing
  122. elif parameter == "GSS_HOST":
  123. try:
  124. 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)
  125. except:
  126. pass # keep testing
  127. elif parameter == "BANNER_TIMEOUT":
  128. try:
  129. 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)
  130. except:
  131. pass # keep testing
  132. elif parameter == "AUTH_TIMEOUT":
  133. try:
  134. 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)
  135. except:
  136. pass # keep testing
  137. elif parameter == "GSS_TRUST_DNS":
  138. try:
  139. 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)
  140. except:
  141. pass # keep testing
  142. elif parameter == "PASSPHRASE":
  143. try:
  144. 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)
  145. except:
  146. pass # keep testing
  147. elif parameter == "DISABLED_ALGORITHMS":
  148. try:
  149. 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)
  150. except:
  151. pass # keep testing
  152. 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):
  153. try:
  154. client = paramiko.SSHClient()
  155. client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
  156. client.load_system_host_keys()
  157. paramiko.util.log_to_file("/dev/null", level="INFO") # logs + bypass -> paramiko.SSHException issue (https://github.com/paramiko/paramiko/issues/1752)
  158. print("[Info] Trying SSH connection...\n")
  159. 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)
  160. print("[Info] Connection established -> OK!")
  161. if verbosity is True:
  162. b = client.get_transport().remote_version
  163. print ("\n -> [*] Banner:")
  164. print(" -> "+str(b))
  165. so = client._transport.get_security_options()
  166. print ("\n -> [*] Ciphering algorithms:")
  167. for c in so.ciphers:
  168. print(" -> "+str(c))
  169. print ("\n -> [*] Key exchange algorithms:")
  170. for k in so.kex:
  171. print(" -> "+str(k))
  172. print("\n[Info] Connection closed -> OK!")
  173. print("\n"+"="*50)
  174. except:
  175. print("="*50)
  176. print ("\n[Error] Connection failed! -> [ABORTING!]\n")
  177. sys.exit()
  178. client.close() # close SSH client
  179. print("\n -> [*] Starting to test SSH (protocol)...")
  180. 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
  181. for parameter in parameters:
  182. print("\n -> [SSH] -> ["+str(parameter)+"]...\n")
  183. method = " [*] Numbers "
  184. for i in progressbar(range(num_payloads_numbers),method+" ", 40):
  185. time.sleep(0.7)
  186. for number in payloads_numbers:
  187. send_payload(client, number, parameter, verbosity, num_payloads_numbers, method)
  188. time.sleep(0.2)
  189. method = " [*] Overflows "
  190. for i in progressbar(range(num_payloads_overflows),method+" ", 40):
  191. time.sleep(0.7)
  192. for overflow in payloads_overflows:
  193. send_payload(client, overflow, parameter, verbosity, num_payloads_overflows, method)
  194. time.sleep(0.2)
  195. method = " [*] Format Strings"
  196. for i in progressbar(range(num_payloads_strings),method+" ", 40):
  197. time.sleep(0.7)
  198. for string in payloads_strings:
  199. send_payload(client, string, parameter, verbosity, num_payloads_strings, method)
  200. time.sleep(0.2)
  201. method = " [*] Known bugs "
  202. for i in progressbar(range(num_payloads_bugs),method+" ", 40):
  203. time.sleep(0.7)
  204. for bug in payloads_bugs:
  205. send_payload(client, bug, parameter, verbosity, num_payloads_bugs, method)
  206. time.sleep(0.2)
  207. print("\n"+"-"*15)
  208. def set_target():
  209. target = input("\n + Enter TARGET (ex: '100.0.0.1'): ")
  210. if target == "": # exit when no 'target' set
  211. print("\n"+"="*50)
  212. print("\n[Error] Not ANY target detected -> [EXITING!]\n")
  213. sys.exit()
  214. port = input("\n + Enter PORT (default: '22'): ")
  215. try: # check port as integer num
  216. port = int(port)
  217. except:
  218. port = 22
  219. if port == "": # default when no 'port' set
  220. port = 22
  221. user = input("\n + Enter USER (default: 'root'): ")
  222. if user == "": # default when no 'user' set
  223. user = "root"
  224. pw = input("\n + Enter PASSWORD (default: 'root'): ")
  225. if pw == "": # default when no 'password' set
  226. ps = "root"
  227. verbosity = input("\n + Enter VERBOSITY (default: 'false'): ")
  228. if verbosity == "True" or verbosity == "true":
  229. verbosity = True
  230. else:
  231. verbosity = False # default when no 'verbosity' set
  232. return target, port, user, pw, verbosity
  233. def print_banner():
  234. print("\n"+"="*50)
  235. print(" _____ __________ _ _ ")
  236. print("| ___| _|__ /__ /___ ___| | | |")
  237. print("| |_ | | | | / / / // __/ __| |_| |")
  238. print("| _|| |_| |/ /_ / /_\__ \__ \ _ |")
  239. print("|_| \__,_/____/____|___/___/_| |_| by psy")
  240. print('\n"SSH -Protocol- Fuzzing Tool"')
  241. print("\n"+"-"*15+"\n")
  242. print(" * VERSION: ")
  243. print(" + "+VERSION+" - (rev:"+RELEASE+")")
  244. print("\n * SOURCES:")
  245. print(" + "+SOURCE1)
  246. print(" + "+SOURCE2)
  247. print("\n * CONTACT: ")
  248. print(" + "+CONTACT+"\n")
  249. print("-"*15+"\n")
  250. print("="*50)
  251. # sub_init #
  252. print_banner() # show banner
  253. print("\n"+"="*50)
  254. target, port, user, pw, verbosity = set_target()
  255. payloads_numbers, num_payloads_numbers, payloads_overflows, num_payloads_overflows, payloads_strings, num_payloads_strings, payloads_bugs, num_payloads_bugs = payloading()
  256. 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)