9
9
10
10
我会长期坚持维护该模块库,欢迎大家加入。共勉。
11
11
12
- 模块基本结构
12
+ 概述
13
13
-------------
14
14
15
+ 在 WebPocket 中撰写一个完整的模块,需要符合如下要求:
16
+
17
+ * 模块必须为一个 ``class `` 且类名为 ``Exploit ``
18
+ * ``Exploit `` 类必须继承自 ``BaseExploit `` (通过 ``from lib.BaseExploit import BaseExploit `` 引入 )
19
+ * 模块必须包含 ``__init__ `` 方法,必须调用父类的 ``__init__ `` 方法,(通过 ``super(Exploit, self).__init__() `` 调用)
20
+ * 模块必须填写相关信息,使用 ``self.update_info() `` 方法
21
+ * POC的目标目前主要分为 ``http `` 和 ``tcp `` 类型,使用 ``self.register_tcp_target() `` 注册tcp类型的目标。 使用 ``self.register_tcp_target() `` 注册http类型的目标。
22
+ * 注册以后的目标可以使用 ``self.options.get_option `` 获取其中的参数。
23
+ * ``check `` 方法用来实现检测漏洞,不可存在攻击行为。
24
+ * ``exploit `` 方法用来实现攻击行为,但也不可进行影响服务器正常运行的操作。
25
+ * 在 ``check `` 和 ``exploit `` 方法中,如果测试成功,调用 ``self.results.success() `` 方法保存结果。失败调用 ``self.results.failure() `` 保存结果。
26
+ * 不管 ``check/exploit `` 成功与否,都要最后返回 ``self.results `` (将来可能会移除该要求,但目前暂时还是需要返回。)。
27
+
28
+ 在写模块的过程中,如果使用 ``pycharm `` 可以跟进上述的方法查看代码,方便大家理解,如有任何疑问或者建议,欢迎联系我。
29
+
30
+ 微信:StrikerSb
31
+
32
+
33
+ 案例:redis未授权检测模块
34
+ ----------------------------
35
+
15
36
基本代码: ::
16
37
17
- import requests
38
+ # 请求redis需要socket 故引入socket
39
+ import socket
18
40
from lib.BaseExploit import BaseExploit
19
- from lib.ExploitOption import ExploitOption
20
41
21
42
22
43
class Exploit(BaseExploit):
23
-
24
44
def __init__(self):
25
45
super(Exploit, self).__init__()
26
- self.update_info(info= {
27
- "name": "模块名称 可用于检索 ",
28
- "description": "模块描述 可用于检索 ",
29
- "author": ["作者, 可以填写多个 "],
46
+ self.update_info({
47
+ "name": "redis unauthorized ",
48
+ "description": "redis unauthorized ",
49
+ "author": ["unknown "],
30
50
"references": [
31
- "参考资料/漏洞来源网址,可填写多个 ",
51
+ "https://www.freebuf.com/column/158065.html ",
32
52
],
33
- "disclosure_date": "漏洞发现时间 ",
34
- "service_name": "服务名称,如:phpcms、zabbix、php、apache ",
35
- "service_version": "服务版本 ",
53
+ "disclosure_date": "2019-02-28 ",
54
+ "service_name": "redis ",
55
+ "service_version": "* ",
36
56
})
57
+ # 因为redis只需要提供ip和端口,所以这里注册tcp的目标。
58
+ self.register_tcp_target(port_value=6379)
37
59
38
- # 注册模块所需的参数, required为True的模块,默认值请设置为None
39
- self.register_options([
40
- ExploitOption(
41
- name="host",
42
- required=True,
43
- description="The target domain",
44
- value=None
45
- ),
46
- ExploitOption(
47
- name="password",
48
- required=True,
49
- description="webshell password",
50
- value=None
51
- ),
52
- ])
53
-
54
- # check 方法仅做漏洞检测,不可进行攻击
55
- # 测试存在漏洞调用 self.results.success方法,传入结果
56
- # 测试不存在漏洞调用 self.results.failure 传入错误信息
57
60
def check(self):
58
- webshell = "http://www.hackersb.cn/shell.php"
59
- if len(webshell):
60
- self.results.success(
61
- message="Target {} has vul".format(self.options.get_option("host"))
62
- )
63
- else:
64
- self.results.failure(error_message="Target {} no vulnerability".format(self.options.get_option("host")))
61
+ # 这三个参数都是self.register_tcp_target方法注册的,这里可以直接调用
62
+ host = self.options.get_option("HOST")
63
+ port = int(self.options.get_option("PORT"))
64
+ timeout = int(self.options.get_option("TIMEOUT"))
65
+
66
+ # 执行测试的整个过程最好放进try里面,然后在except里面捕获错误直接调用self.results.failure打印出报错。
67
+ try:
68
+ socket.setdefaulttimeout(timeout)
69
+ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
70
+ s.connect((host, port))
71
+ s.send(bytes("INFO\r\n", encoding="utf-8"))
72
+ result = s.recv(1024)
73
+ if bytes("redis_version", encoding="utf-8") in result:
74
+ # 存在漏洞 调用该方法 data可传入一个字典,目前没有什么用,也可以不传。
75
+ self.results.success(
76
+ data={
77
+ "host": host,
78
+ "port": port,
79
+ },
80
+ # 由于可能会执行多个目标,所以结果里面最好写上目标和端口,方便辨认。
81
+ message="Host {host}:{port} exists redis unauthorized vulnerability".format(host=host, port=port)
82
+ )
83
+ else:
84
+ # 不存在漏洞 调用self.results.failure方法传入错误信息。
85
+ self.results.failure(
86
+ error_message="Host {host}:{port} does not exists redis unauthorized vulnerability".format(
87
+ host=host,
88
+ port=port
89
+ )
90
+ )
91
+ except Exception as e:
92
+ # 执行错误,使用self.results.failure传入错误信息。
93
+ self.results.failure(error_message="Host {host}:{port}: {error}".format(host=host, port=port, error=e))
65
94
return self.results
66
95
67
- # exploit方法为攻击模块 结果同check方法一样处理
68
- # 注意:不要写可以导致系统崩溃的Exploit方法。
69
96
def exploit(self):
70
- requests.get(self.options.get_option("host"))
71
- webshell = "http://www.hackersb.cn/shell.php"
72
- if len(webshell):
73
- self.results.success(
74
- data={
75
- "target": self.options.get_option("host"),
76
- "webshell": webshell
77
- },
78
- message="Webshell: {}".format(webshell)
79
- )
80
- else:
81
- self.results.failure(error_message="No vulnerability")
82
- return self.results
97
+ return self.check()
83
98
84
99
撰写模块
85
100
---------
122
137
"service_name": "redis",
123
138
"service_version": "*",
124
139
})
125
- self.register_options([
126
- ExploitOption(
127
- name="host",
128
- required=True,
129
- description="The IP of the machine to be tested",
130
- value=None
131
- ),
132
- ExploitOption(
133
- name="timeout",
134
- required=False,
135
- description="The timeout for connecting to redis",
136
- value=10,
137
- ),
138
- ExploitOption(
139
- name="port",
140
- required=False,
141
- description="redis port",
142
- value=6379
143
- )
144
- ])
140
+ self.register_tcp_target(port_value=6379)
145
141
146
142
这里来解释一下,首先看 ``__init__ `` 方法的第一行: ::
147
143
163
159
"service_version": "*",
164
160
})
165
161
166
- 然后使用 ``self.register_options `` 方法注册三个参数,分别是 ``host ``, ``timeout ``, ``port ``,
167
-
168
- * host 表示需要测试漏洞的主机ip
169
- * timeout 表示连接redis超时时间
170
- * port 表示redis端口
171
-
172
- 代码如下: ::
173
-
174
- self.register_options([
175
- ExploitOption(
176
- name="host",
177
- required=True,
178
- description="The IP of the machine to be tested",
179
- value=None
180
- ),
181
- ExploitOption(
182
- name="timeout",
183
- required=False,
184
- description="The timeout for connecting to redis",
185
- value=10,
186
- ),
187
- ExploitOption(
188
- name="port",
189
- required=False,
190
- description="redis port",
191
- value=6379
192
- )
193
- ])
162
+ 然后使用 ``self.register_tcp_target `` 方法注册了一个tcp类型的目标,这个方法自动为我们注册了如下参数: ::
163
+
164
+ self.register_options([
165
+ ExploitOption(name="HOST", required=True, description="The IP address to be tested"),
166
+ ExploitOption(name="PORT", required=True, description="The port to be tested", value=port_value),
167
+ ExploitOption(name="TIMEOUT", required=True, description="Connection timeout", value=timeout_value),
168
+ ExploitOption(name="THREADS", required=True, description="The number of threads", value=threads_value)
169
+ ])
170
+
171
+ 对于我们redis未授权的漏洞,需要HOST和PORT已经够了,所以不需要再注册多余的参数。
172
+
173
+ 如果需要额外注册参数,可以调用 ``self.register_options `` 方法,传入一个list,list包含 ``ExploitOption `` 对象。
174
+
175
+ ``ExploitOption `` 引入方法:``from lib.ExploitOption import ExploitOption ``
194
176
195
177
完成check方法
196
178
--------------
197
179
198
180
check方法主要写检测漏洞是否存在,不可存在攻击行为。 代码如下: ::
199
181
200
182
def check(self):
201
- host = self.options.get_option("host")
202
- port = int(self.options.get_option("port"))
203
- timeout = self.options.get_option("timeout")
183
+ host = self.options.get_option("HOST")
184
+ port = int(self.options.get_option("PORT"))
185
+ timeout = int(self.options.get_option("TIMEOUT"))
186
+
204
187
try:
205
188
socket.setdefaulttimeout(timeout)
206
189
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
@@ -213,14 +196,17 @@ check方法主要写检测漏洞是否存在,不可存在攻击行为。 代
213
196
"host": host,
214
197
"port": port,
215
198
},
216
- message="Host {} exists redis unauthorized vulnerability".format(host)
199
+ message="Host {host}:{port} exists redis unauthorized vulnerability".format(host=host, port=port )
217
200
)
218
201
else:
219
202
self.results.failure(
220
- error_message="Host {} does not exists redis unauthorized vulnerability".format(host)
203
+ error_message="Host {host}:{port} does not exists redis unauthorized vulnerability".format(
204
+ host=host,
205
+ port=port
206
+ )
221
207
)
222
208
except Exception as e:
223
- self.results.failure(error_message=e )
209
+ self.results.failure(error_message="Host {host}:{port}: {error}".format(host=host, port=port, error=e) )
224
210
return self.results
225
211
226
212
首先前三行使用 ``self.options.get_option() `` 方法获取模块参数。
@@ -234,16 +220,19 @@ check方法主要写检测漏洞是否存在,不可存在攻击行为。 代
234
220
"host": host,
235
221
"port": port,
236
222
},
237
- message="Host {} exists redis unauthorized vulnerability".format(host)
223
+ message="Host {host}:{port} exists redis unauthorized vulnerability".format(host=host, port=port )
238
224
)
239
225
240
226
漏洞不存在则执行了 ``self.results.failure `` 方法,传入失败信息: ::
241
227
242
228
self.results.failure(
243
- error_message="Host {} does not exists redis unauthorized vulnerability".format(host)
229
+ error_message="Host {host}:{port} does not exists redis unauthorized vulnerability".format(
230
+ host=host,
231
+ port=port
232
+ )
244
233
)
245
234
246
- check方法最后一行一定要返回 ``self.results `` 出来。 ::
235
+ check方法一定要返回 ``self.results `` 出来。 ::
247
236
248
237
return self.results
249
238
@@ -257,3 +246,12 @@ check方法最后一行一定要返回 ``self.results`` 出来。 ::
257
246
return self.check()
258
247
259
248
exploit方法也一定要返回 ``self.results `` 出来, 因为check方法也是返回 ``self.results `` ,所以这里可以直接调用 ``self.check() `` 。
249
+
250
+ 更多案例
251
+ --------------
252
+
253
+ 现在框架大部分功能已经完成了,我自己会开始写一些模块。
254
+
255
+ 大家可以参考我已经写好的模块,来完成自己的模块。
256
+
257
+ 所有模块都在github仓库中modules目录下。
0 commit comments