• Metasploit之插件-钉钉上线通知


    前言

    • 当有新的主机上线时,希望可以及时得收到通知,Metasploit官方本来就有一个邮件会话上线通知的插件plugins/session_notifier.rb,但是这需要发件服务器,也不一定能及时收到,所以就写了一个钉钉机器人通知。
    • 实现这个需求需要写一个插件,能获取到一个会话上线的事件,按照钉钉的开发文档发送一个请求。

    插件编写

    • lib/msf/core/plugin.rb,插件的基类,全部插件都要实现基类的接口,管理控制台调度程序。
    • lib/msf/core/plugin_manager.rb,插件管理器,实现了loadunload方法

    插件可以通过添加新特性、新的用户界面命令或任何其他任意方法来更改框架的行为。

    • 官方有一个例子plugins/sample.rb,里面ConsoleCommandDispatcher是实现控制台调度程序的一个类。

    class ConsoleCommandDispatcher
        include Msf::Ui::Console::CommandDispatcher
    
        #
        # The dispatcher's name.
        #
        def name
            "Sample"
        end
    
        #
        # Returns the hash of commands supported by this dispatcher.
        #
        def commands
            {
                "sample" => "A sample command added by the sample plugin"
            }
        end
    
        #
        # This method handles the sample command.
        #
        def cmd_sample(*args)
            print_line("You passed: #{args.join(' ')}")
        end
    end
    
    • 上面的代码功能:添加一个sample命令到控制台调度器(help命令可以看见),cmd_sample为这个命令的动作。
    • 如果你的插件需要控制台操作设置就需要使用到插件基类里面的add_console_dispatcher方法添加控制台调度程序。

    事件通知订阅

    • 因为我们只需要会话上线的事件,所以只需要在当前的类将on_session_open方法实现,其他会话事件可以在lib/msf/core/session.rb文件中找到。
    • 实现了on_session_open方法还不行,因为没有程序调用它,所以还要将它加入session_event_subscribers会话事件的订阅器。
    self.framework.events.add_session_subscriber(self)
    
    • 事件的调度器可以在lib/msf/core/event_dispatcher.rb找到,还没添加事件订阅是会话的事件订阅器只有两个。

    • 添加后,即将当前类添加到会话事件订阅器,当有会话事件发生时会到session_event_subscribers这个列表中调用下面的方法。妙啊!

    # 不写事件方法名,当方法名找不到是自动调用下面的函数处理全部事件,下面以on_session_open事件为例
    def method_missing(name, *args)
        event,type,rest = name.to_s.split("_", 3)  # event => on; type => session; rest => open
        subscribers = "#{type}_event_subscribers"  # 得到拼接会话订阅器列表:session_event_subscribers
        found = false
        case event
        when "on"
            if respond_to?(subscribers, true)
                found = true
                self.send(subscribers).each do |sub|
                    next if not sub.respond_to?(name, true)  # 我们在写插件时有定义on_session_open这个方法,当然不会跳过
                    sub.send(name, *args)  # 通过反射判断session_event_subscribers的类中有没有on_session_open这个方法,用就调用
                end
            else
                (general_event_subscribers + custom_event_subscribers).each do |sub|
                    next if not sub.respond_to?(name, true)
                    sub.send(name, *args)
                    found = true
                end
            end
        when "add"
            if respond_to?(subscribers, true)
                found = true
                add_event_subscriber(self.send(subscribers), *args)
            end
        when "remove"
            if respond_to?(subscribers, true)
                found = true
                remove_event_subscriber(self.send(subscribers), *args)
            end
        end
        return found
    end
    

    发送Webhook请求

    • 按照钉钉的开发文档发送markdown格式的消息,通过响应的错误码判断是否发送成功。
    def send_text_to_dingtalk(session)
        # https://ding-doc.dingtalk.com/doc#/serverapi2/qf2nxq/9e91d73c
        uri_parser = URI.parse(dingtalk_webhook)
        markdown_text = "## You have a new #{session.type} session!
    
    " 
            "**platform** : #{session.platform}
    
    " 
            "**tunnel** : #{session.tunnel_to_s}
    
    " 
            "**arch** : #{session.arch}
    
    " 
            "**info** : > #{session.info ? session.info.to_s : nil}"
        json_post_data = JSON.pretty_generate({
            msgtype: 'markdown',
            markdown: { title: 'Session Notifier', text: markdown_text }
            })
        http = Net::HTTP.new(uri_parser.host, uri_parser.port)
        http.use_ssl = true
        request = Net::HTTP::Post.new(uri_parser.request_uri)
        request.content_type = 'application/json'
        request.body = json_post_data
        res = http.request(request)
        body = JSON.parse(res.body)
        print_status((body['errcode'] == 0) ? 'Session notified to DingTalk.' : 'Failed to send notification.')
    end
    

    使用演示

    • 创建钉钉机器人,设置关键词:session

    msf6 exploit(multi/handler) > load session_notifier 
    [*] Successfully loaded plugin: SessionNotifier
    msf6 exploit(multi/handler) > set_session_dingtalk_webhook https://oapi.dingtalk.com/robot/send?access_token=5a439cc0009abd551a97e1302a964801da2f3ffe5ba06e97d19294a55202caa3
    msf6 exploit(multi/handler) > start_session_notifier 
    [*] DingTalk notification started.
    msf6 exploit(multi/handler) > run
    
    [*] Started reverse TCP handler on 192.168.56.1:7788 
    [*] Sending stage (175174 bytes) to 192.168.56.105
    [*] Meterpreter session 1 opened (192.168.56.1:7788 -> 192.168.56.105:1078) at 2020-10-04 11:08:54 +0800
    [*] Session notified to DingTalk.
    
    meterpreter > 
    

  • 相关阅读:
    使用yum时,保留下载包设置
    df命令
    Linux Shell脚本实现根据进程名杀死进程
    centos 清理内存缓存
    sgdisk常用操作
    CentOS7 bonding配置
    linux下显示dd命令的进度:
    OSD磁盘日常监控
    flashcache
    Elasticsearch request body检索
  • 原文地址:https://www.cnblogs.com/Kali-Team/p/14257120.html
Copyright © 2020-2023  润新知