Skip to content

Commit 05ba9d9

Browse files
committed
feat(module): Add to specify multiple targets for the module
fix a typo than lead to unable to set debug mode.
1 parent 97ac53e commit 05ba9d9

File tree

4 files changed

+111
-28
lines changed

4 files changed

+111
-28
lines changed

lib/BaseExploit.py

+16
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from lib.ExploitOption import ExploitOption
12
from lib.ExploitOptions import ExploitOptions
23
from lib.ExploitResult import ExploitResult
34

@@ -12,10 +13,17 @@ class BaseExploit:
1213
service_version = None
1314
info_fields = ['name', 'description', 'author', 'references', 'disclosure_date', 'service_name', 'service_version']
1415

16+
multi_target = False
17+
targets = []
18+
target_type = None
19+
1520
options = None
1621
results = None
1722

1823
def __init__(self):
24+
self.multi_target = False
25+
self.target_type = None
26+
self.targets = []
1927
self.options = ExploitOptions()
2028
self.results = ExploitResult()
2129

@@ -25,6 +33,14 @@ def get_info(self):
2533
info[field_name] = getattr(self, field_name)
2634
return info
2735

36+
def register_tcp_target(self, port_value=None, timeout_value=10):
37+
self.target_type = "tcp"
38+
self.register_options([
39+
ExploitOption(name="HOST", required=True, description="The IP address to be tested"),
40+
ExploitOption(name="PORT", required=True, description="The port to be tested", value=port_value),
41+
ExploitOption(name="TIMEOUT", required=True, description="Connection timeout", value=timeout_value)
42+
])
43+
2844
def update_info(self, info):
2945
for name in info:
3046
if name in self.info_fields:

lib/Pocket.py

+66-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import argparse
2+
from queue import Queue
23
from lib.cmd2 import Cmd, with_category, with_argparser
34
from art import text2art, art
45
from utils import module
@@ -74,18 +75,31 @@ def complete_set(self, text, line, begidx, endidx):
7475

7576
set_parser = argparse.ArgumentParser()
7677
set_parser.add_argument("name", help="The name of the field you want to set")
78+
set_parser.add_argument("-f", "--file", action="store_true", help="Specify multiple targets")
7779
set_parser.add_argument("value", help="The value of the field you want to set")
7880

7981
@with_argparser(set_parser)
8082
@with_category(CMD_MODULE)
8183
def do_set(self, args):
82-
if args.value == 'debug':
84+
if args.name == 'debug':
8385
self.debug = args.value
8486
return None
8587

8688
if not self.module_instance:
8789
raise ModuleNotUseException()
8890

91+
# 使用 -f/--file 指定多个目标
92+
if args.file and args.name in ["HOST", "TARGET"]:
93+
try:
94+
open(args.value, 'r')
95+
self.module_instance.multi_target = True
96+
except IOError as e:
97+
self._print_item(e, color=Fore.RED)
98+
return False
99+
elif not args.file and args.name in ["HOST", "TARGET"]:
100+
self.module_instance.multi_target = False
101+
self.module_instance.targets = None
102+
89103
self.module_instance.options.set_option(args.name, args.value)
90104

91105
def complete_use(self, text, line, begidx, endidx):
@@ -193,6 +207,57 @@ def do_exploit(self, args):
193207
self._print_item(error, color=Fore.RED)
194208
return False
195209

210+
# 处理指定多个目标的情况
211+
if self.module_instance.multi_target:
212+
# 读取多个目标
213+
target_type = self.module_instance.target_type
214+
target_field = None
215+
216+
if target_type == "tcp":
217+
target_field = "HOST"
218+
elif target_type == "http":
219+
target_field = "URL"
220+
221+
target_filename = self.module_instance.options.get_option(target_field)
222+
223+
try:
224+
target_file = open(target_filename, 'r')
225+
self.module_instance.targets = []
226+
for line in target_file.readlines():
227+
self.module_instance.targets.append(line.strip())
228+
self.module_instance.multi_target = True
229+
except IOError as e:
230+
self._print_item(e, color=Fore.RED)
231+
return False
232+
233+
# 将targets数组中的目标写到队列中
234+
targets = self.module_instance.targets
235+
targets_queue = Queue()
236+
for target in targets:
237+
targets_queue.put(target)
238+
239+
while not targets_queue.empty():
240+
[target, port] = module.parse_ip_port(targets_queue.get())
241+
242+
exp = self.module_class.Exploit()
243+
exp.options.set_option(target_field, target)
244+
exp.options.set_option("TIMEOUT", self.module_instance.options.get_option("TIMEOUT"))
245+
if port:
246+
exp.options.set_option("PORT", port)
247+
else:
248+
exp.options.set_option("PORT", self.module_instance.options.get_option("PORT"))
249+
250+
exploit_result = exp.exploit()
251+
if exploit_result.status:
252+
self._print_item(exploit_result.success_message)
253+
else:
254+
self._print_item(exploit_result.error_message, color=Fore.RED)
255+
self.poutput("{style}[*]{style_end} module execution completed".format(
256+
style=Fore.BLUE + Style.BRIGHT,
257+
style_end=Style.RESET_ALL
258+
))
259+
return False
260+
196261
exploit_result = self.module_instance.exploit()
197262
if exploit_result.status:
198263
self._print_item("Exploit success!")

modules/exploits/server/redis_unauthorized.py

+11-27
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import socket
22
from lib.BaseExploit import BaseExploit
3-
from lib.ExploitOption import ExploitOption
43

54

65
class Exploit(BaseExploit):
@@ -17,31 +16,13 @@ def __init__(self):
1716
"service_name": "redis",
1817
"service_version": "*",
1918
})
20-
self.register_options([
21-
ExploitOption(
22-
name="host",
23-
required=True,
24-
description="The IP of the machine to be tested",
25-
value=None
26-
),
27-
ExploitOption(
28-
name="timeout",
29-
required=False,
30-
description="The timeout for connecting to redis",
31-
value=10,
32-
),
33-
ExploitOption(
34-
name="port",
35-
required=False,
36-
description="redis port",
37-
value=6379
38-
)
39-
])
19+
self.register_tcp_target(port_value=6379)
4020

4121
def check(self):
42-
host = self.options.get_option("host")
43-
port = int(self.options.get_option("port"))
44-
timeout = self.options.get_option("timeout")
22+
host = self.options.get_option("HOST")
23+
port = int(self.options.get_option("PORT"))
24+
timeout = int(self.options.get_option("TIMEOUT"))
25+
print(type(host), type(port), type(timeout))
4526
try:
4627
socket.setdefaulttimeout(timeout)
4728
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
@@ -54,14 +35,17 @@ def check(self):
5435
"host": host,
5536
"port": port,
5637
},
57-
message="Host {} exists redis unauthorized vulnerability".format(host)
38+
message="Host {host}:{port} exists redis unauthorized vulnerability".format(host=host, port=port)
5839
)
5940
else:
6041
self.results.failure(
61-
error_message="Host {} does not exists redis unauthorized vulnerability".format(host)
42+
error_message="Host {host}:{port} does not exists redis unauthorized vulnerability".format(
43+
host=host,
44+
port=port
45+
)
6246
)
6347
except Exception as e:
64-
self.results.failure(error_message=e)
48+
self.results.failure(error_message="Host {host}:{port}: {error}".format(host=host, port=port, error=e))
6549
return self.results
6650

6751
def exploit(self):

utils/module.py

+18
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
from utils.files import ROOT_PATH
33
from fnmatch import fnmatchcase
44
from importlib import import_module
5+
from ipaddress import ip_address
6+
from urllib.parse import urlparse
57

68

79
def name_convert(name):
@@ -40,3 +42,19 @@ def get_local_modules():
4042
module_info['description']
4143
))
4244
return local_modules
45+
46+
47+
def parse_ip_port(netloc):
48+
"""
49+
parse netloc to [ip, port]
50+
:param netloc: string eg:127.0.0.1:80
51+
:return: array eg: [127.0.0.1, 80]
52+
"""
53+
try:
54+
ip = str(ip_address(netloc))
55+
port = None
56+
except ValueError:
57+
parsed = urlparse('//{}'.format(netloc))
58+
ip = str(ip_address(parsed.hostname))
59+
port = parsed.port
60+
return ip, port

0 commit comments

Comments
 (0)