package services import ( "context" "fmt" "net" "strings" "time" "github.com/shadow1ng/fscan/common" ) type MemcachedPlugin struct { name string ports []int } func NewMemcachedPlugin() *MemcachedPlugin { return &MemcachedPlugin{ name: "memcached", ports: []int{11211, 11212, 11213}, } } func (p *MemcachedPlugin) GetName() string { return p.name } func (p *MemcachedPlugin) GetPorts() []int { return p.ports } func (p *MemcachedPlugin) Scan(ctx context.Context, info *common.HostInfo) *ScanResult { target := fmt.Sprintf("%s:%s", info.Host, info.Ports) if common.DisableBrute { return p.identifyService(ctx, info) } conn := p.connectToMemcached(ctx, info) if conn == nil { return &ScanResult{ Success: false, Service: "memcached", Error: fmt.Errorf("Memcached服务连接失败"), } } defer conn.Close() if p.testBasicCommand(conn) { common.LogSuccess(fmt.Sprintf("Memcached %s 未授权访问", target)) return &ScanResult{ Success: true, Service: "memcached", Banner: "未授权访问", } } return &ScanResult{ Success: false, Service: "memcached", Error: fmt.Errorf("Memcached服务连接失败"), } } func (p *MemcachedPlugin) connectToMemcached(ctx context.Context, info *common.HostInfo) net.Conn { target := fmt.Sprintf("%s:%s", info.Host, info.Ports) timeout := time.Duration(common.Timeout) * time.Second conn, err := net.DialTimeout("tcp", target, timeout) if err != nil { return nil } conn.SetDeadline(time.Now().Add(timeout)) return conn } func (p *MemcachedPlugin) testBasicCommand(conn net.Conn) bool { timeout := time.Duration(common.Timeout) * time.Second conn.SetWriteDeadline(time.Now().Add(timeout)) if _, err := conn.Write([]byte("version\r\n")); err != nil { return false } conn.SetReadDeadline(time.Now().Add(timeout)) response := make([]byte, 1024) n, err := conn.Read(response) if err != nil { return false } responseStr := string(response[:n]) return strings.Contains(responseStr, "VERSION") || strings.Contains(responseStr, "memcached") } func (p *MemcachedPlugin) identifyService(ctx context.Context, info *common.HostInfo) *ScanResult { target := fmt.Sprintf("%s:%s", info.Host, info.Ports) conn := p.connectToMemcached(ctx, info) if conn == nil { return &ScanResult{ Success: false, Service: "memcached", Error: fmt.Errorf("无法连接到Memcached服务"), } } defer conn.Close() banner := "Memcached" if p.testBasicCommand(conn) { common.LogSuccess(fmt.Sprintf("Memcached %s %s", target, banner)) return &ScanResult{ Success: true, Service: "memcached", Banner: banner, } } return &ScanResult{ Success: false, Service: "memcached", Error: fmt.Errorf("无法识别为Memcached服务"), } } func init() { RegisterPlugin("memcached", func() Plugin { return NewMemcachedPlugin() }) }