打造定制化的Metasploit—邮服用户枚举

君子藏器于身待时而动,安全不露圭角覆盂之安。

——AnonySec

https://payloads.cn

前言

本文开始学习Metasploit Web类模块开发,从HTTPClient类的了解,到Http数据包的Get与Post请求发送,从而实现模拟发包,最终到实现某邮服接口枚举用户的功能模块。

HTTPClient

HttpClient mixin是发送基本HTTP请求的模块。

Get

首先copy下官方的例子,进行发送get请求。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def run
uri = target_uri.path

res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(uri, 'admin', 'index.php'),
'vars_get' => {
'p1' => "This is param 1",
'p2' => "This is param 2"
}
})

if res && res.code == 200
print_good("I got a 200, awesome")
else
print_error("No 200, feeling blue")
end
end

在发包过程中,可以结合抓包,查看实际发送的Http数据包,也可以直接将RequestResponse输出查看。

1
2
print_good ("Request: \n#{res.request.to_s}")
print_good ("Response: \n#{res.to_s} \n")

458f79999f87ade732d24adf53f9b8b4

完整的RequestResponseHttp数据包请求。

3e45864171a4fac55850e781894af9c4

Post

Post请求只需要将'method'=>'POST',并加上post_data

1
2
3
4
5
6
7
post_data = ("username=admin")
res = send_request_cgi({
'method' => 'POST',
'uri' => normalize_uri(uri, '/index.html'),
'ctype' => 'text/x-json',
'data' => post_data
})

eec9e637834c522bdf00dfcf55d25d84

至此,通过HttpClient mixin,已经实现了Http数据包的Get与Post请求发送。


Module

某邮服,可通过用户接口,枚举存在的用户名。
接下来要将该利用方式转化为Metasploit的扫描模块。

c5f3df33a2484b8d5e4cd33d1209607f

字典读取

首先要探测用户接口是否存在,之后才能继续下面操作。
打开用户名字典,进行读取。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
if res.code.to_s == '200'
print_status("Exist username interface, start enumerating ...")
# 数组:用户名行分割
queue = []
File.open(datastore['USER_FILE']).each_line do |users|
queue << users.strip
end
print_status ("#{queue}")
while(not queue.empty?)
# 删除并获取数组第一个元素
user = queue.shift
print_status ("#{user}")
end
else
print_error("Exist not username interface")
end

5beb24b94ec0e78d9c7d2c65e3345916

数据处理

因请求数据是json格式,所以post_data需要进行转换。

1
2
3
4
5
data = {"email":"#{user}"}
print_status ("#{data}")
# 转换json
post_data = data.to_json
print_status ("json: #{post_data}")

转换前后对比:

04832436d916486b8b5f1a8e889fbfd6

Response返回包是xml格式,所以要进行xml解析。
这样,就通过Metasploit实现了该利用模块的Http数据包的发送与接收。

1
2
3
# 解析xml
xml = res.get_xml_document
print_good ("Response_xml\n#{xml}")

56739b0c6c78048edee7a040b287271f

最后将Response_xml中的数据进行处理,并把存在的用户名写入txt文本中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 输出文件格式
outfile = store_loot(
"MailUser",
"text/plain",
rhost,
"")

# at查找string元素
string = xml.at('string')
# text方法也可以被用作去除所有HTML标签
text = string.text
# print_status ("#{text}")
if not text.empty?
print_good ("#{user} : #{text}")
# 存在用户写入文件
output = file_local_write( outfile ,"#{user} : #{text}")
end
print_status ("OutFile: #{outfile}")

f25fba50292524c0ffb39a4bbdcd9839

完整模块运行Demo:

47840989779f7c20a84e9f878ea41149

References


xq