W3AF插件编写很具有模式化,因此编写完一个模块,其它模块的编写就很easy了,插件编写通常包括如下:
- 插件初始化
- 处理分装的请求
- 储存审计结果
为了讲解方便,这里以xss插件为例进行介绍,该插件位置为:/w3af/plugins/audit
插件初始化
插件初始化比较简单,各个插件根据需求在init()中进行初始化,这里不做赘述。
处理分装请求
该步骤是处理上游模块分装的请求,该请求数据W3AF称为FuzzableRequest,位置为:/w3af/core/data/request,该模块主要介绍如下:
- 请求数据(FuzzableRequest)介绍
- 数据处理介绍
请求数据
FuzzableRequest类主要是为了方便W3AF插件能够轻松处理不同注入点,通过查看其init()就能够容易知道该类的用途。
该类属性包括:self._method(请求方法)、self._cookie(请求cookie)、self._post_data(post数据)、 self._headers(header数据)、self._url(url数据)等等。
方法包括:get_default_headers(获取header)、from_parts(根据提供数据重组FuzzableRequest数据)等等。
数据处理介绍
数据处理最重要的两个函数是create_mutants(根据FuzzableReques构造请求)和self._send_mutants_in_threads(多进程处理FuzzableReques数据)。
create_mutants定义如下:
def create_mutants(freq, mutant_str_list, append=False,
fuzzable_param_list=[], orig_resp=None):
"""
@freq: FuzzableReques数据
@mutant_str_list:构造请求的payload,比如:xss中的PAYLOADS[]
@append:设置mutant_str_list是直接加在目标请求参数后面
@fuzzable_param_list:设置检查的参数,如果为空,则检查所有参数
@orig_resp:原始freq的响应页面数据
"""
result = []
fuzzer_config = _get_fuzzer_config() #获取用户的配置
#各种常见注入部分数据类型(包括get、post、cookie等)
mutant_tuple = (QSMutant, PostDataMutant, FileNameMutant, URLPartsMutant,
HeadersMutant, JSONMutant, CookieMutant, FileContentMutant,
XmlRpcMutant)
for mutant_kls in mutant_tuple:
#create_mutants调用父类mutant.py的create_mutants
new_mutants = mutant_kls.create_mutants(freq, mutant_str_list,
fuzzable_param_list, append,
fuzzer_config)
result.extend(new_mutants)
msg = 'Created %s mutants for "%s" (%s)'
count_data = {}
for mutant in result:
if mutant.get_mutant_type() in count_data:
count_data[mutant.get_mutant_type()] += 1
else:
count_data[mutant.get_mutant_type()] = 1
count_summary = ', '.join(['%s: %s' % (i, j) for i, j in count_data.items()])
om.out.debug(msg % (len(result), freq, count_summary))
if orig_resp is not None:
headers = orig_resp.get_headers()
etag, etag_header_name = headers.iget('ETag', None)
for m in result:
m.set_original_response_body(orig_resp.get_body())
if etag is not None:
orig_headers = m.get_headers()
orig_headers['If-None-Match'] = etag
m.set_headers(orig_headers)
return result
_send_mutants_in_threads定义如下:
def _send_mutants_in_threads(self, func, iterable, callback, **kwds):
"""
并行处理回调函数callback
"""
# You can use this code to debug issues that happen in threads, by
# simply not using them:
#
# for i in iterable:
# callback(i, func(i))
# return
#
# Now the real code:
func = return_args(func, **kwds)
imap_unordered = self.worker_pool.imap_unordered
for (mutant,), http_response in imap_unordered(func, iterable):
callback(mutant, http_response)
储存审计结果
审计结果是通过Vuln类记录审计结果,该类比较简单,包括属性name、desc、severity(漏洞安全级别)、response_ids(响应数据id)、plugin_name(审计插件name)等,方法包括set_severity(设置安全级别)等。