fscan/Plugins/services/activemq/plugin.go
ZacharyZcR ecc79aa9b8 feat: 实现ActiveMQ消息队列服务专业扫描插件
新增功能:
- 基于STOMP协议的ActiveMQ弱密码检测
- 完整的多语言i18n支持(中英文)
- 自动信息收集和权限识别
- 队列枚举和管理权限检测
- 优化的Docker测试环境配置

技术特性:
- 支持端口61613(STOMP)和61614(STOMP+SSL)
- 智能用户权限分析
- 异步利用执行机制
- 统一的插件架构设计
- 完善的错误处理和日志记录

测试环境:
- 简化的ActiveMQ Docker配置
- 预配置多种测试凭据
- 专注STOMP协议,提升性能
2025-08-08 02:53:14 +08:00

252 lines
7.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package activemq
import (
"context"
"fmt"
"github.com/shadow1ng/fscan/common"
"github.com/shadow1ng/fscan/common/i18n"
"github.com/shadow1ng/fscan/plugins/base"
)
// ActiveMQ插件基于新一代插件架构的完整实现
// 支持STOMP协议的弱密码检测、信息收集、队列管理等功能
// 展示了消息队列服务插件的标准实现模式
// ActiveMQPlugin ActiveMQ消息队列扫描和利用插件
// 集成了弱密码检测、自动利用、信息收集等完整功能
type ActiveMQPlugin struct {
*base.ServicePlugin // 继承基础服务插件功能
exploiter *ActiveMQExploiter // ActiveMQ专用利用模块
}
// NewActiveMQPlugin 创建新的ActiveMQ插件实例
// 这是标准的插件工厂函数,展示了新架构的完整初始化流程
func NewActiveMQPlugin() *ActiveMQPlugin {
// 定义插件元数据 - 这些信息用于插件注册和管理
metadata := &base.PluginMetadata{
Name: "activemq", // 插件唯一标识符
Version: "2.0.0", // 插件版本(新架构版本)
Author: "fscan-team", // 开发团队
Description: "ActiveMQ消息队列扫描和利用插件", // 功能描述
Category: "service", // 插件类别
Ports: []int{61613, 61614}, // ActiveMQ STOMP端口标准端口, SSL端口
Protocols: []string{"tcp", "stomp"}, // 支持的协议
Tags: []string{"message-queue", "activemq", "stomp", "bruteforce", "exploit"}, // 功能标签
}
// 创建ActiveMQ专用连接器
connector := NewActiveMQConnector()
// 基于连接器创建基础服务插件
servicePlugin := base.NewServicePlugin(metadata, connector)
// 组装完整的ActiveMQ插件
plugin := &ActiveMQPlugin{
ServicePlugin: servicePlugin,
exploiter: NewActiveMQExploiter(), // 集成利用模块
}
// 声明插件具备的安全测试能力
plugin.SetCapabilities([]base.Capability{
base.CapWeakPassword, // 弱密码检测
base.CapDataExtraction, // 数据提取
base.CapInformationLeak, // 信息泄露
base.CapPrivilegeEsc, // 权限提升
})
return plugin
}
// Scan 执行ActiveMQ服务的完整安全扫描
// 重写基础扫描方法,集成弱密码检测和自动利用功能
func (p *ActiveMQPlugin) Scan(ctx context.Context, info *common.HostInfo) (*base.ScanResult, error) {
// 调用基础服务插件进行弱密码扫描
result, err := p.ServicePlugin.Scan(ctx, info)
if err != nil || !result.Success {
return result, err // 扫描失败,直接返回
}
// 记录成功的弱密码发现使用i18n根据端口显示不同协议
target := fmt.Sprintf("%s:%s", info.Host, info.Ports)
cred := result.Credentials[0]
// 专注于STOMP协议的成功消息
common.LogSuccess(i18n.GetText("activemq_stomp_scan_success", target, cred.Username, cred.Password))
// 自动利用功能(可通过-nobr参数禁用
if result.Success && len(result.Credentials) > 0 && !common.DisableBrute {
// 同步执行利用攻击,确保显示结果
p.autoExploit(context.Background(), info, result.Credentials[0])
}
return result, nil
}
// autoExploit 自动利用
func (p *ActiveMQPlugin) autoExploit(ctx context.Context, info *common.HostInfo, creds *base.Credential) {
target := fmt.Sprintf("%s:%s", info.Host, info.Ports)
common.LogDebug(i18n.GetText("plugin_exploit_start", "ActiveMQ", target))
// 执行利用
result, err := p.exploiter.Exploit(ctx, info, creds)
if err != nil {
common.LogDebug(i18n.GetText("plugin_exploit_failed", "ActiveMQ", err))
return
}
if result != nil && result.Success {
// 使用利用结果中的Method字段作为方法名称
methodName := result.Method
if methodName == "" {
methodName = p.getExploitMethodName(result.Type)
}
// 只显示一次完整的利用结果
if result.Output != "" {
common.LogSuccess(fmt.Sprintf("ActiveMQ %s %s 利用成功 输出: %s", target, methodName, result.Output))
} else {
common.LogSuccess(fmt.Sprintf("ActiveMQ %s %s 利用成功", target, methodName))
}
// 保存利用结果(不显示额外日志)
// base.SaveExploitResult(info, result, "ActiveMQ")
}
}
// getExploitMethodName 获取利用方法的中文名称
func (p *ActiveMQPlugin) getExploitMethodName(method base.ExploitType) string {
switch method {
case base.ExploitDataExtraction:
return i18n.GetText("exploit_method_name_data_extraction")
case base.ExploitPrivilegeEsc:
return i18n.GetText("exploit_method_name_activemq_queue_mgmt")
default:
return "未知利用"
}
}
// Exploit 手动利用接口
func (p *ActiveMQPlugin) Exploit(ctx context.Context, info *common.HostInfo, creds *base.Credential) (*base.ExploitResult, error) {
return p.exploiter.Exploit(ctx, info, creds)
}
// GetExploitMethods 获取利用方法
func (p *ActiveMQPlugin) GetExploitMethods() []base.ExploitMethod {
return p.exploiter.GetExploitMethods()
}
// IsExploitSupported 检查利用支持
func (p *ActiveMQPlugin) IsExploitSupported(method base.ExploitType) bool {
return p.exploiter.IsExploitSupported(method)
}
// generateCredentials 重写凭据生成方法
func (p *ActiveMQPlugin) generateCredentials() []*base.Credential {
// 获取ActiveMQ专用的用户名字典
usernames := common.Userdict["activemq"]
if len(usernames) == 0 {
// 默认ActiveMQ用户名
usernames = []string{
"admin", "test", "root", "system", "user", "guest",
"manager", "activemq", "mqadmin", "broker",
}
}
// 生成基本凭据组合
credentials := base.GenerateCredentials(usernames, common.Passwords)
// 添加ActiveMQ专用的默认凭据
defaultCreds := p.ServicePlugin.GetServiceConnector().(*ActiveMQConnector).GetDefaultCredentials()
credentials = append(credentials, defaultCreds...)
// 去重处理(简化实现)
seen := make(map[string]bool)
var unique []*base.Credential
for _, cred := range credentials {
key := cred.Username + ":" + cred.Password
if !seen[key] {
seen[key] = true
unique = append(unique, cred)
}
}
return unique
}
// GetServiceName 获取服务名称
func (p *ActiveMQPlugin) GetServiceName() string {
return "ActiveMQ"
}
// GetServiceDescription 获取服务描述
func (p *ActiveMQPlugin) GetServiceDescription() string {
return "Apache ActiveMQ消息队列中间件"
}
// GetDefaultPorts 获取默认端口
func (p *ActiveMQPlugin) GetDefaultPorts() []int {
return []int{61613, 61614}
}
// SupportsBruteforce 支持暴力破解
func (p *ActiveMQPlugin) SupportsBruteforce() bool {
return true
}
// SupportsExploit 支持利用
func (p *ActiveMQPlugin) SupportsExploit() bool {
return true
}
// GetProtocols 获取支持的协议
func (p *ActiveMQPlugin) GetProtocols() []string {
return []string{"tcp", "stomp"}
}
// ValidateTarget 验证目标是否适用
func (p *ActiveMQPlugin) ValidateTarget(info *common.HostInfo) error {
// 基本验证
if info.Host == "" {
return fmt.Errorf("主机地址不能为空")
}
if info.Ports == "" {
return fmt.Errorf("端口不能为空")
}
return nil
}
// =============================================================================
// 插件注册
// =============================================================================
// RegisterActiveMQPlugin 注册ActiveMQ插件
func RegisterActiveMQPlugin() {
factory := base.NewSimplePluginFactory(
&base.PluginMetadata{
Name: "activemq",
Version: "2.0.0",
Author: "fscan-team",
Description: "ActiveMQ消息队列扫描和利用插件",
Category: "service",
Ports: []int{61613, 61614},
Protocols: []string{"tcp", "stomp"},
Tags: []string{"message-queue", "activemq", "stomp", "bruteforce", "exploit"},
},
func() base.Plugin {
return NewActiveMQPlugin()
},
)
// 注册到全局插件注册表
base.GlobalPluginRegistry.Register("activemq", factory)
// 记录注册信息
common.LogDebug("ActiveMQ插件已注册")
}
// 自动注册
func init() {
RegisterActiveMQPlugin()
}