-
Notifications
You must be signed in to change notification settings - Fork 3
怎么使用 datastore 参数
数据存储选项是一种可以由用户设置的变量, 允许 Metasploit 的各种组件在使用过程中更加可配置. 例如, 在 msfconsole 中, 你可以设置 ConsoleLogging 选项以记录所有控制台输入/输出 - 这对于在渗透测试期间的文档目的来说非常方便. 当你加载一个模块时, mixin(s) 或模块会注册更多的选项. 一些常见的包括用于服务器端漏洞利用或辅助模块的 RHOSTS 和 RPORT, 用于客户端模块的 SRVHOST 等. 找出可以设置的数据存储选项的最佳方法是使用以下命令:
-
show options
- 向你展示所有基本选项. -
show advanced
- 向你显示所有高级选项. -
show missing
- 显示你尚未配置的所有必需选项. -
set
- 向你展示一切. 显然, 你还使用此命令设置选项.
选项来源: ModuleDataStore, active_module, session, and framework
在用户方面, 数据存储选项被视为全局或模块级别: 全局意味着所有模块都可以使用该选项, 可以使用 setg
命令设置. 模块级意味着只有你正在使用的特定模块会记住该数据存储选项, 其他组件不会知道它. 如果你首先加载模块, 然后使用 set
命令, 则你正在设置模块级选项, 如下所示:
msf > use exploit/windows/smb/ms08_067_netapi
msf exploit(ms08_067_netapi) > set rhost 10.0.1.3
rhost => 10.0.1.3
在开发方面, 事情有点疯狂. 数据存储选项实际上可以在至少四个不同的来源中找到: ModuleDataStore 对象, active_module, session 对象 和 framework 对象.
如果你只是在进行模块开发, 那么你可以信任的最佳来源是 ModuleDataStore 对象. 在将所需选项交给你之前, 此对象具有特定的加载顺序: 如果可以在模块的数据存储中找到该选项, 它将为你提供. 如果没有找到, 它会给你一个来自框架的. 以下是如何读取模块中的数据存储选项的示例:
current_host = datastore['RHOST']
如果你的开发工作在模块领域之外, 则很有可能甚至不用 ModuleDataStore 对象. 但在某些情况下, 你仍然可以从驱动程序的 active_module 访问器中读取. 或者, 如果你可以访问 ModuleCommandDispatcher, 那么也有一个 mod 方法可以为你提供相同的功能, 有时 mixin 在调度模块时会在 run_simple 方法中传递它. 你可以查看的一个示例是 Msf::Ui::Console::CommandDispatcher::Auxiliary 类.
在某些情况下, 例如在后期利用中运行脚本, 你可能没有 ModuleDataStore 甚至 active_module, 但你仍然应该有一个会话对象. 应该有一个 exploit_datastore, 它为你提供所有数据存储选项:
session.exploit_datastore
如果你无权访问模块或会话对象, 那么最后一个源显然是框架对象, 并且始终存在框架对象. 但是, 就像我们之前所说的, 如果用户设置了模块级选项, 其他组件将不会看到它, 这包括框架对象:
framework.datastore
所以现在你知道有多种数据存储选项来源. 并且希望在这一点上你很清楚并非所有来源都必然共享相同的东西. 如果你必须尝试一切, 作为一般规则, 这应该是你的加载顺序:
- 尝试 ModuleDataStore
- 尝试 active_module
- 尝试 session
- 尝试 framework
有核心数据存储选项类型都在 option_container.rb 文件中定义为类. 你应该始终选择最合适的一个, 因为每个都有自己的输入验证器.
在数据存储注册期间初始化选项时, 它应采用以下格式:
OptSomething.new(option_name, [boolean, description, value, *enums*], aliases: *aliases*, conditions: *conditions*)
- option_name - 明确表示数据存储选项的名称.
- boolean - 第一个属性, true 表示这是必需选项, false 表示可选.
- description - 关于此选项的简短说明
- value - 一个默认值. 请注意, 如果第一个属性为 false, 则无需提供值, 它会自动设置为 nil.
-
enums - 可选, 可接受值的数组, 例如
%w[ LEFT RIGHT ]
. - aliases - 可选, 仅关键字 引用此选项的附加名称数组. 这在 重命名 datastore 选项 以保持向后兼容性时很有用. 有关详细信息, 请参阅重命名数据存储选项部分
- conditions - 可选, 关键字 应显示选项的条件数组. 这可以用来隐藏选项, 因为它们是根据其他配置无关的. 有关详细信息, 请参阅 过滤 datastore 选项 部分.
现在让我们看看可用的类有哪些:
IPv4 地址的输入. 代码示例:
OptAddress.new('IP', [ true, 'Set an IP', '10.0.1.3' ])
一个 IPv4 地址范围的输入, 例如: 10.0.1.1-10.0.1.20 或 10.0.1.1/24. 你还可以提供文件路径而不是范围, 它会自动将该文件视为 IP 列表. 或者, 如果你执行 rand:3 语法, 3 表示 3 次, 它将为你生成 3 个随机 IP. 基本代码示例:
OptAddressRange.new('Range', [ true, 'Set an IP range', '10.0.1.3-10.0.1.23' ])
布尔选项. 它将验证输入是真还是假的变量. 例如: y、yes、n、no、0、1 等. 代码示例:
OptBool.new('BLAH', [ true, 'Set a BLAH option', false ])
基本上, 这会将输入限制为特定的选择. 例如, 如果你希望输入是"apple"或"orange", 而不是其他, 那么 OptEnum 就是你的最佳选择. 代码示例:
# 选择 apple 或 orange, 默认为苹果
OptEnum.new('FRUIT', [ true, 'Set a fruit', 'apple', ['apple', 'orange']])
这可以是十六进制值, 也可以是十进制值.
OptInt.new('FILE', [ true, 'A hex or decimal', 1024 ])
如果你的数据存储选项要求提供本地文件路径, 请使用此选项.
OptPath.new('FILE', [ true, 'Load a local file' ])
对于打算用作端口号的输入. 此数字应介于 0 - 65535 之间. 代码示例:
OptPort.new('RPORT', [ true, 'Set a port', 21 ])
它实际上与 OptString 的功能完全相同.
选项是一个正则表达式.
OptRegexp.new('PATTERN', [true, 'Match a name', '^alien']),
其它类型:
在某些情况下, 可能没有适合你的 datastore 选项类型. 最好的例子是一个 URL: 即使没有 OptUrl 这样的东西, 你可以做的是使用 OptString 类型, 然后在你的模块中, 对其进行一些验证, 如下所示:
def valid?(input)
if input =~ /^http:\/\/.+/i
return true
else
# 这里可以考虑抛出 OptionValidateError
return false
end
end
if valid?(datastore['URL'])
# 我们可以用 URL 做一些事情
else
# 不是我们正在寻找的格式. 拒绝做任何事情.
end
通常用于字符串选项. 如果输入以"file://"开头, OptString 也会自动假定这是一个文件, 并从中读取. 但是, 发生这种情况时没有文件路径验证, 所以如果你想加载一个文件, 你应该使用 OptPath 代替, 然后自己读取文件. 代码示例:
OptString.new('MYTEST', [ true, 'Set a MYTEST option', 'This is a default value' ])
register_options
方法可以注册多个基本数据存储选项. 基本数据存储选项是必须配置的选项, 例如服务器端漏洞利用中的 RHOST 选项. 或者它非常常用, 例如登录模块中的各种用户名/密码选项.
以下是在一个模块中注册多个数据存储选项的示例:
register_options(
[
OptString.new('SUBJECT', [ true, 'Set a subject' ]),
OptString.new('MESSAGE', [ true, 'Set a message' ])
])
register_advanced_options
方法可以注册多个高级 datastore 选项. 高级 datastore 选项是不需要用户在使用模块之前进行配置的选项. 例如, 代理选项几乎总是被认为是"advanced". 但当然, 这也可能意味着大多数用户会觉得难以配置.
注册高级选项的示例:
register_advanced_options(
[
OptInt.new('Timeout', [ true, 'Set a timeout, in seconds', 60 ])
])
方法可以取消注册基本或高级选项. 用法非常简单:
deregister_options('OPTION1', 'OPTION2', 'OPTION3')
当 mixin 已经注册了一个数据存储选项时, 仍然有办法从模块中更改默认值. 你可以使用 register_options 方法, 也可以在模块的元数据中添加 DefaultOptions 键. 首选使用 DefaultOptions 键, 因为选项的描述和其他属性将保持不变.
使用 register_options
的优点之一是, 如选项是高级 datastore 的, 则允许它位于基本选项菜单上, 这意味着当人们在 msfconsole 上执行 show options
时, 该选项将出现. 你还可以更改选项描述, 以及是否需要使用此方法.
当 Metasploit 初始化一个模块时, 一个 import_defaults 方法被调用. 此方法将更新所有现有的数据存储选项 (这就是为什么 register_options
可用于更新默认值的原因) , 然后它会专门从模块的元数据中检查 DefaultOptions 键, 并再次更新.
下面是一个利用 DefaultOptions 键的漏洞利用模块初始化部分的示例:
def initialize(info={})
super(update_info(info,
'Name' => "Module name",
'Description' => %q{
This is an example of setting the default value of RPORT using the DefaultOptions key
},
'License' => MSF_LICENSE,
'Author' => [ 'Name' ],
'References' =>
[
[ 'URL', '' ]
],
'Platform' => 'win',
'Targets' =>
[
[ 'Windows', { 'Ret' => 0x41414141 } ]
],
'Payload' =>
{
'BadChars' => "\x00"
},
'DefaultOptions' =>
{
'RPORT' => 8080
},
'Privileged' => false,
'DisclosureDate' => "",
'DefaultTarget' => 0))
end
目前, 在运行时修改数据存储选项的最安全方法是覆盖方法. 例如, 一些 mixin 像这样检索 RPORT 选项:
def rport
datastore['RPORT']
end
在这种情况下, 你可以从模块中覆盖此 rport 方法, 并返回不同的值:
def rport
80
end
这样, 当一个 mixin 需要该信息时, 它将以 80 的值结束, 而不是 datastore['RPORT']
中实际存在的任何值.
普通选项总是大写, 高级选项是 CamelCase, 具有类似目的的高级选项是 Prefixed::CamelCase.
选项可以重命名并保持向后兼容性, 方法是使用 alias:
选项中的关键字参数. 例如, 要重命名 OldOption
为 NewOption
, 需要定义如下
OptString.new('NewOption', [true, 'A (sort of) new option', 'hello'], aliases: %w[ OldOption ])
选项可以在某些条件下根据 conditions
关键字定义的条件进行隐藏. 这允许在基于另一个选项、选定目标或选定操作的值不相关时隐藏选项.
条件的语法是 *thing* *operator* *value*
.
- thing - ACTION、TARGET 或 datastore 选项的名称之一.
-
operator -
==
,!=
,in
,nin
之一. 在in
和nin
(not-in) 的情况下, 该值是一个数组. - value - 在条件中检查的值.
当条件评估为真时, 该选项被视为活动并显示给用户. 默认情况下, 未定义条件的 datastore 选项处于活动状态.
-
conditions: %w[VERSION == 5]
- 当VERSION
数据存储选项为 5 时处于活动状态. -
conditions: ['ACTION', 'in', %w[SSRF EXEC SECSTORE]]
- 当ACTION
是SSRF
、EXEC
或SECSTORE
之一时激活选项.