mirror of
https://github.com/shadow1ng/fscan.git
synced 2026-09-25 20:51:52 +08:00
fix: 大型修复,增加超时和线程控制
This commit is contained in:
+131
-31
@@ -1,46 +1,35 @@
|
||||
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)
|
||||
timeout := time.Duration(Common.Timeout) * time.Second
|
||||
Common.LogDebug(fmt.Sprintf("开始扫描 Memcached %s", realhost))
|
||||
|
||||
// 建立TCP连接
|
||||
client, err := Common.WrapperTcpWithTimeout("tcp", realhost, timeout)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer client.Close()
|
||||
// 尝试连接并检查未授权访问
|
||||
result := tryMemcachedConnection(ctx, info, Common.Timeout)
|
||||
|
||||
// 设置超时时间
|
||||
if err := client.SetDeadline(time.Now().Add(timeout)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 发送stats命令
|
||||
if _, err := client.Write([]byte("stats\n")); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 读取响应
|
||||
rev := make([]byte, 1024)
|
||||
n, err := client.Read(rev)
|
||||
if err != nil {
|
||||
Common.LogError(fmt.Sprintf("Memcached %v:%v %v", info.Host, info.Ports, err))
|
||||
return err
|
||||
}
|
||||
|
||||
// 检查响应内容
|
||||
if strings.Contains(string(rev[:n]), "STAT") {
|
||||
// 保存结果
|
||||
result := &Common.ScanResult{
|
||||
if result.Success {
|
||||
// 保存成功结果
|
||||
scanResult := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.VULN,
|
||||
Target: info.Host,
|
||||
@@ -50,11 +39,122 @@ func MemcachedScan(info *Common.HostInfo) error {
|
||||
"service": "memcached",
|
||||
"type": "unauthorized-access",
|
||||
"description": "Memcached unauthorized access",
|
||||
"stats": result.Stats,
|
||||
},
|
||||
}
|
||||
Common.SaveResult(result)
|
||||
Common.SaveResult(scanResult)
|
||||
Common.LogSuccess(fmt.Sprintf("Memcached %s 未授权访问", realhost))
|
||||
}
|
||||
|
||||
return nil
|
||||
// 检查是否因为全局超时而退出
|
||||
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("连接超时"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user