fscan/Plugins/Memcached.go
ZacharyZcR 05ba01f170 refactor: 统一包命名规范并清理冗余文件
主要更改:
- 统一包目录命名为小写(Core→core, Plugins→plugins, WebScan→webscan)
- 更新所有import路径以符合Go语言命名规范
- 重构parsers模块,简化复杂的工厂模式(从2000+行优化至400行)
- 移除i18n兼容层,统一使用模块化i18n包
- 简化Core/Manager.go架构(从591行优化至133行)
- 清理冗余文件:备份文件、构建产物、测试配置、重复图片
- 移除TestDocker测试环境配置目录
- 解决变量命名冲突问题

性能优化:
- 减少代码复杂度60-70%
- 提升构建和运行性能
- 保持完整功能兼容性

代码质量:
- 符合Go语言最佳实践
- 统一命名规范
- 优化项目结构
2025-08-06 01:30:18 +08:00

161 lines
3.6 KiB
Go

package Plugins
import (
"context"
"fmt"
"github.com/shadow1ng/fscan/common"
"strings"
"time"
)
// MemcachedScanResult 表示Memcached扫描结果
type MemcachedScanResult struct {
Success bool
Error error
Stats string
}
// MemcachedScan 检测Memcached未授权访问
func MemcachedScan(info *common.HostInfo) error {
// 设置全局超时上下文
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(common.GlobalTimeout)*time.Second)
defer cancel()
realhost := fmt.Sprintf("%s:%v", info.Host, info.Ports)
common.LogDebug(fmt.Sprintf("开始扫描 Memcached %s", realhost))
// 尝试连接并检查未授权访问
result := tryMemcachedConnection(ctx, info, common.Timeout)
if result.Success {
// 保存成功结果
scanResult := &common.ScanResult{
Time: time.Now(),
Type: common.VULN,
Target: info.Host,
Status: "vulnerable",
Details: map[string]interface{}{
"port": info.Ports,
"service": "memcached",
"type": "unauthorized-access",
"description": "Memcached unauthorized access",
"stats": result.Stats,
},
}
common.SaveResult(scanResult)
common.LogSuccess(fmt.Sprintf("Memcached %s 未授权访问", realhost))
}
// 检查是否因为全局超时而退出
select {
case <-ctx.Done():
if ctx.Err() == context.DeadlineExceeded {
common.LogDebug("Memcached扫描全局超时")
return fmt.Errorf("全局超时")
}
default:
}
common.LogDebug(fmt.Sprintf("Memcached扫描完成: %s", realhost))
return result.Error
}
// tryMemcachedConnection 尝试连接Memcached并检查未授权访问
func tryMemcachedConnection(ctx context.Context, info *common.HostInfo, timeoutSeconds int64) *MemcachedScanResult {
realhost := fmt.Sprintf("%s:%v", info.Host, info.Ports)
timeout := time.Duration(timeoutSeconds) * time.Second
// 创建结果通道
resultChan := make(chan *MemcachedScanResult, 1)
// 创建连接上下文,带超时
connCtx, connCancel := context.WithTimeout(ctx, timeout)
defer connCancel()
// 在协程中尝试连接
go func() {
// 构建结果结构
result := &MemcachedScanResult{
Success: false,
Error: nil,
Stats: "",
}
// 建立TCP连接
client, err := common.WrapperTcpWithTimeout("tcp", realhost, timeout)
if err != nil {
result.Error = err
select {
case <-connCtx.Done():
case resultChan <- result:
}
return
}
defer client.Close()
// 设置操作截止时间
if err := client.SetDeadline(time.Now().Add(timeout)); err != nil {
result.Error = err
select {
case <-connCtx.Done():
case resultChan <- result:
}
return
}
// 发送stats命令
if _, err := client.Write([]byte("stats\n")); err != nil {
result.Error = err
select {
case <-connCtx.Done():
case resultChan <- result:
}
return
}
// 读取响应
rev := make([]byte, 1024)
n, err := client.Read(rev)
if err != nil {
result.Error = err
select {
case <-connCtx.Done():
case resultChan <- result:
}
return
}
// 检查响应是否包含统计信息
response := string(rev[:n])
if strings.Contains(response, "STAT") {
result.Success = true
result.Stats = response
}
// 发送结果
select {
case <-connCtx.Done():
case resultChan <- result:
}
}()
// 等待结果或上下文取消
select {
case result := <-resultChan:
return result
case <-connCtx.Done():
if ctx.Err() != nil {
// 全局上下文取消
return &MemcachedScanResult{
Success: false,
Error: ctx.Err(),
}
}
// 连接超时
return &MemcachedScanResult{
Success: false,
Error: fmt.Errorf("连接超时"),
}
}
}