君子藏器于身待时而动,安全不露圭角覆盂之安。
——AnonySec
https://payloads.cn
项目地址:Metasploit Modules
前言
本文开始学习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数据包,也可以直接将Request
与Response
输出查看。
1 2
| print_good ("Request: \n#{res.request.to_s}") print_good ("Response: \n#{res.to_s} \n")
|
完整的Request
与Response
Http数据包请求。
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 })
|
至此,通过HttpClient mixin
,已经实现了Http数据包的Get与Post请求发送。
Module
某邮服,可通过用户接口,枚举存在的用户名。
接下来要将该利用方式转化为Metasploit的扫描模块。
字典读取
首先要探测用户接口是否存在,之后才能继续下面操作。
打开用户名字典,进行读取。
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
|
数据处理
因请求数据是json格式,所以post_data
需要进行转换。
1 2 3 4 5
| data = {"email":"#{user}"} print_status ("#{data}")
post_data = data.to_json print_status ("json: #{post_data}")
|
转换前后对比:
因Response
返回包是xml格式,所以要进行xml解析。
这样,就通过Metasploit实现了该利用模块的Http数据包的发送与接收。
1 2 3
| xml = res.get_xml_document print_good ("Response_xml\n#{xml}")
|
最后将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, "")
string = xml.at('string')
text = string.text
if not text.empty? print_good ("#{user} : #{text}") output = file_local_write( outfile ,"#{user} : #{text}") end print_status ("OutFile: #{outfile}")
|
完整模块运行Demo:
References