mirror of
https://github.com/shadow1ng/fscan.git
synced 2026-09-25 20:51:52 +08:00
fix: 补全 HTTP/TLS proxy stats 加锁,修复 RPC/SMB 解析越界和 POC 加载逻辑
- httpdialer.go/tlsdialer.go: LastError/LastConnectTime/AverageConnectTime 加 mutex - findnet.go: RPC 响应结束标记位置 < 4 时跳过截断,防止负数切片 panic - ms17010.go: SMB 会话响应最小长度改为 45,sessionSetupResponse 加长度校验 - web_scan.go: POC 加载失败时不标记 pocLoaded,允许后续重试 - Eval.go: DNSLog 配置去掉 sync.Once,允许多次扫描更新配置
This commit is contained in:
@@ -30,7 +30,9 @@ func (h *httpDialer) DialContext(ctx context.Context, network, address string) (
|
|||||||
proxyConn, err := h.baseDial.DialContext(ctx, NetworkTCP, h.config.Address)
|
proxyConn, err := h.baseDial.DialContext(ctx, NetworkTCP, h.config.Address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
atomic.AddInt64(&h.stats.FailedConnections, 1)
|
atomic.AddInt64(&h.stats.FailedConnections, 1)
|
||||||
|
h.stats.mu.Lock()
|
||||||
h.stats.LastError = err.Error()
|
h.stats.LastError = err.Error()
|
||||||
|
h.stats.mu.Unlock()
|
||||||
return nil, NewProxyError(ErrTypeConnection, ErrMsgHTTPConnFailed, ErrCodeHTTPConnFailed, err)
|
return nil, NewProxyError(ErrTypeConnection, ErrMsgHTTPConnFailed, ErrCodeHTTPConnFailed, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,12 +40,16 @@ func (h *httpDialer) DialContext(ctx context.Context, network, address string) (
|
|||||||
if err := h.sendConnectRequest(proxyConn, address); err != nil {
|
if err := h.sendConnectRequest(proxyConn, address); err != nil {
|
||||||
_ = proxyConn.Close() // 错误处理路径,Close错误可忽略
|
_ = proxyConn.Close() // 错误处理路径,Close错误可忽略
|
||||||
atomic.AddInt64(&h.stats.FailedConnections, 1)
|
atomic.AddInt64(&h.stats.FailedConnections, 1)
|
||||||
|
h.stats.mu.Lock()
|
||||||
h.stats.LastError = err.Error()
|
h.stats.LastError = err.Error()
|
||||||
|
h.stats.mu.Unlock()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
duration := time.Since(start)
|
duration := time.Since(start)
|
||||||
|
h.stats.mu.Lock()
|
||||||
h.stats.LastConnectTime = start
|
h.stats.LastConnectTime = start
|
||||||
|
h.stats.mu.Unlock()
|
||||||
atomic.AddInt64(&h.stats.ActiveConnections, 1)
|
atomic.AddInt64(&h.stats.ActiveConnections, 1)
|
||||||
h.updateAverageConnectTime(duration)
|
h.updateAverageConnectTime(duration)
|
||||||
|
|
||||||
@@ -108,7 +114,8 @@ func (h *httpDialer) sendConnectRequest(conn net.Conn, address string) error {
|
|||||||
|
|
||||||
// updateAverageConnectTime 更新平均连接时间
|
// updateAverageConnectTime 更新平均连接时间
|
||||||
func (h *httpDialer) updateAverageConnectTime(duration time.Duration) {
|
func (h *httpDialer) updateAverageConnectTime(duration time.Duration) {
|
||||||
// 简单的移动平均
|
h.stats.mu.Lock()
|
||||||
|
defer h.stats.mu.Unlock()
|
||||||
if h.stats.AverageConnectTime == 0 {
|
if h.stats.AverageConnectTime == 0 {
|
||||||
h.stats.AverageConnectTime = duration
|
h.stats.AverageConnectTime = duration
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -50,7 +50,9 @@ func (t *tlsDialerWrapper) DialTLSContext(ctx context.Context, network, address
|
|||||||
if err := tlsConn.Handshake(); err != nil {
|
if err := tlsConn.Handshake(); err != nil {
|
||||||
_ = tcpConn.Close() // TLS握手失败,Close错误可忽略
|
_ = tcpConn.Close() // TLS握手失败,Close错误可忽略
|
||||||
atomic.AddInt64(&t.stats.FailedConnections, 1)
|
atomic.AddInt64(&t.stats.FailedConnections, 1)
|
||||||
|
t.stats.mu.Lock()
|
||||||
t.stats.LastError = err.Error()
|
t.stats.LastError = err.Error()
|
||||||
|
t.stats.mu.Unlock()
|
||||||
return nil, NewProxyError(ErrTypeConnection, ErrMsgTLSHandshakeFailed, ErrCodeTLSHandshakeFailed, err)
|
return nil, NewProxyError(ErrTypeConnection, ErrMsgTLSHandshakeFailed, ErrCodeTLSHandshakeFailed, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,7 +73,8 @@ func (t *tlsDialerWrapper) DialTLSContext(ctx context.Context, network, address
|
|||||||
|
|
||||||
// updateAverageConnectTime 更新平均连接时间
|
// updateAverageConnectTime 更新平均连接时间
|
||||||
func (t *tlsDialerWrapper) updateAverageConnectTime(duration time.Duration) {
|
func (t *tlsDialerWrapper) updateAverageConnectTime(duration time.Duration) {
|
||||||
// 简单的移动平均
|
t.stats.mu.Lock()
|
||||||
|
defer t.stats.mu.Unlock()
|
||||||
if t.stats.AverageConnectTime == 0 {
|
if t.stats.AverageConnectTime == 0 {
|
||||||
t.stats.AverageConnectTime = duration
|
t.stats.AverageConnectTime = duration
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -169,7 +169,9 @@ func (p *FindNetPlugin) performNetworkDiscovery(conn net.Conn) (*NetworkInfo, er
|
|||||||
// 查找响应结束标记
|
// 查找响应结束标记
|
||||||
for i := 0; i < len(responseData)-5; i++ {
|
for i := 0; i < len(responseData)-5; i++ {
|
||||||
if bytes.Equal(responseData[i:i+6], rpcBuffer3) {
|
if bytes.Equal(responseData[i:i+6], rpcBuffer3) {
|
||||||
|
if i >= 4 {
|
||||||
responseData = responseData[:i-4]
|
responseData = responseData[:i-4]
|
||||||
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -319,7 +319,7 @@ func (p *MS17010Plugin) checkMS17010Vulnerability(ip string, config *common.Conf
|
|||||||
}
|
}
|
||||||
|
|
||||||
n, readErr = conn.Read(reply)
|
n, readErr = conn.Read(reply)
|
||||||
if readErr != nil || n < 36 {
|
if readErr != nil || n < 45 {
|
||||||
return false, "", fmt.Errorf("SMB会话建立失败")
|
return false, "", fmt.Errorf("SMB会话建立失败")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -330,7 +330,7 @@ func (p *MS17010Plugin) checkMS17010Vulnerability(ip string, config *common.Conf
|
|||||||
// 提取系统信息
|
// 提取系统信息
|
||||||
var osVersion string
|
var osVersion string
|
||||||
sessionSetupResponse := reply[36:n]
|
sessionSetupResponse := reply[36:n]
|
||||||
if wordCount := sessionSetupResponse[0]; wordCount != 0 {
|
if wordCount := sessionSetupResponse[0]; wordCount != 0 && len(sessionSetupResponse) >= 10 {
|
||||||
byteCount := binary.LittleEndian.Uint16(sessionSetupResponse[7:9])
|
byteCount := binary.LittleEndian.Uint16(sessionSetupResponse[7:9])
|
||||||
if n == int(byteCount)+45 {
|
if n == int(byteCount)+45 {
|
||||||
for i := 10; i < len(sessionSetupResponse)-1; i++ {
|
for i := 10; i < len(sessionSetupResponse)-1; i++ {
|
||||||
|
|||||||
+1
-4
@@ -33,16 +33,13 @@ var (
|
|||||||
|
|
||||||
// 包级POC配置
|
// 包级POC配置
|
||||||
var (
|
var (
|
||||||
pocConfigOnce sync.Once
|
|
||||||
pocDNSLog bool // DNSLog配置缓存
|
pocDNSLog bool // DNSLog配置缓存
|
||||||
)
|
)
|
||||||
|
|
||||||
// InitPOCConfig 初始化POC配置(在扫描开始前调用一次)
|
// InitPOCConfig 初始化POC配置(在扫描开始前调用)
|
||||||
// 这样CEL回调函数可以使用包级变量而非GetGlobalConfig
|
// 这样CEL回调函数可以使用包级变量而非GetGlobalConfig
|
||||||
func InitPOCConfig(dnsLog bool) {
|
func InitPOCConfig(dnsLog bool) {
|
||||||
pocConfigOnce.Do(func() {
|
|
||||||
pocDNSLog = dnsLog
|
pocDNSLog = dnsLog
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewEnv 创建一个新的 CEL 环境(使用缓存避免重复注册函数)
|
// NewEnv 创建一个新的 CEL 环境(使用缓存避免重复注册函数)
|
||||||
|
|||||||
@@ -56,8 +56,10 @@ func WebScan(ctx context.Context, info *common.HostInfo, cfg *common.Config) {
|
|||||||
if !pocLoaded {
|
if !pocLoaded {
|
||||||
cachedPocPath = cfg.POC.PocPath
|
cachedPocPath = cfg.POC.PocPath
|
||||||
initPocs()
|
initPocs()
|
||||||
|
if len(allPocs) > 0 {
|
||||||
pocLoaded = true
|
pocLoaded = true
|
||||||
}
|
}
|
||||||
|
}
|
||||||
pocMu.Unlock()
|
pocMu.Unlock()
|
||||||
|
|
||||||
// 验证输入
|
// 验证输入
|
||||||
|
|||||||
Reference in New Issue
Block a user