mirror of
https://github.com/shadow1ng/fscan.git
synced 2025-09-14 14:06:44 +08:00

- 修改SMB插件,在testCredential和identifyService中添加发包控制 - 修改LDAP插件,在connectLDAP中添加发包控制和包计数 - 统一包计数逻辑,确保TCP连接成功和失败都正确计数 - 保持现有功能不变,提升网络操作一致性
150 lines
3.6 KiB
Go
150 lines
3.6 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()
|
||
|
||
// 尝试多种DN格式进行绑定测试
|
||
dnFormats := []string{
|
||
fmt.Sprintf("cn=%s,dc=example,dc=com", cred.Username), // 标准格式
|
||
fmt.Sprintf("uid=%s,dc=example,dc=com", cred.Username), // uid格式
|
||
fmt.Sprintf("cn=%s,ou=users,dc=example,dc=com", cred.Username), // ou格式
|
||
cred.Username, // 直接用户名(某些配置)
|
||
}
|
||
|
||
for _, dn := range dnFormats {
|
||
if err := conn.Bind(dn, cred.Password); err == nil {
|
||
common.LogDebug(fmt.Sprintf("LDAP绑定成功,DN: %s", dn))
|
||
return true
|
||
}
|
||
common.LogDebug(fmt.Sprintf("LDAP绑定失败,DN: %s, 错误: %v", dn, err))
|
||
}
|
||
return false
|
||
}
|
||
|
||
func (p *LDAPPlugin) connectLDAP(ctx context.Context, info *common.HostInfo, creds plugins.Credential) (*ldaplib.Conn, error) {
|
||
// 检查发包限制
|
||
if canSend, reason := common.CanSendPacket(); !canSend {
|
||
common.LogError(fmt.Sprintf("LDAP连接 %s:%s 受限: %s", info.Host, info.Ports, reason))
|
||
return nil, fmt.Errorf("发包受限: %s", reason)
|
||
}
|
||
|
||
target := fmt.Sprintf("%s:%s", info.Host, info.Ports)
|
||
|
||
var conn *ldaplib.Conn
|
||
var err error
|
||
|
||
if info.Ports == "636" {
|
||
conn, err = ldaplib.DialTLS("tcp", target, nil)
|
||
} else {
|
||
conn, err = ldaplib.Dial("tcp", target)
|
||
}
|
||
|
||
// 统计包数量
|
||
if err != nil {
|
||
common.IncrementTCPFailedPacketCount()
|
||
} else {
|
||
common.IncrementTCPSuccessPacketCount()
|
||
}
|
||
|
||
return conn, err
|
||
}
|
||
|
||
func (p *LDAPPlugin) identifyService(ctx context.Context, info *common.HostInfo) *plugins.Result {
|
||
target := fmt.Sprintf("%s:%s", info.Host, info.Ports)
|
||
|
||
// 检查发包限制
|
||
if canSend, reason := common.CanSendPacket(); !canSend {
|
||
common.LogError(fmt.Sprintf("LDAP识别 %s 受限: %s", target, reason))
|
||
return &plugins.Result{
|
||
Success: false,
|
||
Service: "ldap",
|
||
Error: fmt.Errorf("发包受限: %s", reason),
|
||
}
|
||
}
|
||
|
||
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})
|
||
} |