Skip to content

Commit 6f621ef

Browse files
committed
docs: update development docs.
1 parent 8cbd0d3 commit 6f621ef

File tree

1 file changed

+108
-110
lines changed

1 file changed

+108
-110
lines changed

docs/framework/development.rst

+108-110
Original file line numberDiff line numberDiff line change
@@ -9,77 +9,92 @@
99

1010
我会长期坚持维护该模块库,欢迎大家加入。共勉。
1111

12-
模块基本结构
12+
概述
1313
-------------
1414

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+
1536
基本代码: ::
1637

17-
import requests
38+
# 请求redis需要socket 故引入socket
39+
import socket
1840
from lib.BaseExploit import BaseExploit
19-
from lib.ExploitOption import ExploitOption
2041

2142

2243
class Exploit(BaseExploit):
23-
2444
def __init__(self):
2545
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"],
3050
"references": [
31-
"参考资料/漏洞来源网址,可填写多个",
51+
"https://www.freebuf.com/column/158065.html",
3252
],
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": "*",
3656
})
57+
# 因为redis只需要提供ip和端口,所以这里注册tcp的目标。
58+
self.register_tcp_target(port_value=6379)
3759

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 传入错误信息
5760
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))
6594
return self.results
6695

67-
# exploit方法为攻击模块 结果同check方法一样处理
68-
# 注意:不要写可以导致系统崩溃的Exploit方法。
6996
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()
8398

8499
撰写模块
85100
---------
@@ -122,26 +137,7 @@
122137
"service_name": "redis",
123138
"service_version": "*",
124139
})
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)
145141

146142
这里来解释一下,首先看 ``__init__`` 方法的第一行: ::
147143

@@ -163,44 +159,31 @@
163159
"service_version": "*",
164160
})
165161

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``
194176

195177
完成check方法
196178
--------------
197179

198180
check方法主要写检测漏洞是否存在,不可存在攻击行为。 代码如下: ::
199181

200182
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+
204187
try:
205188
socket.setdefaulttimeout(timeout)
206189
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
@@ -213,14 +196,17 @@ check方法主要写检测漏洞是否存在,不可存在攻击行为。 代
213196
"host": host,
214197
"port": port,
215198
},
216-
message="Host {} exists redis unauthorized vulnerability".format(host)
199+
message="Host {host}:{port} exists redis unauthorized vulnerability".format(host=host, port=port)
217200
)
218201
else:
219202
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+
)
221207
)
222208
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))
224210
return self.results
225211

226212
首先前三行使用 ``self.options.get_option()`` 方法获取模块参数。
@@ -234,16 +220,19 @@ check方法主要写检测漏洞是否存在,不可存在攻击行为。 代
234220
"host": host,
235221
"port": port,
236222
},
237-
message="Host {} exists redis unauthorized vulnerability".format(host)
223+
message="Host {host}:{port} exists redis unauthorized vulnerability".format(host=host, port=port)
238224
)
239225

240226
漏洞不存在则执行了 ``self.results.failure`` 方法,传入失败信息: ::
241227

242228
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+
)
244233
)
245234

246-
check方法最后一行一定要返回 ``self.results`` 出来。 ::
235+
check方法一定要返回 ``self.results`` 出来。 ::
247236

248237
return self.results
249238

@@ -257,3 +246,12 @@ check方法最后一行一定要返回 ``self.results`` 出来。 ::
257246
return self.check()
258247

259248
exploit方法也一定要返回 ``self.results`` 出来, 因为check方法也是返回 ``self.results`` ,所以这里可以直接调用 ``self.check()`` 。
249+
250+
更多案例
251+
--------------
252+
253+
现在框架大部分功能已经完成了,我自己会开始写一些模块。
254+
255+
大家可以参考我已经写好的模块,来完成自己的模块。
256+
257+
所有模块都在github仓库中modules目录下。

0 commit comments

Comments
 (0)