fscan/plugins/services/cassandra/plugin.go
ZacharyZcR 4a3f281b6b refactor: 统一Plugins目录大小写为小写
- 将所有Plugins路径重命名为plugins
- 修复Git索引与实际文件系统大小写不一致问题
- 确保跨平台兼容性和路径一致性
2025-08-12 13:08:06 +08:00

258 lines
7.6 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 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 方法
// 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()
}