diff --git a/Common/i18n/messages/plugins.go b/Common/i18n/messages/plugins.go index 0bb0e67..4a96702 100644 --- a/Common/i18n/messages/plugins.go +++ b/Common/i18n/messages/plugins.go @@ -558,6 +558,24 @@ var PluginMessages = map[string]map[string]string{ LangZH: "FTP文件上传测试成功", LangEN: "FTP file upload test successful", }, + + // ========================= IMAP插件消息 ========================= + "imap_weak_pwd_success": { + LangZH: "IMAP弱密码: %s [%s:%s]", + LangEN: "IMAP weak password: %s [%s:%s]", + }, + "imap_service_identified": { + LangZH: "IMAP服务识别成功: %s - %s", + LangEN: "IMAP service identified: %s - %s", + }, + "imap_connection_failed": { + LangZH: "IMAP连接失败: %v", + LangEN: "IMAP connection failed: %v", + }, + "imap_auth_failed": { + LangZH: "IMAP认证失败: %v", + LangEN: "IMAP authentication failed: %v", + }, "ftp_directory_found": { LangZH: "发现FTP目录: %s", LangEN: "FTP directories found: %s", diff --git a/Core/Registry.go b/Core/Registry.go index ad37fe7..362275a 100644 --- a/Core/Registry.go +++ b/Core/Registry.go @@ -7,7 +7,9 @@ import ( // 导入新架构插件,触发自动注册 _ "github.com/shadow1ng/fscan/plugins/services/activemq" + _ "github.com/shadow1ng/fscan/plugins/services/cassandra" _ "github.com/shadow1ng/fscan/plugins/services/ftp" + _ "github.com/shadow1ng/fscan/plugins/services/imap" _ "github.com/shadow1ng/fscan/plugins/services/mysql" _ "github.com/shadow1ng/fscan/plugins/services/redis" _ "github.com/shadow1ng/fscan/plugins/services/ssh" diff --git a/Plugins/services/imap/connector.go b/Plugins/services/imap/connector.go new file mode 100644 index 0000000..ffdf6c7 --- /dev/null +++ b/Plugins/services/imap/connector.go @@ -0,0 +1,133 @@ +package imap + +import ( + "bufio" + "context" + "crypto/tls" + "fmt" + "io" + "net" + "strings" + "time" + + "github.com/shadow1ng/fscan/common" + "github.com/shadow1ng/fscan/plugins/base" +) + +// IMAPConnection IMAP连接包装器 +type IMAPConnection struct { + conn net.Conn + reader *bufio.Reader + target string +} + +// IMAPConnector IMAP连接器实现 +type IMAPConnector struct { + host string + port string +} + +// NewIMAPConnector 创建IMAP连接器 +func NewIMAPConnector() *IMAPConnector { + return &IMAPConnector{} +} + +// Connect 连接到IMAP服务 +func (c *IMAPConnector) Connect(ctx context.Context, info *common.HostInfo) (interface{}, error) { + c.host = info.Host + c.port = info.Ports + + target := fmt.Sprintf("%s:%s", c.host, c.port) + + // 根据端口选择连接类型 + var conn net.Conn + var err error + + if c.port == "993" { + // IMAPS端口,使用TLS连接 + tlsConfig := &tls.Config{ + InsecureSkipVerify: true, + } + conn, err = common.WrapperTlsWithContext(ctx, "tcp", target, tlsConfig) + } else { + // IMAP端口,使用普通连接 + conn, err = common.WrapperTcpWithContext(ctx, "tcp", target) + } + + if err != nil { + return nil, fmt.Errorf("IMAP连接失败: %v", err) + } + + reader := bufio.NewReader(conn) + + // 设置IMAP特殊超时:默认超时时间 + 5秒 + imapTimeout := time.Duration(common.Timeout+5) * time.Second + conn.SetReadDeadline(time.Now().Add(imapTimeout)) + + // 读取IMAP欢迎消息 + if _, readErr := reader.ReadString('\n'); readErr != nil { + conn.Close() + return nil, fmt.Errorf("IMAP欢迎消息读取失败: %v", readErr) + } + + return &IMAPConnection{ + conn: conn, + reader: reader, + target: target, + }, nil +} + +// Authenticate 认证 +func (c *IMAPConnector) Authenticate(ctx context.Context, conn interface{}, cred *base.Credential) error { + imapConn, ok := conn.(*IMAPConnection) + if !ok { + return fmt.Errorf("无效的连接类型") + } + + // 设置IMAP特殊超时:默认超时时间 + 5秒 + imapTimeout := time.Duration(common.Timeout+5) * time.Second + imapConn.conn.SetDeadline(time.Now().Add(imapTimeout)) + + // 发送LOGIN命令 + loginCmd := fmt.Sprintf("a001 LOGIN \"%s\" \"%s\"\r\n", cred.Username, cred.Password) + _, err := imapConn.conn.Write([]byte(loginCmd)) + if err != nil { + return fmt.Errorf("发送登录命令失败: %v", err) + } + + // 读取认证响应 + for { + select { + case <-ctx.Done(): + return fmt.Errorf("IMAP认证超时: %v", ctx.Err()) + default: + // 设置读取超时,避免无限等待(使用IMAP特殊超时) + imapTimeout := time.Duration(common.Timeout+5) * time.Second + imapConn.conn.SetReadDeadline(time.Now().Add(imapTimeout)) + + response, err := imapConn.reader.ReadString('\n') + if err != nil { + if err == io.EOF { + return fmt.Errorf("IMAP认证失败") + } + return fmt.Errorf("读取响应失败: %v", err) + } + + if strings.Contains(response, "a001 OK") { + return nil // 认证成功 + } + + if strings.Contains(response, "a001 NO") || strings.Contains(response, "a001 BAD") { + return fmt.Errorf("IMAP认证失败") + } + } + } +} + +// Close 关闭连接 +func (c *IMAPConnector) Close(conn interface{}) error { + if imapConn, ok := conn.(*IMAPConnection); ok && imapConn.conn != nil { + return imapConn.conn.Close() + } + return nil +} \ No newline at end of file diff --git a/Plugins/services/imap/exploiter.go b/Plugins/services/imap/exploiter.go new file mode 100644 index 0000000..ba68da3 --- /dev/null +++ b/Plugins/services/imap/exploiter.go @@ -0,0 +1,36 @@ +package imap + +import ( + "context" + + "github.com/shadow1ng/fscan/common" + "github.com/shadow1ng/fscan/plugins/base" +) + +// IMAPExploiter IMAP利用器实现 - 最小化版本,不提供利用功能 +type IMAPExploiter struct { + *base.BaseExploiter +} + +// NewIMAPExploiter 创建IMAP利用器 +func NewIMAPExploiter() *IMAPExploiter { + exploiter := &IMAPExploiter{ + BaseExploiter: base.NewBaseExploiter("imap"), + } + + // IMAP插件不提供利用功能 + exploiter.setupExploitMethods() + + return exploiter +} + +// setupExploitMethods 设置利用方法 +func (e *IMAPExploiter) setupExploitMethods() { + // IMAP插件不提供利用功能,仅进行弱密码扫描 +} + +// Exploit 利用接口实现 - 空实现 +func (e *IMAPExploiter) Exploit(ctx context.Context, info *common.HostInfo, creds *base.Credential) (*base.ExploitResult, error) { + // IMAP插件不提供利用功能 + return nil, nil +} \ No newline at end of file diff --git a/Plugins/services/imap/plugin.go b/Plugins/services/imap/plugin.go new file mode 100644 index 0000000..520c9ae --- /dev/null +++ b/Plugins/services/imap/plugin.go @@ -0,0 +1,224 @@ +package imap + +import ( + "context" + "crypto/tls" + "fmt" + "net" + "regexp" + "strings" + "time" + + "github.com/shadow1ng/fscan/common" + "github.com/shadow1ng/fscan/common/i18n" + "github.com/shadow1ng/fscan/plugins/base" +) + +// IMAPPlugin IMAP插件实现 +type IMAPPlugin struct { + *base.ServicePlugin + exploiter *IMAPExploiter +} + +// NewIMAPPlugin 创建IMAP插件 +func NewIMAPPlugin() *IMAPPlugin { + // 插件元数据 + metadata := &base.PluginMetadata{ + Name: "imap", + Version: "2.0.0", + Author: "fscan-team", + Description: "IMAP邮件服务扫描和利用插件", + Category: "service", + Ports: []int{143, 993}, // IMAP和IMAPS端口 + Protocols: []string{"tcp"}, + Tags: []string{"imap", "mail", "bruteforce"}, + } + + // 创建连接器和服务插件 + connector := NewIMAPConnector() + servicePlugin := base.NewServicePlugin(metadata, connector) + + // 创建IMAP插件 + plugin := &IMAPPlugin{ + ServicePlugin: servicePlugin, + exploiter: NewIMAPExploiter(), + } + + // 设置能力 + plugin.SetCapabilities([]base.Capability{ + base.CapWeakPassword, + base.CapDataExtraction, + }) + + + return plugin +} + +// Scan 重写扫描方法以支持服务识别 +func (p *IMAPPlugin) 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] + common.LogSuccess(i18n.GetText("imap_weak_pwd_success", target, cred.Username, cred.Password)) + + return result, nil +} + +// generateCredentials 重写凭据生成方法 +func (p *IMAPPlugin) generateCredentials() []*base.Credential { + // 获取IMAP专用的用户名字典 + usernames := common.Userdict["imap"] + if len(usernames) == 0 { + // 默认IMAP用户名 + usernames = []string{"admin", "root", "test", "mail", "postmaster", "administrator"} + } + + return base.GenerateCredentials(usernames, common.Passwords) +} + +// Exploit 使用exploiter执行利用 +func (p *IMAPPlugin) Exploit(ctx context.Context, info *common.HostInfo, creds *base.Credential) (*base.ExploitResult, error) { + return p.exploiter.Exploit(ctx, info, creds) +} + +// GetExploitMethods 获取利用方法 +func (p *IMAPPlugin) GetExploitMethods() []base.ExploitMethod { + return p.exploiter.GetExploitMethods() +} + +// IsExploitSupported 检查利用支持 +func (p *IMAPPlugin) IsExploitSupported(method base.ExploitType) bool { + return p.exploiter.IsExploitSupported(method) +} + +// performServiceIdentification 执行IMAP服务识别(-nobr模式) +func (p *IMAPPlugin) performServiceIdentification(ctx context.Context, info *common.HostInfo) (*base.ScanResult, error) { + target := fmt.Sprintf("%s:%s", info.Host, info.Ports) + + // 根据端口选择连接类型 + var conn net.Conn + var err error + + if info.Ports == "993" { + // IMAPS端口,使用TLS连接 + tlsConfig := &tls.Config{ + InsecureSkipVerify: true, + } + conn, err = common.WrapperTlsWithContext(ctx, "tcp", target, tlsConfig) + } else { + // IMAP端口,使用普通连接 + conn, err = common.WrapperTcpWithContext(ctx, "tcp", target) + } + + if err != nil { + return &base.ScanResult{ + Success: false, + Error: err, + }, nil + } + defer conn.Close() + + // 读取IMAP Banner + imapInfo, isIMAP := p.identifyIMAPService(conn) + if isIMAP { + // 记录服务识别成功 + service := "IMAP" + if info.Ports == "993" { + service = "IMAPS" + } + common.LogSuccess(i18n.GetText("imap_service_identified", target, imapInfo)) + + return &base.ScanResult{ + Success: true, + Service: service, + Banner: imapInfo, + Extra: map[string]interface{}{ + "service": service, + "port": info.Ports, + "info": imapInfo, + }, + }, nil + } + + // 如果无法识别为IMAP,返回失败 + return &base.ScanResult{ + Success: false, + Error: fmt.Errorf("无法识别为IMAP服务"), + }, nil +} + +// identifyIMAPService 通过Banner识别IMAP服务 +func (p *IMAPPlugin) identifyIMAPService(conn net.Conn) (string, bool) { + // 设置读取超时 + conn.SetReadDeadline(time.Now().Add(time.Duration(common.Timeout) * time.Second)) + + // IMAP服务器在连接后会发送欢迎消息 + banner := make([]byte, 512) + n, err := conn.Read(banner) + if err != nil || n < 4 { + return "", false + } + + bannerStr := strings.TrimSpace(string(banner[:n])) + + // 检查IMAP协议标识 + if strings.Contains(bannerStr, "* OK") && (strings.Contains(strings.ToLower(bannerStr), "imap") || + strings.Contains(strings.ToLower(bannerStr), "dovecot") || + strings.Contains(strings.ToLower(bannerStr), "courier") || + strings.Contains(strings.ToLower(bannerStr), "cyrus")) { + + // 提取服务器信息 + if matched := regexp.MustCompile(`\* OK (.+?) ready`).FindStringSubmatch(bannerStr); len(matched) >= 2 { + return fmt.Sprintf("IMAP服务: %s", matched[1]), true + } + + if matched := regexp.MustCompile(`\* OK (.+?)$`).FindStringSubmatch(bannerStr); len(matched) >= 2 { + return fmt.Sprintf("IMAP服务: %s", matched[1]), true + } + + return fmt.Sprintf("IMAP服务: %s", bannerStr), true + } + + return "", false +} + +// ============================================================================= +// 插件注册 +// ============================================================================= + +// RegisterIMAPPlugin 注册IMAP插件 +func RegisterIMAPPlugin() { + factory := base.NewSimplePluginFactory( + &base.PluginMetadata{ + Name: "imap", + Version: "2.0.0", + Author: "fscan-team", + Description: "IMAP邮件服务扫描和利用插件", + Category: "service", + Ports: []int{143, 993}, // IMAP和IMAPS端口 + Protocols: []string{"tcp"}, + Tags: []string{"imap", "mail", "bruteforce"}, + }, + func() base.Plugin { + return NewIMAPPlugin() + }, + ) + + base.GlobalPluginRegistry.Register("imap", factory) +} + +// 自动注册 +func init() { + RegisterIMAPPlugin() +} \ No newline at end of file