From 074aebfeec87acf26575c0371b36ed08679ff8d9 Mon Sep 17 00:00:00 2001 From: ZacharyZcR Date: Tue, 12 Aug 2025 17:56:06 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E7=AE=80=E5=8C=96=E6=8F=92?= =?UTF-8?q?=E4=BB=B6=E5=88=A9=E7=94=A8=E6=9E=B6=E6=9E=84=EF=BC=8C=E7=A7=BB?= =?UTF-8?q?=E9=99=A4=E4=B8=8D=E5=BF=85=E8=A6=81=E7=9A=84exploit=E6=8E=A7?= =?UTF-8?q?=E5=88=B6=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除-ne (DisableExploit)参数及其相关控制逻辑 - 统一服务插件exploit实现为空函数,保持接口一致性 - MySQL/FTP/Cassandra/ActiveMQ插件exploit方法改为空实现 - Redis插件移除-ne控制,利用功能由专用参数控制(-rwp/-rf/-rs) - VNC插件exploit功能改为空实现,专注于服务检测和弱密码扫描 - 更新插件描述,准确反映实际功能范围 所有exploit功能现在由明确的用户参数控制,无需通用禁用开关 --- Common/Flag.go | 2 - Common/i18n/messages/flag.go | 4 - plugins/services/activemq/plugin.go | 37 +------ plugins/services/cassandra/plugin.go | 24 +---- plugins/services/ftp/plugin.go | 29 +---- plugins/services/mysql/plugin.go | 24 +---- plugins/services/redis/plugin.go | 10 +- plugins/services/vnc/exploiter.go | 153 +++------------------------ plugins/services/vnc/plugin.go | 90 ++++++---------- 9 files changed, 60 insertions(+), 313 deletions(-) diff --git a/Common/Flag.go b/Common/Flag.go index 8c117e1..5dd96f8 100644 --- a/Common/Flag.go +++ b/Common/Flag.go @@ -57,7 +57,6 @@ var ( RedisWriteFile string DisableBrute bool - DisableExploit bool MaxRetries int DisableSave bool @@ -227,7 +226,6 @@ func Flag(Info *HostInfo) { // 暴力破解控制参数 // ═════════════════════════════════════════════════ flag.BoolVar(&DisableBrute, "nobr", false, i18n.GetText("flag_disable_brute")) - flag.BoolVar(&DisableExploit, "ne", false, i18n.GetText("flag_disable_exploit")) flag.IntVar(&MaxRetries, "retry", 3, i18n.GetText("flag_max_retries")) // ═════════════════════════════════════════════════ diff --git a/Common/i18n/messages/flag.go b/Common/i18n/messages/flag.go index 571c379..3cbe95d 100644 --- a/Common/i18n/messages/flag.go +++ b/Common/i18n/messages/flag.go @@ -190,10 +190,6 @@ var FlagMessages = map[string]map[string]string{ LangZH: "禁用暴力破解", LangEN: "Disable brute force", }, - "flag_disable_exploit": { - LangZH: "禁用利用攻击", - LangEN: "Disable exploit attacks", - }, "flag_max_retries": { LangZH: "最大重试次数", LangEN: "Maximum retries", diff --git a/plugins/services/activemq/plugin.go b/plugins/services/activemq/plugin.go index 355c830..6cf7221 100644 --- a/plugins/services/activemq/plugin.go +++ b/plugins/services/activemq/plugin.go @@ -83,45 +83,12 @@ func (p *ActiveMQPlugin) Scan(ctx context.Context, info *common.HostInfo) (*base // 专注于STOMP协议的成功消息 common.LogSuccess(i18n.GetText("activemq_stomp_scan_success", target, cred.Username, cred.Password)) - // 自动利用功能(可通过-ne参数禁用) - if result.Success && len(result.Credentials) > 0 && !common.DisableExploit { - // 同步执行利用攻击,确保显示结果 - p.autoExploit(context.Background(), info, result.Credentials[0]) - } + // ActiveMQ插件不提供利用功能,仅进行弱密码扫描 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") - } -} +// autoExploit方法已移除 - ActiveMQ插件不提供利用功能 // getExploitMethodName 获取利用方法的中文名称 func (p *ActiveMQPlugin) getExploitMethodName(method base.ExploitType) string { diff --git a/plugins/services/cassandra/plugin.go b/plugins/services/cassandra/plugin.go index 36cb5ca..07498b6 100644 --- a/plugins/services/cassandra/plugin.go +++ b/plugins/services/cassandra/plugin.go @@ -77,34 +77,14 @@ func (p *CassandraPlugin) Scan(ctx context.Context, info *common.HostInfo) (*bas 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]) - } + // Cassandra插件不提供利用功能,仅进行弱密码扫描 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") - } -} +// autoExploit方法已移除 - Cassandra插件不提供利用功能 // Exploit 使用exploiter执行利用 func (p *CassandraPlugin) Exploit(ctx context.Context, info *common.HostInfo, creds *base.Credential) (*base.ExploitResult, error) { diff --git a/plugins/services/ftp/plugin.go b/plugins/services/ftp/plugin.go index 07d65ba..364c7ed 100644 --- a/plugins/services/ftp/plugin.go +++ b/plugins/services/ftp/plugin.go @@ -72,10 +72,7 @@ func (p *FTPPlugin) Scan(ctx context.Context, info *common.HostInfo) (*base.Scan target := fmt.Sprintf("%s:%s", info.Host, info.Ports) common.LogSuccess(i18n.GetText("ftp_anonymous_success", target)) - // 自动利用匿名访问 - if !common.DisableExploit { - p.autoExploit(context.Background(), info, anonymousCred) - } + // FTP插件不提供利用功能,仅记录匿名访问 return result, nil } @@ -91,34 +88,14 @@ func (p *FTPPlugin) Scan(ctx context.Context, info *common.HostInfo) (*base.Scan cred := result.Credentials[0] common.LogSuccess(i18n.GetText("ftp_weak_pwd_success", target, cred.Username, cred.Password)) - // 自动利用功能(可通过-ne参数禁用) - if result.Success && len(result.Credentials) > 0 && !common.DisableExploit { - p.autoExploit(context.Background(), info, result.Credentials[0]) - } + // FTP插件不提供利用功能,仅进行弱密码扫描 return result, nil } // 已移除未使用的 generateCredentials 方法 -// autoExploit 自动利用功能 -func (p *FTPPlugin) 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", "FTP", target)) - - // 执行利用操作 - result, err := p.exploiter.Exploit(ctx, info, creds) - if err != nil { - common.LogError(i18n.GetText("plugin_exploit_failed", "FTP", err)) - return - } - - // 处理利用结果 - if result != nil && result.Success { - // SaveExploitResult会自动使用LogSuccess显示红色利用成功消息 - base.SaveExploitResult(info, result, "FTP") - } -} +// autoExploit方法已移除 - FTP插件不提供利用功能 // Exploit 使用exploiter执行利用 func (p *FTPPlugin) Exploit(ctx context.Context, info *common.HostInfo, creds *base.Credential) (*base.ExploitResult, error) { diff --git a/plugins/services/mysql/plugin.go b/plugins/services/mysql/plugin.go index 8f7f11e..256473a 100644 --- a/plugins/services/mysql/plugin.go +++ b/plugins/services/mysql/plugin.go @@ -82,32 +82,12 @@ func (p *MySQLPlugin) Scan(ctx context.Context, info *common.HostInfo) (*base.Sc cred := result.Credentials[0] common.LogSuccess(i18n.GetText("mysql_scan_success", target, cred.Username, cred.Password)) - // 自动利用功能(可通过-ne参数禁用) - if result.Success && len(result.Credentials) > 0 && !common.DisableExploit { - // 异步执行利用攻击,避免阻塞扫描进程 - go p.autoExploit(context.Background(), info, result.Credentials[0]) - } + // MySQL插件不提供利用功能,仅进行弱密码扫描 return result, nil } -// autoExploit 自动利用 -func (p *MySQLPlugin) 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", "MySQL", target)) - - // 执行利用 - result, err := p.exploiter.Exploit(ctx, info, creds) - if err != nil { - common.LogError(i18n.GetText("plugin_exploit_failed", "MySQL", err)) - return - } - - if result != nil && result.Success { - common.LogSuccess(i18n.GetText("plugin_exploit_success", "MySQL", i18n.GetExploitMethodName(result.Method))) - base.SaveExploitResult(info, result, "MySQL") - } -} +// autoExploit方法已移除 - MySQL插件不提供利用功能 // Exploit 手动利用接口 func (p *MySQLPlugin) Exploit(ctx context.Context, info *common.HostInfo, creds *base.Credential) (*base.ExploitResult, error) { diff --git a/plugins/services/redis/plugin.go b/plugins/services/redis/plugin.go index 175953e..6c3a864 100644 --- a/plugins/services/redis/plugin.go +++ b/plugins/services/redis/plugin.go @@ -69,10 +69,8 @@ func (p *RedisPlugin) Scan(ctx context.Context, info *common.HostInfo) (*base.Sc if unauthorizedResult != nil && unauthorizedResult.Success { common.LogSuccess(i18n.GetText("redis_unauth_success", target)) - // 如果启用了利用功能,执行自动利用 - if !common.DisableExploit { // 使用DisableExploit控制利用功能 - go p.autoExploit(context.Background(), info, nil) // 未授权访问不需要凭据 - } + // Redis利用功能由明确的用户参数控制(-rwp, -rf, -rs),无需-ne参数控制 + go p.autoExploit(context.Background(), info, nil) // 未授权访问不需要凭据 return unauthorizedResult, nil } @@ -91,8 +89,8 @@ func (p *RedisPlugin) Scan(ctx context.Context, info *common.HostInfo) (*base.Sc common.LogSuccess(i18n.GetText("redis_weak_pwd_success", target, result.Credentials[0].Password)) - // 如果扫描成功并且启用了利用功能,执行自动利用 - if result.Success && len(result.Credentials) > 0 && !common.DisableExploit { + // Redis利用功能由明确的用户参数控制(-rwp, -rf, -rs),无需-ne参数控制 + if result.Success && len(result.Credentials) > 0 { go p.autoExploit(context.Background(), info, result.Credentials[0]) } diff --git a/plugins/services/vnc/exploiter.go b/plugins/services/vnc/exploiter.go index c753554..bd0426a 100644 --- a/plugins/services/vnc/exploiter.go +++ b/plugins/services/vnc/exploiter.go @@ -2,154 +2,35 @@ package vnc import ( "context" - "fmt" "github.com/shadow1ng/fscan/common" - "github.com/shadow1ng/fscan/common/i18n" "github.com/shadow1ng/fscan/plugins/base" ) -// VNCExploiter VNC利用器 +// VNCExploiter VNC利用器实现 - 最小化版本,不提供利用功能 type VNCExploiter struct { - connector *VNCConnector + *base.BaseExploiter } // NewVNCExploiter 创建VNC利用器 func NewVNCExploiter() *VNCExploiter { - return &VNCExploiter{ - connector: NewVNCConnector(), + exploiter := &VNCExploiter{ + BaseExploiter: base.NewBaseExploiter("vnc"), } + + // VNC插件不提供利用功能 + exploiter.setupExploitMethods() + + return exploiter } -// Exploit 执行VNC利用 +// setupExploitMethods 设置利用方法 +func (e *VNCExploiter) setupExploitMethods() { + // VNC插件不提供利用功能,仅进行弱密码扫描和服务识别 +} + +// Exploit 利用接口实现 - 空实现 func (e *VNCExploiter) Exploit(ctx context.Context, info *common.HostInfo, creds *base.Credential) (*base.ExploitResult, error) { - target := fmt.Sprintf("%s:%s", info.Host, info.Ports) - - // 尝试连接VNC服务 - conn, err := e.connector.Connect(ctx, info) - if err != nil { - return &base.ExploitResult{ - Success: false, - Error: fmt.Errorf("VNC连接失败: %v", err), - }, nil - } - - // 尝试认证 - authErr := e.connector.Authenticate(ctx, conn, creds) - if authErr != nil { - return &base.ExploitResult{ - Success: false, - Error: authErr, - }, nil - } - - // 认证成功,收集信息 - connectionInfo := conn.(map[string]interface{}) - version := connectionInfo["version"].(string) - - exploitData := map[string]interface{}{ - "service": "VNC", - "target": target, - "version": version, - "credentials": map[string]string{ - "username": creds.Username, - "password": creds.Password, - }, - "access_type": e.getAccessType(creds), - "description": "VNC远程桌面访问", - } - - // 尝试获取更多信息 - e.gatherVNCInfo(ctx, info, exploitData) - - common.LogSuccess(i18n.GetText("exploit_success", "VNC", target)) - - return &base.ExploitResult{ - Success: true, - Output: fmt.Sprintf("VNC利用成功 - %s", target), - Data: exploitData, - }, nil -} - -// IsExploitSupported 检查是否支持指定的利用类型 -func (e *VNCExploiter) IsExploitSupported(exploitType base.ExploitType) bool { - switch exploitType { - case base.ExploitDataExtraction: - return true - case base.ExploitUnauthorized: - return true - default: - return false - } -} - -// getAccessType 获取访问类型描述 -func (e *VNCExploiter) getAccessType(creds *base.Credential) string { - if creds.Password == "" { - return "无认证访问" - } - return "密码认证访问" -} - -// gatherVNCInfo 收集VNC相关信息 -func (e *VNCExploiter) gatherVNCInfo(ctx context.Context, info *common.HostInfo, data map[string]interface{}) { - // 添加端口信息 - if portNum := info.Ports; portNum != "" { - data["port"] = portNum - - // VNC端口通常对应显示器编号 - if len(portNum) >= 4 && portNum[:2] == "59" { - if displayNum := portNum[2:]; len(displayNum) >= 2 { - data["display_number"] = displayNum - data["display_info"] = fmt.Sprintf("VNC显示器 :%s", displayNum) - } - } - } - - // 添加安全信息 - data["security_info"] = map[string]interface{}{ - "encryption_support": "取决于VNC版本", - "authentication_types": []string{"None", "VNC Authentication", "RA2", "RA2ne", "Tight", "ARD"}, - "common_vulnerabilities": []string{ - "弱密码", - "无认证访问", - "未加密传输", - "DES加密漏洞", - }, - } - - // 添加建议的后续操作 - data["next_steps"] = []string{ - "尝试连接VNC客户端进行远程控制", - "检查VNC服务配置", - "查看可用的安全设置", - "评估网络流量加密状态", - } - - // 添加风险评估 - risk := "中等" - if data["access_type"] == "无认证访问" { - risk = "高" - } - data["risk_level"] = risk -} - -// GetSupportedExploits 获取支持的利用类型 -func (e *VNCExploiter) GetSupportedExploits() []base.ExploitType { - return []base.ExploitType{ - base.ExploitDataExtraction, - base.ExploitUnauthorized, - } -} - -// GetExploitDescription 获取利用描述 -func (e *VNCExploiter) GetExploitDescription(exploitType base.ExploitType) string { - switch exploitType { - case base.ExploitDataExtraction: - return "收集VNC服务信息,包括版本、认证类型等" - case base.ExploitUnauthorized: - return "尝试无认证访问或弱密码攻击VNC服务" - default: - return "未知的利用类型" - } + // VNC插件不提供利用功能 + return nil, nil } \ No newline at end of file diff --git a/plugins/services/vnc/plugin.go b/plugins/services/vnc/plugin.go index 739c9f5..1f3dea7 100644 --- a/plugins/services/vnc/plugin.go +++ b/plugins/services/vnc/plugin.go @@ -22,22 +22,22 @@ func NewVNCPlugin() *VNCPlugin { Name: "vnc", Version: "1.0.0", Author: "fscan-team", - Description: "VNC远程桌面协议检测和利用插件", + Description: "VNC远程桌面协议检测插件", Category: "service", Tags: []string{"vnc", "remote-desktop", "service", "unauth"}, Protocols: []string{"vnc"}, Ports: []int{5900, 5901, 5902, 5903, 5904, 5905, 5906, 5907, 5908, 5909}, } - + connector := NewVNCConnector() exploiter := NewVNCExploiter() - + plugin := &VNCPlugin{ ServicePlugin: base.NewServicePlugin(metadata, connector), connector: connector, exploiter: exploiter, } - + return plugin } @@ -45,7 +45,7 @@ func NewVNCPlugin() *VNCPlugin { func (p *VNCPlugin) Scan(ctx context.Context, info *common.HostInfo) (*base.ScanResult, error) { target := fmt.Sprintf("%s:%s", info.Host, info.Ports) common.LogDebug(i18n.GetText("plugin_scan_start", "VNC", target)) - + // 1. 尝试连接VNC服务 conn, err := p.connector.Connect(ctx, info) if err != nil { @@ -56,16 +56,16 @@ func (p *VNCPlugin) Scan(ctx context.Context, info *common.HostInfo) (*base.Scan Error: fmt.Errorf("VNC服务不可访问: %v", err), }, nil } - + connectionInfo := conn.(map[string]interface{}) version := connectionInfo["version"].(string) - + // 2. 尝试获取默认凭据 defaultCreds := p.connector.GetDefaultCredentials() - + var successCreds *base.Credential var authResults []string - + // 3. 尝试认证 for _, cred := range defaultCreds { err := p.connector.Authenticate(ctx, conn, cred) @@ -81,7 +81,7 @@ func (p *VNCPlugin) Scan(ctx context.Context, info *common.HostInfo) (*base.Scan common.LogDebug(fmt.Sprintf("VNC认证失败 [%s]: %v", cred.Password, err)) } } - + // 4. 构建扫描结果 result := &base.ScanResult{ Success: true, @@ -94,7 +94,7 @@ func (p *VNCPlugin) Scan(ctx context.Context, info *common.HostInfo) (*base.Scan "auth_tested": len(defaultCreds), }, } - + if successCreds != nil { result.Extra["vulnerable"] = true result.Extra["credentials"] = map[string]string{ @@ -102,56 +102,35 @@ func (p *VNCPlugin) Scan(ctx context.Context, info *common.HostInfo) (*base.Scan "password": successCreds.Password, } result.Extra["auth_result"] = authResults[0] - - // 执行自动利用 - p.autoExploit(ctx, info, successCreds) + + // VNC插件不提供利用功能,仅进行服务识别和弱密码检测 + if successCreds.Password == "" { + common.LogSuccess(i18n.GetText("vnc_unauth_success", fmt.Sprintf("%s:%s", info.Host, info.Ports))) + } else { + common.LogSuccess(i18n.GetText("vnc_weak_pwd_success", fmt.Sprintf("%s:%s", info.Host, info.Ports), successCreds.Password)) + } } else { result.Extra["vulnerable"] = false result.Extra["auth_result"] = "认证失败" } - + common.LogSuccess(i18n.GetText("plugin_scan_complete", "VNC", target)) return result, nil } -// autoExploit 自动利用功能 -func (p *VNCPlugin) 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", "VNC", target)) - - // 执行利用操作 - result, err := p.exploiter.Exploit(ctx, info, creds) - if err != nil { - common.LogError(i18n.GetText("plugin_exploit_failed", "VNC", err)) - return - } - - if result.Success { - common.LogSuccess(i18n.GetText("plugin_exploit_success", "VNC", target)) - - // 输出利用结果 - if result.Data != nil { - if accessType, exists := result.Data["access_type"]; exists { - common.LogInfo(fmt.Sprintf("VNC访问类型: %s", accessType)) - } - if version, exists := result.Data["version"]; exists { - common.LogInfo(fmt.Sprintf("VNC版本: %s", version)) - } - if riskLevel, exists := result.Data["risk_level"]; exists { - common.LogInfo(fmt.Sprintf("风险等级: %s", riskLevel)) - } - } - } else { - common.LogError(fmt.Sprintf("VNC利用失败: %v", result.Error)) - } -} +// autoExploit方法已移除 - VNC插件不提供利用功能 // Exploit 使用exploiter执行利用 func (p *VNCPlugin) Exploit(ctx context.Context, info *common.HostInfo, creds *base.Credential) (*base.ExploitResult, error) { return p.exploiter.Exploit(ctx, info, creds) } -// IsExploitSupported 检查是否支持指定的利用方法 +// GetExploitMethods 获取利用方法 +func (p *VNCPlugin) GetExploitMethods() []base.ExploitMethod { + return p.exploiter.GetExploitMethods() +} + +// IsExploitSupported 检查利用支持 func (p *VNCPlugin) IsExploitSupported(method base.ExploitType) bool { return p.exploiter.IsExploitSupported(method) } @@ -164,8 +143,8 @@ func RegisterVNCPlugin() { &base.PluginMetadata{ Name: "vnc", Version: "1.0.0", - Author: "fscan-team", - Description: "VNC远程桌面协议检测和利用插件", + Author: "fscan-team", + Description: "VNC远程桌面协议检测插件", Category: "service", Tags: []string{"vnc", "remote-desktop", "service", "unauth"}, Protocols: []string{"vnc"}, @@ -175,20 +154,11 @@ func RegisterVNCPlugin() { return NewVNCPlugin() }, ) - - base.GlobalPluginRegistry.Register("vnc", factory) -} -// GetInfo 获取插件信息 -func (p *VNCPlugin) GetInfo() string { - return fmt.Sprintf(`VNC远程桌面协议插件 -支持端口: %v -功能: 服务识别、无认证检测、弱密码检测 -作者: fscan-team -版本: 1.0.0`, p.GetMetadata().Ports) + base.GlobalPluginRegistry.Register("vnc", factory) } // 插件注册函数 func init() { RegisterVNCPlugin() -} \ No newline at end of file +}