package cassandra import ( "context" "fmt" "net" "strings" "time" "github.com/shadow1ng/fscan/common" "github.com/shadow1ng/fscan/common/i18n" "github.com/shadow1ng/fscan/plugins/base" ) // CassandraPlugin Cassandra插件实现 type CassandraPlugin struct { *base.ServicePlugin exploiter *CassandraExploiter } // NewCassandraPlugin 创建Cassandra插件 func NewCassandraPlugin() *CassandraPlugin { // 插件元数据 metadata := &base.PluginMetadata{ Name: "cassandra", Version: "2.0.0", Author: "fscan-team", Description: "Apache Cassandra服务扫描和利用插件", Category: "service", Ports: []int{9042}, // Cassandra Native Protocol Protocols: []string{"tcp"}, Tags: []string{"cassandra", "nosql", "database", "bruteforce"}, } // 创建连接器和服务插件 connector := NewCassandraConnector() servicePlugin := base.NewServicePlugin(metadata, connector) // 创建Cassandra插件 plugin := &CassandraPlugin{ ServicePlugin: servicePlugin, exploiter: NewCassandraExploiter(), } // 设置能力 plugin.SetCapabilities([]base.Capability{ base.CapWeakPassword, base.CapDataExtraction, base.CapInformationLeak, }) return plugin } // Scan 重写扫描方法以支持自动利用 func (p *CassandraPlugin) Scan(ctx context.Context, info *common.HostInfo) (*base.ScanResult, error) { // 如果禁用暴力破解,只进行服务识别 if common.DisableBrute { return p.performServiceIdentification(ctx, info) } // 执行基础的密码扫描 result, err := p.ServicePlugin.Scan(ctx, info) if err != nil || !result.Success { return result, err } // 记录成功的弱密码/未授权访问发现 target := fmt.Sprintf("%s:%s", info.Host, info.Ports) cred := result.Credentials[0] if cred.Username == "" && cred.Password == "" { // 未授权访问 common.LogSuccess(i18n.GetText("plugin_unauthorized_access", "Cassandra", target)) } else { // 弱密码 common.LogSuccess(i18n.GetText("plugin_login_success", "Cassandra", target, cred.Username, cred.Password)) } // 自动利用功能(可通过-ne参数禁用) if result.Success && len(result.Credentials) > 0 && !common.DisableExploit { p.autoExploit(context.Background(), info, result.Credentials[0]) } return result, nil } // generateCredentials 生成Cassandra凭据 func (p *CassandraPlugin) generateCredentials() []*base.Credential { // 获取Cassandra专用的用户名字典 usernames := common.Userdict["cassandra"] if len(usernames) == 0 { // 默认Cassandra用户名(包含空用户名用于测试未授权访问) usernames = []string{"", "cassandra", "admin", "root", "user"} } // 生成凭据组合,包括空密码测试未授权访问 var credentials []*base.Credential // 首先测试未授权访问(空用户名和密码) credentials = append(credentials, &base.Credential{ Username: "", Password: "", }) // 然后生成常规用户名密码组合 regularCreds := base.GenerateCredentials(usernames, common.Passwords) credentials = append(credentials, regularCreds...) return credentials } // autoExploit 自动利用功能 func (p *CassandraPlugin) 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", "Cassandra", target)) // 执行利用操作 result, err := p.exploiter.Exploit(ctx, info, creds) if err != nil { common.LogError(i18n.GetText("plugin_exploit_failed", "Cassandra", err)) return } // 处理利用结果 if result != nil && result.Success { // SaveExploitResult会自动使用LogSuccess显示红色利用成功消息 base.SaveExploitResult(info, result, "Cassandra") } } // Exploit 使用exploiter执行利用 func (p *CassandraPlugin) Exploit(ctx context.Context, info *common.HostInfo, creds *base.Credential) (*base.ExploitResult, error) { return p.exploiter.Exploit(ctx, info, creds) } // GetExploitMethods 获取利用方法 func (p *CassandraPlugin) GetExploitMethods() []base.ExploitMethod { return p.exploiter.GetExploitMethods() } // IsExploitSupported 检查利用支持 func (p *CassandraPlugin) IsExploitSupported(method base.ExploitType) bool { return p.exploiter.IsExploitSupported(method) } // performServiceIdentification 执行Cassandra服务识别(-nobr模式) func (p *CassandraPlugin) performServiceIdentification(ctx context.Context, info *common.HostInfo) (*base.ScanResult, error) { target := fmt.Sprintf("%s:%s", info.Host, info.Ports) // 尝试连接到Cassandra服务进行识别 cassandraInfo, isCassandra := p.identifyCassandraService(ctx, info) if isCassandra { // 记录服务识别成功 common.LogSuccess(i18n.GetText("cassandra_service_identified", target, cassandraInfo)) return &base.ScanResult{ Success: true, Service: "Cassandra", Banner: cassandraInfo, Extra: map[string]interface{}{ "service": "Cassandra", "port": info.Ports, "info": cassandraInfo, }, }, nil } // 如果无法识别为Cassandra,返回失败 return &base.ScanResult{ Success: false, Error: fmt.Errorf("无法识别为Cassandra服务"), }, nil } // identifyCassandraService 通过连接识别Cassandra服务 func (p *CassandraPlugin) identifyCassandraService(ctx context.Context, info *common.HostInfo) (string, bool) { // 尝试建立简单的TCP连接 target := fmt.Sprintf("%s:%s", info.Host, info.Ports) conn, err := common.WrapperTcpWithTimeout("tcp", target, time.Duration(common.Timeout)*time.Second) if err != nil { return "", false } defer conn.Close() // 对于Cassandra native protocol (9042),尝试发送OPTIONS frame if info.Ports == "9042" { return p.identifyNativeProtocol(conn) } // 通用端口检测(其他端口) return p.identifyGenericCassandra(conn) } // identifyNativeProtocol 识别Cassandra native protocol func (p *CassandraPlugin) identifyNativeProtocol(conn net.Conn) (string, bool) { // 设置读写超时 conn.SetDeadline(time.Now().Add(time.Duration(common.Timeout) * time.Second)) // Cassandra native protocol OPTIONS frame // Frame format: version(1) + flags(1) + stream(2) + opcode(1) + length(4) + body optionsFrame := []byte{ 0x04, // Version 4 0x00, // Flags 0x00, 0x00, // Stream ID 0x05, // Opcode: OPTIONS 0x00, 0x00, 0x00, 0x00, // Body length: 0 } // 发送OPTIONS请求 _, err := conn.Write(optionsFrame) if err != nil { return "", false } // 读取响应 response := make([]byte, 1024) n, err := conn.Read(response) if err != nil || n < 8 { return "", false } // 检查响应是否为有效的Cassandra协议响应 if n >= 8 && response[0] == 0x84 { // Response version // 简单解析响应以获取支持的版本信息 return "Cassandra Native Protocol v4", true } return "", false } // identifyGenericCassandra 通用Cassandra识别 func (p *CassandraPlugin) identifyGenericCassandra(conn net.Conn) (string, bool) { // 设置超时 conn.SetDeadline(time.Now().Add(time.Duration(common.Timeout) * time.Second)) // 尝试读取任何初始数据 response := make([]byte, 512) n, err := conn.Read(response) if err == nil && n > 0 { responseStr := string(response[:n]) // 检查响应中是否包含Cassandra相关信息 if strings.Contains(strings.ToLower(responseStr), "cassandra") { return fmt.Sprintf("Cassandra服务: %s", strings.TrimSpace(responseStr)), true } } // 如果端口开放但没有明确标识,仍然认为可能是Cassandra return "Cassandra服务", true } // ============================================================================= // 插件注册 // ============================================================================= // RegisterCassandraPlugin 注册Cassandra插件 func RegisterCassandraPlugin() { factory := base.NewSimplePluginFactory( &base.PluginMetadata{ Name: "cassandra", Version: "2.0.0", Author: "fscan-team", Description: "Apache Cassandra服务扫描和利用插件", Category: "service", Ports: []int{9042}, // Cassandra Native Protocol Protocols: []string{"tcp"}, Tags: []string{"cassandra", "nosql", "database", "bruteforce"}, }, func() base.Plugin { return NewCassandraPlugin() }, ) base.GlobalPluginRegistry.Register("cassandra", factory) } // 自动注册 func init() { RegisterCassandraPlugin() }