fscan/plugins/services/ldap.go
ZacharyZcR 8ae94f7813 fix: 修复LDAP插件结构体和接口兼容性问题
## 主要修复
- 将ScanResult结构体改为plugins.Result
- 将Credential结构体改为plugins.Credential
- 将GenerateCredentials函数改为plugins.GenerateCredentials
- 将RegisterPluginWithPorts改为plugins.RegisterWithPorts
- 添加上下文取消检查,提升扫描控制能力

## 测试结果
- 服务识别模式(-nobr)正常工作:成功识别LDAP 127.0.0.1:389
- 密码爆破模式正常运行,不再报告"未发现弱密码"错误
- 插件接口与新架构完全兼容
2025-09-02 04:06:39 +00:00

110 lines
2.4 KiB
Go

package services
import (
"context"
"fmt"
ldaplib "github.com/go-ldap/ldap/v3"
"github.com/shadow1ng/fscan/common"
"github.com/shadow1ng/fscan/plugins"
)
type LDAPPlugin struct {
plugins.BasePlugin
}
func NewLDAPPlugin() *LDAPPlugin {
return &LDAPPlugin{
BasePlugin: plugins.NewBasePlugin("ldap"),
}
}
func (p *LDAPPlugin) Scan(ctx context.Context, info *common.HostInfo) *plugins.Result {
target := fmt.Sprintf("%s:%s", info.Host, info.Ports)
if common.DisableBrute {
return p.identifyService(ctx, info)
}
credentials := plugins.GenerateCredentials("ldap")
for _, cred := range credentials {
// 检查上下文是否已取消
select {
case <-ctx.Done():
return &plugins.Result{
Success: false,
Service: "ldap",
Error: ctx.Err(),
}
default:
}
if p.testCredential(ctx, info, cred) {
common.LogSuccess(fmt.Sprintf("LDAP %s %s:%s", target, cred.Username, cred.Password))
return &plugins.Result{
Success: true,
Service: "ldap",
Username: cred.Username,
Password: cred.Password,
}
}
}
return &plugins.Result{
Success: false,
Service: "ldap",
Error: fmt.Errorf("未发现弱密码"),
}
}
func (p *LDAPPlugin) testCredential(ctx context.Context, info *common.HostInfo, cred plugins.Credential) bool {
conn, err := p.connectLDAP(ctx, info, cred)
if err != nil {
return false
}
defer conn.Close()
// 简单的绑定测试
if err := conn.Bind(cred.Username, cred.Password); err == nil {
return true
}
return false
}
func (p *LDAPPlugin) connectLDAP(ctx context.Context, info *common.HostInfo, creds plugins.Credential) (*ldaplib.Conn, error) {
target := fmt.Sprintf("%s:%s", info.Host, info.Ports)
if info.Ports == "636" {
return ldaplib.DialTLS("tcp", target, nil)
}
return ldaplib.Dial("tcp", target)
}
func (p *LDAPPlugin) identifyService(ctx context.Context, info *common.HostInfo) *plugins.Result {
target := fmt.Sprintf("%s:%s", info.Host, info.Ports)
conn, err := p.connectLDAP(ctx, info, plugins.Credential{})
if err != nil {
return &plugins.Result{
Success: false,
Service: "ldap",
Error: err,
}
}
defer conn.Close()
banner := "LDAP"
common.LogSuccess(fmt.Sprintf("LDAP %s %s", target, banner))
return &plugins.Result{
Success: true,
Service: "ldap",
Banner: banner,
}
}
func init() {
plugins.RegisterWithPorts("ldap", func() plugins.Plugin {
return NewLDAPPlugin()
}, []int{389, 636, 3268, 3269})
}