fscan/Plugins/services/vnc/plugin.go
ZacharyZcR 3e4cd2466e feat: 实现完整的VNC插件支持
- 新增VNC远程桌面协议检测和利用插件
- 实现RFB协议连接器支持版本识别和认证
- 支持无认证访问检测和弱密码暴力破解
- 添加VNC服务风险评估和信息收集功能
- 支持标准VNC端口范围(5900-5909)
- 在插件注册系统中集成VNC服务扫描

功能特性: 服务识别、安全检测、利用验证、风险评估
2025-08-12 12:08:30 +08:00

220 lines
6.0 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 vnc
import (
"context"
"fmt"
"github.com/shadow1ng/fscan/common"
"github.com/shadow1ng/fscan/common/i18n"
"github.com/shadow1ng/fscan/plugins/base"
)
// VNCPlugin VNC插件
type VNCPlugin struct {
*base.ServicePlugin
connector *VNCConnector
exploiter *VNCExploiter
}
// NewVNCPlugin 创建VNC插件
func NewVNCPlugin() *VNCPlugin {
metadata := &base.PluginMetadata{
Name: "vnc",
Version: "1.0.0",
Author: "fscan-team",
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
}
// Scan 执行VNC扫描
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 {
return &base.ScanResult{
Success: false,
Service: "VNC",
Banner: "",
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)
if err == nil {
successCreds = cred
if cred.Password == "" {
authResults = append(authResults, "无认证访问")
} else {
authResults = append(authResults, fmt.Sprintf("弱密码: %s", cred.Password))
}
break
} else {
common.LogDebug(fmt.Sprintf("VNC认证失败 [%s]: %v", cred.Password, err))
}
}
// 4. 构建扫描结果
result := &base.ScanResult{
Success: true,
Service: "VNC",
Banner: fmt.Sprintf("VNC服务 %s", version),
Extra: map[string]interface{}{
"version": version,
"port": info.Ports,
"target": target,
"auth_tested": len(defaultCreds),
},
}
if successCreds != nil {
result.Extra["vulnerable"] = true
result.Extra["credentials"] = map[string]string{
"username": successCreds.Username,
"password": successCreds.Password,
}
result.Extra["auth_result"] = authResults[0]
// 执行自动利用
p.autoExploit(ctx, info, successCreds)
} 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))
}
}
// 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 检查是否支持指定的利用方法
func (p *VNCPlugin) IsExploitSupported(method base.ExploitType) bool {
return p.exploiter.IsExploitSupported(method)
}
// performServiceIdentification 执行VNC服务识别-nobr模式
func (p *VNCPlugin) performServiceIdentification(ctx context.Context, info *common.HostInfo) (*base.ScanResult, error) {
// 尝试连接到VNC服务进行识别
conn, err := p.connector.Connect(ctx, info)
if err != nil {
return &base.ScanResult{
Success: false,
Service: "Unknown",
Banner: "",
Error: fmt.Errorf("服务不可访问"),
}, nil
}
connectionInfo := conn.(map[string]interface{})
version := connectionInfo["version"].(string)
return &base.ScanResult{
Success: true,
Service: "VNC",
Banner: fmt.Sprintf("VNC服务 %s", version),
Extra: map[string]interface{}{
"version": version,
"identified": true,
"protocol": "VNC",
},
}, nil
}
// RegisterVNCPlugin 注册VNC插件
func RegisterVNCPlugin() {
factory := base.NewSimplePluginFactory(
&base.PluginMetadata{
Name: "vnc",
Version: "1.0.0",
Author: "fscan-team",
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},
},
func() base.Plugin {
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)
}
// 插件注册函数
func init() {
RegisterVNCPlugin()
}