refactor: 全量替换 WrapperTcpWithTimeout 为 session.DialTCP (Phase 4)

- core/port_scan.go: EnhancedPortScan/connectWithRetry/scanSinglePort 接入 session
- core/service_probe.go: SmartPortInfoScanner 持有 session,重连走 session.DialTCP
- core/icmp.go: CheckLive/tcpProbeAlive 接入 session
- 17 个 service 插件: 内部 helper 函数全部穿透 ctx+session
- 移除插件中冗余的手动 TCP 计数(DialTCP 内部已处理)
- plugins/core 下已无 WrapperTcpWithTimeout/SafeTCPDial 调用残留
This commit is contained in:
ZacharyZcR
2026-04-27 23:27:21 +08:00
parent a865e5d45e
commit c98805e85a
24 changed files with 266 additions and 339 deletions
+3 -3
View File
@@ -62,14 +62,14 @@ func (s *AliveScanStrategy) Execute(_ context.Context, session *common.ScanSessi
}
// 执行存活探测
s.performAliveScan(info, session.Config, session.State)
s.performAliveScan(info, session)
// 输出统计信息
s.outputStats()
}
// performAliveScan 执行存活探测
func (s *AliveScanStrategy) performAliveScan(info common.HostInfo, config *common.Config, state *common.State) {
func (s *AliveScanStrategy) performAliveScan(info common.HostInfo, session *common.ScanSession) {
// 解析目标主机
fv := common.GetFlagVars()
hosts, err := parsers.ParseIP(info.Host, fv.HostsFile, fv.ExcludeHosts)
@@ -90,7 +90,7 @@ func (s *AliveScanStrategy) performAliveScan(info common.HostInfo, config *commo
// 执行存活检测
aliveList := CheckLive(hosts, false, config, state) // 使用ICMP探测
aliveList := CheckLive(hosts, false, session) // 使用ICMP探测
// 更新统计信息
s.stats.AliveHosts = len(aliveList)
+12 -8
View File
@@ -2,6 +2,7 @@ package core
import (
"bytes"
"context"
"errors"
"fmt"
"net"
@@ -39,7 +40,9 @@ var pingErrorKeywords = []string{
// CheckLive 检测主机存活状态
// 支持 ICMP/Ping 探测,并在响应率过低时自动启用 TCP 补充探测
func CheckLive(hostslist []string, Ping bool, config *common.Config, state *common.State) []string {
func CheckLive(hostslist []string, Ping bool, session *common.ScanSession) []string {
config := session.Config
state := session.State
// 创建局部WaitGroup
var livewg sync.WaitGroup
@@ -68,7 +71,7 @@ func CheckLive(hostslist []string, Ping bool, config *common.Config, state *comm
// TCP 补充探测:当 ICMP/Ping 响应率过低时自动启用
// 这对防火墙过滤 ICMP 的环境特别有用
aliveHosts = tcpSupplementaryProbe(hostslist, aliveHosts, config)
aliveHosts = tcpSupplementaryProbe(hostslist, aliveHosts, session)
// 输出存活统计信息
printAliveStats(aliveHosts, hostslist)
@@ -78,7 +81,7 @@ func CheckLive(hostslist []string, Ping bool, config *common.Config, state *comm
// tcpSupplementaryProbe TCP 补充探测
// 当 ICMP 响应率过低时(<10%),对未响应主机进行 TCP 探测
func tcpSupplementaryProbe(allHosts []string, aliveHosts []string, config *common.Config) []string {
func tcpSupplementaryProbe(allHosts []string, aliveHosts []string, session *common.ScanSession) []string {
totalHosts := len(allHosts)
if totalHosts == 0 {
return aliveHosts
@@ -102,7 +105,7 @@ func tcpSupplementaryProbe(allHosts []string, aliveHosts []string, config *commo
common.LogInfo(i18n.Tr("tcp_probe_low_icmp_rate", fmt.Sprintf("%.1f%%", responseRate*100), len(unrespondedHosts)))
// 执行 TCP 补充探测
tcpAliveHosts := runTcpProbeForHosts(unrespondedHosts, config)
tcpAliveHosts := runTcpProbeForHosts(unrespondedHosts, session)
// 合并结果
if len(tcpAliveHosts) > 0 {
@@ -682,10 +685,10 @@ const tcpProbeThreshold = 0.1 // 10%
// tcpProbeAlive 使用 TCP 探测主机是否存活
// 尝试连接常用端口,任一端口响应即认为存活
func tcpProbeAlive(host string) bool {
func tcpProbeAlive(session *common.ScanSession, host string) bool {
for _, port := range tcpProbeCommonPorts {
addr := fmt.Sprintf("%s:%d", host, port)
conn, err := common.WrapperTcpWithTimeout("tcp", addr, tcpProbeTimeout)
conn, err := session.DialTCP(context.Background(), "tcp", addr, tcpProbeTimeout)
if err == nil {
_ = conn.Close()
return true
@@ -696,7 +699,8 @@ func tcpProbeAlive(host string) bool {
// runTcpProbeForHosts 对指定主机列表进行 TCP 补充探测
// 返回存活的主机列表
func runTcpProbeForHosts(hosts []string, config *common.Config) []string {
func runTcpProbeForHosts(hosts []string, session *common.ScanSession) []string {
config := session.Config
if len(hosts) == 0 {
return nil
}
@@ -722,7 +726,7 @@ func runTcpProbeForHosts(hosts []string, config *common.Config) []string {
wg.Done()
}()
if tcpProbeAlive(h) {
if tcpProbeAlive(session, h) {
mu.Lock()
aliveHosts = append(aliveHosts, h)
mu.Unlock()
+13 -9
View File
@@ -1,6 +1,7 @@
package core
import (
"context"
"fmt"
"net"
"strings"
@@ -110,7 +111,9 @@ func (f *failedPortCollector) Count() int {
// EnhancedPortScan 高性能端口扫描函数
// 使用滑动窗口调度 + 自适应线程池 + 流式迭代器
func EnhancedPortScan(hosts []string, ports string, timeout int64, config *common.Config, state *common.State) []string {
func EnhancedPortScan(hosts []string, ports string, timeout int64, session *common.ScanSession) []string {
config := session.Config
state := session.State
common.LogDebug(fmt.Sprintf("[PortScan] 开始: %d个主机, 线程数=%d", len(hosts), config.ThreadNum))
// 解析端口和排除端口
@@ -179,7 +182,7 @@ func EnhancedPortScan(hosts []string, ports string, timeout int64, config *commo
}()
addr := fmt.Sprintf("%s:%d", taskInfo.host, taskInfo.port)
scanSinglePort(taskInfo.host, taskInfo.port, addr, to, &count, collector, failedCollector, config, state)
scanSinglePort(taskInfo.host, taskInfo.port, addr, to, &count, collector, failedCollector, session)
common.UpdateProgressBar(1)
}, state)
if err != nil {
@@ -263,11 +266,11 @@ func slidingWindowSchedule(iter *SocketIterator, pool *AdaptivePool, wg *sync.Wa
}
// connectWithRetry 带重试的TCP连接 - 只对资源耗尽错误重试
func connectWithRetry(addr string, timeout time.Duration, maxRetries int, state *common.State) (net.Conn, error) {
func connectWithRetry(ctx context.Context, session *common.ScanSession, addr string, timeout time.Duration, maxRetries int) (net.Conn, error) {
var lastErr error
for attempt := 0; attempt < maxRetries; attempt++ {
conn, err := common.WrapperTcpWithTimeout("tcp", addr, timeout)
conn, err := session.DialTCP(ctx, "tcp", addr, timeout)
if err == nil {
return conn, nil
@@ -281,7 +284,7 @@ func connectWithRetry(addr string, timeout time.Duration, maxRetries int, state
}
// 记录资源耗尽错误
state.IncrementResourceExhaustedCount()
session.State.IncrementResourceExhaustedCount()
// 指数退避:第1次等50ms,第2次等150ms
if attempt < maxRetries-1 {
@@ -344,9 +347,10 @@ func buildServiceLogMessage(addr string, serviceInfo *ServiceInfo, isWeb bool) s
}
// scanSinglePort 扫描单个端口并进行服务识别(重构后的简洁版本)
func scanSinglePort(host string, port int, addr string, timeout time.Duration, count *int64, collector *resultCollector, failedCollector *failedPortCollector, config *common.Config, state *common.State) {
func scanSinglePort(host string, port int, addr string, timeout time.Duration, count *int64, collector *resultCollector, failedCollector *failedPortCollector, session *common.ScanSession) {
config := session.Config
// 步骤1:建立连接
conn, err := connectWithRetry(addr, timeout, 3, state)
conn, err := connectWithRetry(context.Background(), session, addr, timeout, 3)
if err != nil {
handleConnectionFailure(err, host, port, addr, failedCollector)
return
@@ -365,7 +369,7 @@ func scanSinglePort(host string, port int, addr string, timeout time.Duration, c
if common.IsProxyEnabled() && verifyMethod != "direct" {
_ = conn.Close()
// 重新建立干净的连接用于服务识别
conn, err = connectWithRetry(addr, timeout, 3, state)
conn, err = connectWithRetry(context.Background(), session, addr, timeout, 3)
if err != nil {
handleConnectionFailure(err, host, port, addr, failedCollector)
return
@@ -378,7 +382,7 @@ func scanSinglePort(host string, port int, addr string, timeout time.Duration, c
saveOpenPort(host, port)
// 步骤3:服务识别(Scanner负责关闭连接,包括探测中可能创建的新连接)
scanner := NewSmartPortInfoScanner(host, port, conn, timeout, config)
scanner := NewSmartPortInfoScanner(host, port, conn, timeout, config, session)
defer scanner.Close()
serviceInfo, _ := scanner.SmartIdentify()
+16 -11
View File
@@ -1,6 +1,7 @@
package core
import (
"context"
"errors"
"fmt"
"io"
@@ -70,13 +71,14 @@ type Service struct {
// Info 定义单个端口探测的上下文信息
type Info struct {
Address string // 目标IP地址
Port int // 目标端口
Conn net.Conn // 网络连接
Result Result // 探测结果
Found bool // 是否成功识别服务
config *common.Config // 配置引用
readTimeoutMS int // 当前读取超时时间(毫秒)
Address string // 目标IP地址
Port int // 目标端口
Conn net.Conn // 网络连接
Result Result // 探测结果
Found bool // 是否成功识别服务
config *common.Config // 配置引用
session *common.ScanSession // 会话引用
readTimeoutMS int // 当前读取超时时间(毫秒)
}
// SmartPortInfoScanner 智能服务识别器:保持nmap准确性,优化网络交互
@@ -86,24 +88,27 @@ type SmartPortInfoScanner struct {
Conn net.Conn
Timeout time.Duration
info *Info
config *common.Config // 配置引用
config *common.Config // 配置引用
session *common.ScanSession // 会话引用
}
// 预定义的基础探测器已在PortFinger.go中定义,这里不再重复定义
// NewSmartPortInfoScanner 创建智能服务识别器
func NewSmartPortInfoScanner(addr string, port int, conn net.Conn, timeout time.Duration, config *common.Config) *SmartPortInfoScanner {
func NewSmartPortInfoScanner(addr string, port int, conn net.Conn, timeout time.Duration, config *common.Config, session *common.ScanSession) *SmartPortInfoScanner {
return &SmartPortInfoScanner{
Address: addr,
Port: port,
Conn: conn,
Timeout: timeout,
config: config,
session: session,
info: &Info{
Address: addr,
Port: port,
Conn: conn,
config: config,
session: session,
Result: Result{
Service: Service{},
},
@@ -251,7 +256,7 @@ func (s *SmartPortInfoScanner) reconnectIfNeeded() {
}
// 重新建立连接
newConn, err := common.WrapperTcpWithTimeout("tcp", fmt.Sprintf("%s:%d", s.Address, s.Port), s.Timeout)
newConn, err := s.session.DialTCP(context.Background(), "tcp", fmt.Sprintf("%s:%d", s.Address, s.Port), s.Timeout)
if err != nil {
return
}
@@ -511,7 +516,7 @@ func (i *Info) Write(msg []byte) error {
_ = oldConn.Close()
// 尝试重新连接 - 支持SOCKS5代理
newConn, retryErr := common.WrapperTcpWithTimeout("tcp", fmt.Sprintf("%s:%d", i.Address, i.Port), time.Duration(6)*time.Second)
newConn, retryErr := i.session.DialTCP(context.Background(), "tcp", fmt.Sprintf("%s:%d", i.Address, i.Port), time.Duration(6)*time.Second)
if retryErr != nil {
return retryErr
}
+1 -1
View File
@@ -155,7 +155,7 @@ func TestSmartPortInfoScanner_Creation(t *testing.T) {
}
// 使用 nil 连接(实际测试中会使用真实连接)
scanner := NewSmartPortInfoScanner("127.0.0.1", 80, nil, 3*time.Second, config)
scanner := NewSmartPortInfoScanner("127.0.0.1", 80, nil, 3*time.Second, config, nil)
if scanner == nil {
t.Fatal("Scanner 创建失败")
+12 -8
View File
@@ -141,7 +141,7 @@ func (s *ServiceScanStrategy) Execute(ctx context.Context, session *common.ScanS
// performHostScan 执行主机扫描的完整流程
func (s *ServiceScanStrategy) performHostScan(ctx context.Context, session *common.ScanSession, info common.HostInfo, ch chan struct{}, wg *sync.WaitGroup) {
// 发现目标主机和端口
targetInfos, err := s.discoverTargets(info.Host, info, session.Config, session.State)
targetInfos, err := s.discoverTargets(info.Host, info, session)
if err != nil {
common.LogError(err.Error())
return
@@ -154,9 +154,9 @@ func (s *ServiceScanStrategy) performHostScan(ctx context.Context, session *comm
}
// PrepareTargets 准备目标信息
func (s *ServiceScanStrategy) PrepareTargets(info common.HostInfo, config *common.Config, state *common.State) []common.HostInfo {
func (s *ServiceScanStrategy) PrepareTargets(info common.HostInfo, session *common.ScanSession) []common.HostInfo {
// 发现目标主机和端口
targetInfos, err := s.discoverTargets(info.Host, info, config, state)
targetInfos, err := s.discoverTargets(info.Host, info, session)
if err != nil {
common.LogError(err.Error())
return nil
@@ -215,7 +215,9 @@ func (s *ServiceScanStrategy) LogVulnerabilityPluginInfo(targets []common.HostIn
// =============================================================================
// discoverTargets 发现目标主机和端口
func (s *ServiceScanStrategy) discoverTargets(hostInput string, baseInfo common.HostInfo, config *common.Config, state *common.State) ([]common.HostInfo, error) {
func (s *ServiceScanStrategy) discoverTargets(hostInput string, baseInfo common.HostInfo, session *common.ScanSession) ([]common.HostInfo, error) {
config := session.Config
state := session.State
// 标准流程:解析目标主机
fv := common.GetFlagVars()
hosts, err := parsers.ParseIP(hostInput, fv.HostsFile, fv.ExcludeHosts)
@@ -229,12 +231,12 @@ func (s *ServiceScanStrategy) discoverTargets(hostInput string, baseInfo common.
if len(hosts) > 0 || len(state.GetHostPorts()) > 0 {
// 主机存活检测
if s.shouldPerformLivenessCheck(hosts, config) {
hosts = CheckLive(hosts, false, config, state)
hosts = CheckLive(hosts, false, session)
common.LogInfo(i18n.Tr("alive_hosts_count_info", len(hosts)))
}
// 端口扫描
alivePorts := s.discoverAlivePorts(hosts, config, state)
alivePorts := s.discoverAlivePorts(hosts, session)
if len(alivePorts) > 0 {
targetInfos = s.convertToTargetInfos(alivePorts, baseInfo)
}
@@ -249,7 +251,9 @@ func (s *ServiceScanStrategy) shouldPerformLivenessCheck(hosts []string, config
}
// discoverAlivePorts 发现存活的端口
func (s *ServiceScanStrategy) discoverAlivePorts(hosts []string, config *common.Config, state *common.State) []string {
func (s *ServiceScanStrategy) discoverAlivePorts(hosts []string, session *common.ScanSession) []string {
config := session.Config
state := session.State
var alivePorts []string
// 如果已经有明确指定的host:port,直接使用(让后续SmartIdentify统一验证和识别)
@@ -263,7 +267,7 @@ func (s *ServiceScanStrategy) discoverAlivePorts(hosts []string, config *common.
// 根据扫描模式选择端口扫描方式
if len(hosts) > 0 {
alivePorts = EnhancedPortScan(hosts, config.Target.Ports, int64(config.Timeout.Seconds()), config, state)
alivePorts = EnhancedPortScan(hosts, config.Target.Ports, int64(config.Timeout.Seconds()), session)
}
return alivePorts
+10 -18
View File
@@ -27,11 +27,10 @@ func NewActiveMQPlugin() *ActiveMQPlugin {
func (p *ActiveMQPlugin) Scan(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult {
config := session.Config
state := session.State
target := info.Target()
if config.DisableBrute {
return p.identifyService(ctx, info, config, state)
return p.identifyService(ctx, info, session)
}
// 生成测试凭据
@@ -50,7 +49,7 @@ func (p *ActiveMQPlugin) Scan(ctx context.Context, info *common.HostInfo, sessio
}
// 使用公共框架进行并发凭据测试
authFn := p.createAuthFunc(info, config, state)
authFn := p.createAuthFunc(info, session)
testConfig := DefaultConcurrentTestConfig(config)
result := TestCredentialsConcurrently(ctx, credentials, authFn, "activemq", testConfig)
@@ -63,23 +62,23 @@ func (p *ActiveMQPlugin) Scan(ctx context.Context, info *common.HostInfo, sessio
}
// createAuthFunc 创建ActiveMQ认证函数
func (p *ActiveMQPlugin) createAuthFunc(info *common.HostInfo, config *common.Config, state *common.State) AuthFunc {
func (p *ActiveMQPlugin) createAuthFunc(info *common.HostInfo, session *common.ScanSession) AuthFunc {
return func(ctx context.Context, cred Credential) *AuthResult {
return p.doActiveMQAuth(ctx, info, cred, config, state)
return p.doActiveMQAuth(ctx, info, cred, session)
}
}
// doActiveMQAuth 执行ActiveMQ认证
func (p *ActiveMQPlugin) doActiveMQAuth(ctx context.Context, info *common.HostInfo, cred Credential, config *common.Config, state *common.State) *AuthResult {
func (p *ActiveMQPlugin) doActiveMQAuth(ctx context.Context, info *common.HostInfo, cred Credential, session *common.ScanSession) *AuthResult {
target := info.Target()
config := session.Config
timeout := config.Timeout
resultChan := make(chan *AuthResult, 1)
go func() {
conn, err := common.WrapperTcpWithTimeout("tcp", target, timeout)
conn, err := session.DialTCP(ctx, "tcp", target, timeout)
if err != nil {
state.IncrementTCPFailedPacketCount()
resultChan <- &AuthResult{
Success: false,
ErrorType: classifyActiveMQErrorType(err),
@@ -90,7 +89,6 @@ func (p *ActiveMQPlugin) doActiveMQAuth(ctx context.Context, info *common.HostIn
success, err := p.authenticateSTOMP(conn, cred.Username, cred.Password, config)
if success {
state.IncrementTCPSuccessPacketCount()
resultChan <- &AuthResult{
Success: true,
Conn: &activeMQConnWrapper{conn},
@@ -101,7 +99,6 @@ func (p *ActiveMQPlugin) doActiveMQAuth(ctx context.Context, info *common.HostIn
}
_ = conn.Close()
state.IncrementTCPFailedPacketCount()
resultChan <- &AuthResult{
Success: false,
ErrorType: classifyActiveMQErrorType(err),
@@ -113,7 +110,6 @@ func (p *ActiveMQPlugin) doActiveMQAuth(ctx context.Context, info *common.HostIn
case result := <-resultChan:
return result
case <-ctx.Done():
// context 被取消,启动清理协程等待并关闭可能创建的连接
go func() {
result := <-resultChan
if result != nil && result.Conn != nil {
@@ -201,13 +197,12 @@ func (p *ActiveMQPlugin) authenticateSTOMP(conn net.Conn, username, password str
}
// identifyService ActiveMQ服务识别
func (p *ActiveMQPlugin) identifyService(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult {
func (p *ActiveMQPlugin) identifyService(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult {
target := info.Target()
timeout := config.Timeout
timeout := session.Config.Timeout
conn, err := common.WrapperTcpWithTimeout("tcp", target, timeout)
conn, err := session.DialTCP(ctx, "tcp", target, timeout)
if err != nil {
state.IncrementTCPFailedPacketCount()
return &ScanResult{
Success: false,
Service: "activemq",
@@ -220,7 +215,6 @@ func (p *ActiveMQPlugin) identifyService(ctx context.Context, info *common.HostI
_ = conn.SetWriteDeadline(time.Now().Add(timeout))
if _, writeErr := conn.Write([]byte(stompConnect)); writeErr != nil {
state.IncrementTCPFailedPacketCount()
return &ScanResult{
Success: false,
Service: "activemq",
@@ -232,7 +226,6 @@ func (p *ActiveMQPlugin) identifyService(ctx context.Context, info *common.HostI
response := make([]byte, 512)
n, err := conn.Read(response)
if err != nil {
state.IncrementTCPFailedPacketCount()
return &ScanResult{
Success: false,
Service: "activemq",
@@ -247,7 +240,6 @@ func (p *ActiveMQPlugin) identifyService(ctx context.Context, info *common.HostI
}
}
state.IncrementTCPSuccessPacketCount()
responseStr := string(response[:n])
if common.ContainsAny(responseStr, "CONNECTED", "ERROR") {
+1 -7
View File
@@ -38,7 +38,6 @@ func NewFindNetPlugin() *FindNetPlugin {
// Scan 执行FindNet扫描 - Windows网络信息收集
func (p *FindNetPlugin) Scan(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult {
config := session.Config
state := session.State
target := info.Target()
// 检查是否为RPC端口
@@ -50,10 +49,8 @@ func (p *FindNetPlugin) Scan(ctx context.Context, info *common.HostInfo, session
}
}
// WrapperTcpWithTimeout内部已包含发包限制检查
conn, err := common.WrapperTcpWithTimeout("tcp", target, config.Timeout)
conn, err := session.DialTCP(ctx, "tcp", target, config.Timeout)
if err != nil {
state.IncrementTCPFailedPacketCount()
return &ScanResult{
Success: false,
Service: "findnet",
@@ -68,7 +65,6 @@ func (p *FindNetPlugin) Scan(ctx context.Context, info *common.HostInfo, session
// 执行RPC网络发现
networkInfo, err := p.performNetworkDiscovery(conn)
if err != nil {
state.IncrementTCPFailedPacketCount()
return &ScanResult{
Success: false,
Service: "findnet",
@@ -76,8 +72,6 @@ func (p *FindNetPlugin) Scan(ctx context.Context, info *common.HostInfo, session
}
}
state.IncrementTCPSuccessPacketCount()
// 记录发现的网络信息 (一次性输出,避免被其他日志打断)
if networkInfo.Valid {
var lines []string
+16 -23
View File
@@ -25,16 +25,15 @@ func NewLDAPPlugin() *LDAPPlugin {
func (p *LDAPPlugin) Scan(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult {
config := session.Config
state := session.State
if config.DisableBrute {
return p.identifyService(ctx, info, config, state)
return p.identifyService(ctx, info, session)
}
target := info.Target()
// Hash 认证优先:检查是否配置了 Hash 和 Domain
if len(config.Credentials.HashValues) > 0 && config.Credentials.Domain != "" {
result := p.tryHashAuth(ctx, info, config, state)
result := p.tryHashAuth(ctx, info, session)
if result != nil && result.Success {
return result
}
@@ -50,7 +49,7 @@ func (p *LDAPPlugin) Scan(ctx context.Context, info *common.HostInfo, session *c
}
// 使用公共框架进行并发凭据测试
authFn := p.createAuthFunc(info, config, state)
authFn := p.createAuthFunc(info, session)
testConfig := DefaultConcurrentTestConfig(config)
result := TestCredentialsConcurrently(ctx, credentials, authFn, "ldap", testConfig)
@@ -63,24 +62,22 @@ func (p *LDAPPlugin) Scan(ctx context.Context, info *common.HostInfo, session *c
}
// createAuthFunc 创建LDAP认证函数
func (p *LDAPPlugin) createAuthFunc(info *common.HostInfo, config *common.Config, state *common.State) AuthFunc {
func (p *LDAPPlugin) createAuthFunc(info *common.HostInfo, session *common.ScanSession) AuthFunc {
return func(ctx context.Context, cred Credential) *AuthResult {
return p.doLDAPAuth(ctx, info, cred, config, state)
return p.doLDAPAuth(ctx, info, cred, session)
}
}
// doLDAPAuth 执行LDAP认证
func (p *LDAPPlugin) doLDAPAuth(ctx context.Context, info *common.HostInfo, cred Credential, config *common.Config, state *common.State) *AuthResult {
conn, err := p.connectLDAP(ctx, info, config)
func (p *LDAPPlugin) doLDAPAuth(ctx context.Context, info *common.HostInfo, cred Credential, session *common.ScanSession) *AuthResult {
conn, err := p.connectLDAP(ctx, info, session)
if err != nil {
state.IncrementTCPFailedPacketCount()
return &AuthResult{
Success: false,
ErrorType: classifyLDAPErrorType(err),
Error: err,
}
}
state.IncrementTCPSuccessPacketCount()
// 尝试多种DN格式进行绑定测试
dnFormats := []string{
@@ -119,7 +116,8 @@ func (w *ldapConnWrapper) Close() error {
}
// tryHashAuth 尝试 NTLM Hash 认证
func (p *LDAPPlugin) tryHashAuth(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult {
func (p *LDAPPlugin) tryHashAuth(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult {
config := session.Config
target := info.Target()
domain := config.Credentials.Domain
users := config.Credentials.Userdict["ldap"]
@@ -141,7 +139,7 @@ func (p *LDAPPlugin) tryHashAuth(ctx context.Context, info *common.HostInfo, con
default:
}
result := p.doNTLMHashAuth(ctx, info, domain, user, hash, config, state)
result := p.doNTLMHashAuth(ctx, info, domain, user, hash, session)
if result.Success {
// 截断 hash 用于显示
displayHash := hash
@@ -164,17 +162,15 @@ func (p *LDAPPlugin) tryHashAuth(ctx context.Context, info *common.HostInfo, con
}
// doNTLMHashAuth 执行单次 NTLM Hash 认证
func (p *LDAPPlugin) doNTLMHashAuth(ctx context.Context, info *common.HostInfo, domain, username, hash string, config *common.Config, state *common.State) *AuthResult {
conn, err := p.connectLDAP(ctx, info, config)
func (p *LDAPPlugin) doNTLMHashAuth(ctx context.Context, info *common.HostInfo, domain, username, hash string, session *common.ScanSession) *AuthResult {
conn, err := p.connectLDAP(ctx, info, session)
if err != nil {
state.IncrementTCPFailedPacketCount()
return &AuthResult{
Success: false,
ErrorType: classifyLDAPErrorType(err),
Error: err,
}
}
state.IncrementTCPSuccessPacketCount()
if err := conn.NTLMBindWithHash(domain, username, hash); err == nil {
return &AuthResult{
@@ -194,7 +190,7 @@ func (p *LDAPPlugin) doNTLMHashAuth(ctx context.Context, info *common.HostInfo,
}
// connectLDAP 连接LDAP服务器
func (p *LDAPPlugin) connectLDAP(ctx context.Context, info *common.HostInfo, config *common.Config) (*ldaplib.Conn, error) {
func (p *LDAPPlugin) connectLDAP(ctx context.Context, info *common.HostInfo, session *common.ScanSession) (*ldaplib.Conn, error) {
target := info.Target()
type result struct {
@@ -204,7 +200,7 @@ func (p *LDAPPlugin) connectLDAP(ctx context.Context, info *common.HostInfo, con
resultChan := make(chan result, 1)
go func() {
tcpConn, err := common.WrapperTcpWithTimeout("tcp", target, config.Timeout)
tcpConn, err := session.DialTCP(ctx, "tcp", target, session.Config.Timeout)
if err != nil {
resultChan <- result{nil, err}
return
@@ -225,7 +221,6 @@ func (p *LDAPPlugin) connectLDAP(ctx context.Context, info *common.HostInfo, con
case res := <-resultChan:
return res.conn, res.err
case <-ctx.Done():
// context 被取消,启动清理协程等待并关闭可能创建的连接
go func() {
res := <-resultChan
if res.conn != nil {
@@ -259,19 +254,17 @@ func classifyLDAPErrorType(err error) ErrorType {
return ClassifyError(err, ldapAuthErrors, ldapNetworkErrors)
}
func (p *LDAPPlugin) identifyService(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult {
func (p *LDAPPlugin) identifyService(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult {
target := info.Target()
conn, err := p.connectLDAP(ctx, info, config)
conn, err := p.connectLDAP(ctx, info, session)
if err != nil {
state.IncrementTCPFailedPacketCount()
return &ScanResult{
Success: false,
Service: "ldap",
Error: err,
}
}
state.IncrementTCPSuccessPacketCount()
defer func() { _ = conn.Close() }()
banner := "LDAP"
+12 -15
View File
@@ -26,15 +26,14 @@ func NewMemcachedPlugin() *MemcachedPlugin {
func (p *MemcachedPlugin) Scan(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult {
config := session.Config
state := session.State
target := info.Target()
if config.DisableBrute {
return p.identifyService(ctx, info, config, state)
return p.identifyService(ctx, info, session)
}
// 检测未授权访问
if result := p.testUnauthorizedAccess(ctx, info, config, state); result != nil && result.Success {
if result := p.testUnauthorizedAccess(ctx, info, session); result != nil && result.Success {
common.LogVuln(i18n.Tr("memcached_unauth", target))
return result
}
@@ -48,14 +47,14 @@ func (p *MemcachedPlugin) Scan(ctx context.Context, info *common.HostInfo, sessi
}
// testUnauthorizedAccess 测试Memcached未授权访问
func (p *MemcachedPlugin) testUnauthorizedAccess(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult {
conn := p.connectToMemcached(ctx, info, config, state)
func (p *MemcachedPlugin) testUnauthorizedAccess(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult {
conn := p.connectToMemcached(ctx, info, session)
if conn == nil {
return nil
}
defer func() { _ = conn.Close() }()
if p.testBasicCommand(conn, config) {
if p.testBasicCommand(conn, session.Config) {
return &ScanResult{
Type: plugins.ResultTypeVuln,
Success: true,
@@ -67,20 +66,19 @@ func (p *MemcachedPlugin) testUnauthorizedAccess(ctx context.Context, info *comm
return nil
}
func (p *MemcachedPlugin) connectToMemcached(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) net.Conn {
func (p *MemcachedPlugin) connectToMemcached(ctx context.Context, info *common.HostInfo, session *common.ScanSession) net.Conn {
target := info.Target()
timeout := session.Config.Timeout
connChan := make(chan net.Conn, 1)
go func() {
conn, err := common.WrapperTcpWithTimeout("tcp", target, config.Timeout)
conn, err := session.DialTCP(ctx, "tcp", target, timeout)
if err != nil {
state.IncrementTCPFailedPacketCount()
connChan <- nil
return
}
state.IncrementTCPSuccessPacketCount()
_ = conn.SetDeadline(time.Now().Add(config.Timeout))
_ = conn.SetDeadline(time.Now().Add(timeout))
connChan <- conn
}()
@@ -88,7 +86,6 @@ func (p *MemcachedPlugin) connectToMemcached(ctx context.Context, info *common.H
case conn := <-connChan:
return conn
case <-ctx.Done():
// context 被取消,启动清理协程等待并关闭可能创建的连接
go func() {
conn := <-connChan
if conn != nil {
@@ -116,10 +113,10 @@ func (p *MemcachedPlugin) testBasicCommand(conn net.Conn, config *common.Config)
return common.ContainsAny(responseStr, "VERSION", "memcached")
}
func (p *MemcachedPlugin) identifyService(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult {
func (p *MemcachedPlugin) identifyService(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult {
target := info.Target()
conn := p.connectToMemcached(ctx, info, config, state)
conn := p.connectToMemcached(ctx, info, session)
if conn == nil {
return &ScanResult{
Success: false,
@@ -129,7 +126,7 @@ func (p *MemcachedPlugin) identifyService(ctx context.Context, info *common.Host
}
defer func() { _ = conn.Close() }()
if p.testBasicCommand(conn, config) {
if p.testBasicCommand(conn, session.Config) {
banner := "Memcached"
common.LogSuccess(i18n.Tr("memcached_service", target, banner))
return &ScanResult{
+10 -10
View File
@@ -34,11 +34,11 @@ func (p *MongoDBPlugin) Scan(ctx context.Context, info *common.HostInfo, session
target := info.Target()
if config.DisableBrute {
return p.identifyService(ctx, info, config)
return p.identifyService(ctx, info, session)
}
// 首先检测未授权访问
isUnauth, err := p.mongodbUnauth(ctx, info, config)
isUnauth, err := p.mongodbUnauth(ctx, info, session)
if err != nil {
return &ScanResult{
Success: false,
@@ -184,10 +184,10 @@ func classifyMongoDBErrorType(err error) ErrorType {
return ClassifyError(err, mongoAuthErrors, mongoNetworkErrors)
}
func (p *MongoDBPlugin) identifyService(ctx context.Context, info *common.HostInfo, config *common.Config) *ScanResult {
func (p *MongoDBPlugin) identifyService(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult {
target := info.Target()
isUnauth, err := p.mongodbUnauth(ctx, info, config)
isUnauth, err := p.mongodbUnauth(ctx, info, session)
if err != nil {
return &ScanResult{
Success: false,
@@ -216,14 +216,14 @@ func (p *MongoDBPlugin) identifyService(ctx context.Context, info *common.HostIn
}
// mongodbUnauth 检测MongoDB未授权访问
func (p *MongoDBPlugin) mongodbUnauth(ctx context.Context, info *common.HostInfo, config *common.Config) (bool, error) {
func (p *MongoDBPlugin) mongodbUnauth(ctx context.Context, info *common.HostInfo, session *common.ScanSession) (bool, error) {
msgPacket := p.createOpMsgPacket()
queryPacket := p.createOpQueryPacket()
realhost := fmt.Sprintf("%s:%d", info.Host, info.Port)
reply, err := p.checkMongoAuth(ctx, realhost, msgPacket, config)
reply, err := p.checkMongoAuth(ctx, realhost, msgPacket, session)
if err != nil {
reply, err = p.checkMongoAuth(ctx, realhost, queryPacket, config)
reply, err = p.checkMongoAuth(ctx, realhost, queryPacket, session)
if err != nil {
return false, err
}
@@ -241,8 +241,8 @@ func (p *MongoDBPlugin) mongodbUnauth(ctx context.Context, info *common.HostInfo
}
// checkMongoAuth 检查MongoDB认证状态
func (p *MongoDBPlugin) checkMongoAuth(ctx context.Context, address string, packet []byte, config *common.Config) (string, error) {
conn, err := common.WrapperTcpWithTimeout("tcp", address, config.Timeout)
func (p *MongoDBPlugin) checkMongoAuth(ctx context.Context, address string, packet []byte, session *common.ScanSession) (string, error) {
conn, err := session.DialTCP(ctx, "tcp", address, session.Config.Timeout)
if err != nil {
return "", fmt.Errorf("连接失败: %w", err)
}
@@ -254,7 +254,7 @@ func (p *MongoDBPlugin) checkMongoAuth(ctx context.Context, address string, pack
default:
}
if deadlineErr := conn.SetDeadline(time.Now().Add(config.Timeout)); deadlineErr != nil {
if deadlineErr := conn.SetDeadline(time.Now().Add(session.Config.Timeout)); deadlineErr != nil {
return "", fmt.Errorf("设置超时失败: %w", deadlineErr)
}
+14 -25
View File
@@ -36,7 +36,6 @@ func NewMS17010Plugin() *MS17010Plugin {
// Scan 执行MS17-010扫描
func (p *MS17010Plugin) Scan(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult {
config := session.Config
state := session.State
// 如果禁用暴力破解,也禁用漏洞检测
if config.DisableBrute {
return &ScanResult{
@@ -58,7 +57,7 @@ func (p *MS17010Plugin) Scan(ctx context.Context, info *common.HostInfo, session
}
// 执行MS17010漏洞检测
vulnerable, osVersion, err := p.checkMS17010Vulnerability(info.Host, config, state)
vulnerable, osVersion, err := p.checkMS17010Vulnerability(ctx, info.Host, session)
if err != nil {
return &ScanResult{
Success: false,
@@ -90,7 +89,8 @@ func (p *MS17010Plugin) Scan(ctx context.Context, info *common.HostInfo, session
}
// Exploit 执行MS17-010漏洞利用
func (p *MS17010Plugin) Exploit(ctx context.Context, info *common.HostInfo, creds Credential, config *common.Config) *ExploitResult {
func (p *MS17010Plugin) Exploit(ctx context.Context, info *common.HostInfo, creds Credential, session *common.ScanSession) *ExploitResult {
config := session.Config
target := info.Target()
common.LogSuccess(i18n.Tr("ms17010_start", target))
@@ -98,7 +98,7 @@ func (p *MS17010Plugin) Exploit(ctx context.Context, info *common.HostInfo, cred
output.WriteString(fmt.Sprintf("=== MS17-010漏洞利用结果 - %s ===\n", target))
// 首先确认漏洞存在
vulnerable, osVersion, err := p.checkMS17010Vulnerability(info.Host, config, nil)
vulnerable, osVersion, err := p.checkMS17010Vulnerability(ctx, info.Host, session)
if err != nil {
output.WriteString(fmt.Sprintf("\n[漏洞检测失败] %v\n", err))
return &ExploitResult{
@@ -123,7 +123,7 @@ func (p *MS17010Plugin) Exploit(ctx context.Context, info *common.HostInfo, cred
}
// 检测DOUBLEPULSAR后门
hasBackdoor := p.checkDoublePulsar(info.Host, config)
hasBackdoor := p.checkDoublePulsar(ctx, info.Host, session)
if hasBackdoor {
output.WriteString("\n[后门检测] ⚠️ 发现DOUBLEPULSAR后门\n")
} else {
@@ -136,7 +136,7 @@ func (p *MS17010Plugin) Exploit(ctx context.Context, info *common.HostInfo, cred
output.WriteString("[利用状态] 开始执行EternalBlue攻击...\n")
// 执行实际的MS17010利用
err = p.executeMS17010Exploit(info, config)
err = p.executeMS17010Exploit(info, session)
if err != nil {
output.WriteString(fmt.Sprintf("[利用结果] ❌ 利用失败: %v\n", err))
return &ExploitResult{
@@ -284,18 +284,14 @@ func init() {
}
// checkMS17010Vulnerability 检测MS17-010漏洞 (从原始MS17010.go复制和适配)
func (p *MS17010Plugin) checkMS17010Vulnerability(ip string, config *common.Config, state *common.State) (bool, string, error) {
// 使用统一TCP包装器,支持代理和限流
conn, err := common.WrapperTcpWithTimeout("tcp", ip+":445", config.Timeout)
func (p *MS17010Plugin) checkMS17010Vulnerability(ctx context.Context, ip string, session *common.ScanSession) (bool, string, error) {
conn, err := session.DialTCP(ctx, "tcp", ip+":445", session.Config.Timeout)
if err != nil {
if state != nil {
state.IncrementTCPFailedPacketCount()
}
return false, "", fmt.Errorf("连接错误: %w", err)
}
defer func() { _ = conn.Close() }()
if err = conn.SetDeadline(time.Now().Add(config.Timeout)); err != nil {
if err = conn.SetDeadline(time.Now().Add(session.Config.Timeout)); err != nil {
return false, "", fmt.Errorf("设置超时错误: %w", err)
}
@@ -383,29 +379,22 @@ func (p *MS17010Plugin) checkMS17010Vulnerability(ip string, config *common.Conf
// 漏洞检测 - 关键检查点
if reply[9] == 0x05 && reply[10] == 0x02 && reply[11] == 0x00 && reply[12] == 0xc0 {
if state != nil {
state.IncrementTCPSuccessPacketCount()
}
return true, osVersion, nil
}
if state != nil {
state.IncrementTCPSuccessPacketCount()
}
return false, osVersion, nil
}
// checkDoublePulsar 检测DOUBLEPULSAR后门
func (p *MS17010Plugin) checkDoublePulsar(ip string, config *common.Config) bool {
// 使用统一TCP包装器,支持代理和限流
conn, err := common.WrapperTcpWithTimeout("tcp", ip+":445", config.Timeout)
func (p *MS17010Plugin) checkDoublePulsar(ctx context.Context, ip string, session *common.ScanSession) bool {
conn, err := session.DialTCP(ctx, "tcp", ip+":445", session.Config.Timeout)
if err != nil {
return false
}
defer func() { _ = conn.Close() }()
// 简化的后门检测逻辑
vulnerable, _, err := p.checkMS17010Vulnerability(ip, config, nil)
vulnerable, _, err := p.checkMS17010Vulnerability(ctx, ip, session)
if err != nil || !vulnerable {
return false
}
@@ -416,8 +405,8 @@ func (p *MS17010Plugin) checkDoublePulsar(ip string, config *common.Config) bool
}
// executeMS17010Exploit 执行MS17010漏洞利用 (简化版,保留接口)
func (p *MS17010Plugin) executeMS17010Exploit(info *common.HostInfo, config *common.Config) error {
// address := info.Host + ":445" // 暂时不使用,为了保持原始复杂度
func (p *MS17010Plugin) executeMS17010Exploit(info *common.HostInfo, session *common.ScanSession) error {
config := session.Config
var sc string
// 根据不同类型选择shellcode (从MS17010-Exp.go复制)
+4 -4
View File
@@ -40,7 +40,7 @@ func (p *MySQLPlugin) Scan(ctx context.Context, info *common.HostInfo, session *
config := session.Config
state := session.State
if config.DisableBrute {
return p.identifyService(info, config)
return p.identifyService(ctx, info, session)
}
credentials := GenerateCredentials("mysql", config)
@@ -139,10 +139,10 @@ func classifyMySQLErrorType(err error) ErrorType {
return ClassifyError(err, mysqlAuthErrors, mysqlNetworkErrors)
}
func (p *MySQLPlugin) identifyService(info *common.HostInfo, config *common.Config) *ScanResult {
func (p *MySQLPlugin) identifyService(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult {
target := info.Target()
conn, err := common.SafeTCPDial(target, config.Timeout)
conn, err := session.DialTCP(ctx, "tcp", target, session.Config.Timeout)
if err != nil {
return &ScanResult{
Success: false,
@@ -152,7 +152,7 @@ func (p *MySQLPlugin) identifyService(info *common.HostInfo, config *common.Conf
}
defer func() { _ = conn.Close() }()
if banner := p.readMySQLBanner(conn, config); banner != "" {
if banner := p.readMySQLBanner(conn, session.Config); banner != "" {
common.LogSuccess(i18n.Tr("mysql_service", target, banner))
return &ScanResult{
Type: plugins.ResultTypeService,
+4 -4
View File
@@ -51,7 +51,7 @@ func (p *NetBIOSPlugin) Scan(ctx context.Context, info *common.HostInfo, session
netbiosInfo, err = p.queryNetBIOSNames(info.Host, config, state)
} else {
// TCP端口139 - NetBIOS会话服务
netbiosInfo, err = p.queryNetBIOSSession(info.Host, config)
netbiosInfo, err = p.queryNetBIOSSession(ctx, info.Host, session)
}
if err != nil {
@@ -186,16 +186,16 @@ func (p *NetBIOSPlugin) queryNetBIOSNames(host string, config *common.Config, st
}
// queryNetBIOSSession 查询NetBIOS会话服务(TCP 139)
func (p *NetBIOSPlugin) queryNetBIOSSession(host string, config *common.Config) (*NetBIOSInfo, error) {
func (p *NetBIOSPlugin) queryNetBIOSSession(ctx context.Context, host string, session *common.ScanSession) (*NetBIOSInfo, error) {
target := fmt.Sprintf("%s:139", host)
conn, err := common.WrapperTcpWithTimeout("tcp", target, config.Timeout)
conn, err := session.DialTCP(ctx, "tcp", target, session.Config.Timeout)
if err != nil {
return nil, fmt.Errorf("连接NetBIOS会话服务失败: %w", err)
}
defer func() { _ = conn.Close() }()
_ = conn.SetDeadline(time.Now().Add(config.Timeout))
_ = conn.SetDeadline(time.Now().Add(session.Config.Timeout))
// 发送SMB协商数据包
smbNegotiate1 := []byte{
+3 -3
View File
@@ -30,7 +30,7 @@ func (p *OraclePlugin) Scan(ctx context.Context, info *common.HostInfo, session
target := info.Target()
if config.DisableBrute {
return p.identifyService(ctx, info, config, state)
return p.identifyService(ctx, info, session)
}
// 先测试未授权访问
@@ -180,10 +180,10 @@ func (p *OraclePlugin) testUnauthorizedAccess(ctx context.Context, info *common.
return nil
}
func (p *OraclePlugin) identifyService(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult {
func (p *OraclePlugin) identifyService(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult {
target := info.Target()
conn, err := common.WrapperTcpWithTimeout("tcp", target, config.Timeout)
conn, err := session.DialTCP(ctx, "tcp", target, session.Config.Timeout)
if err != nil {
return &ScanResult{
Success: false,
+10 -8
View File
@@ -32,7 +32,7 @@ func (p *RabbitMQPlugin) Scan(ctx context.Context, info *common.HostInfo, sessio
target := info.Target()
if config.DisableBrute {
return p.identifyService(ctx, info, config, state)
return p.identifyService(ctx, info, session)
}
// 先检测未授权访问
@@ -211,16 +211,16 @@ func (p *RabbitMQPlugin) testUnauthorizedAccess(ctx context.Context, info *commo
}
// testAMQPProtocol 检测AMQP协议
func (p *RabbitMQPlugin) testAMQPProtocol(ctx context.Context, info *common.HostInfo, config *common.Config) *ScanResult {
func (p *RabbitMQPlugin) testAMQPProtocol(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult {
target := info.Target()
conn, err := common.WrapperTcpWithTimeout("tcp", target, config.Timeout)
conn, err := session.DialTCP(ctx, "tcp", target, session.Config.Timeout)
if err != nil {
return nil
}
defer func() { _ = conn.Close() }()
_ = conn.SetDeadline(time.Now().Add(config.Timeout))
_ = conn.SetDeadline(time.Now().Add(session.Config.Timeout))
// 发送AMQP协议头
amqpHeader := []byte{0x41, 0x4d, 0x51, 0x50, 0x00, 0x00, 0x09, 0x01}
@@ -249,19 +249,21 @@ func (p *RabbitMQPlugin) testAMQPProtocol(ctx context.Context, info *common.Host
return nil
}
func (p *RabbitMQPlugin) identifyService(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult {
func (p *RabbitMQPlugin) identifyService(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult {
// 对于AMQP端口,检测AMQP协议
if info.Port == 5672 || info.Port == 5671 {
if result := p.testAMQPProtocol(ctx, info, config); result != nil && result.Success {
if result := p.testAMQPProtocol(ctx, info, session); result != nil && result.Success {
return result
}
}
// 检测HTTP管理界面
return p.testManagementInterface(ctx, info, config, state)
return p.testManagementInterface(ctx, info, session)
}
func (p *RabbitMQPlugin) testManagementInterface(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult {
func (p *RabbitMQPlugin) testManagementInterface(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult {
config := session.Config
state := session.State
target := info.Target()
baseURL := fmt.Sprintf("http://%s:%d", info.Host, info.Port)
+20 -26
View File
@@ -33,21 +33,20 @@ func NewRedisPlugin() *RedisPlugin {
// Scan 执行Redis扫描
func (p *RedisPlugin) Scan(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult {
config := session.Config
state := session.State
target := info.Target()
// 如果禁用暴力破解,只做服务识别
if config.DisableBrute {
return p.identifyService(ctx, info, config, state)
return p.identifyService(ctx, info, session)
}
// 首先检查未授权访问
if result := p.testUnauthorizedAccess(ctx, info, config, state); result != nil && result.Success {
if result := p.testUnauthorizedAccess(ctx, info, session); result != nil && result.Success {
common.LogVuln(i18n.Tr("redis_unauth_success", target)) //nolint:govet
// 如果需要利用,重新建立连接执行
if p.shouldExploit(config) {
p.exploitWithPassword(ctx, info, "", config)
p.exploitWithPassword(ctx, info, "", session)
}
return result
}
@@ -56,7 +55,7 @@ func (p *RedisPlugin) Scan(ctx context.Context, info *common.HostInfo, session *
credentials := GenerateCredentials("redis", config)
// 使用公共框架进行并发凭据测试
authFn := p.createAuthFunc(info, config, state)
authFn := p.createAuthFunc(info, session)
testConfig := DefaultConcurrentTestConfig(config)
testConfig.Concurrency = 20 // Redis 默认并发度更高
@@ -68,7 +67,7 @@ func (p *RedisPlugin) Scan(ctx context.Context, info *common.HostInfo, session *
// 如果需要利用,重新建立连接执行
if p.shouldExploit(config) {
p.exploitWithPassword(ctx, info, result.Password, config)
p.exploitWithPassword(ctx, info, result.Password, session)
}
}
@@ -76,21 +75,20 @@ func (p *RedisPlugin) Scan(ctx context.Context, info *common.HostInfo, session *
}
// createAuthFunc 创建Redis认证函数
func (p *RedisPlugin) createAuthFunc(info *common.HostInfo, config *common.Config, state *common.State) AuthFunc {
func (p *RedisPlugin) createAuthFunc(info *common.HostInfo, session *common.ScanSession) AuthFunc {
return func(ctx context.Context, cred Credential) *AuthResult {
return p.doRedisAuth(ctx, info, cred, config, state)
return p.doRedisAuth(ctx, info, cred, session)
}
}
// doRedisAuth 执行Redis认证
func (p *RedisPlugin) doRedisAuth(ctx context.Context, info *common.HostInfo, cred Credential, config *common.Config, state *common.State) *AuthResult {
func (p *RedisPlugin) doRedisAuth(ctx context.Context, info *common.HostInfo, cred Credential, session *common.ScanSession) *AuthResult {
target := info.Target()
timeout := config.Timeout
timeout := session.Config.Timeout
// 建立TCP连接
conn, err := common.WrapperTcpWithTimeout("tcp", target, timeout)
conn, err := session.DialTCP(ctx, "tcp", target, timeout)
if err != nil {
state.IncrementTCPFailedPacketCount()
return &AuthResult{
Success: false,
ErrorType: classifyRedisErrorType(err),
@@ -169,7 +167,6 @@ func (p *RedisPlugin) doRedisAuth(ctx context.Context, info *common.HostInfo, cr
responseStr := string(response[:n])
if !strings.Contains(responseStr, "PONG") {
_ = conn.Close()
state.IncrementTCPFailedPacketCount()
return &AuthResult{
Success: false,
ErrorType: ErrorTypeUnknown,
@@ -177,7 +174,6 @@ func (p *RedisPlugin) doRedisAuth(ctx context.Context, info *common.HostInfo, cr
}
}
state.IncrementTCPSuccessPacketCount()
return &AuthResult{
Success: true,
Conn: conn,
@@ -204,10 +200,10 @@ func classifyRedisErrorType(err error) ErrorType {
}
// testUnauthorizedAccess 测试未授权访问
func (p *RedisPlugin) testUnauthorizedAccess(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult {
func (p *RedisPlugin) testUnauthorizedAccess(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult {
emptyCred := Credential{Username: "", Password: ""}
result := p.doRedisAuth(ctx, info, emptyCred, config, state)
result := p.doRedisAuth(ctx, info, emptyCred, session)
if result.Success {
if result.Conn != nil {
_ = result.Conn.Close()
@@ -224,10 +220,10 @@ func (p *RedisPlugin) testUnauthorizedAccess(ctx context.Context, info *common.H
}
// exploitWithPassword 使用指定密码建立连接并执行利用
func (p *RedisPlugin) exploitWithPassword(ctx context.Context, info *common.HostInfo, password string, config *common.Config) {
func (p *RedisPlugin) exploitWithPassword(ctx context.Context, info *common.HostInfo, password string, session *common.ScanSession) {
target := info.Target()
conn, err := common.WrapperTcpWithTimeout("tcp", target, config.Timeout)
conn, err := session.DialTCP(ctx, "tcp", target, session.Config.Timeout)
if err != nil {
common.LogError(i18n.Tr("redis_reconnect_failed", err))
return
@@ -237,28 +233,27 @@ func (p *RedisPlugin) exploitWithPassword(ctx context.Context, info *common.Host
// 如果有密码,先认证
if password != "" {
authCmd := fmt.Sprintf("AUTH %s\r\n", password)
_ = conn.SetWriteDeadline(time.Now().Add(config.Timeout))
_ = conn.SetWriteDeadline(time.Now().Add(session.Config.Timeout))
if _, writeErr := conn.Write([]byte(authCmd)); writeErr != nil {
return
}
_ = conn.SetReadDeadline(time.Now().Add(config.Timeout))
_ = conn.SetReadDeadline(time.Now().Add(session.Config.Timeout))
response := make([]byte, 512)
if _, readErr := conn.Read(response); readErr != nil {
return
}
}
p.exploit(ctx, info, conn, password, config)
p.exploit(ctx, info, conn, password, session.Config)
}
// identifyService 服务识别
func (p *RedisPlugin) identifyService(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult {
func (p *RedisPlugin) identifyService(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult {
target := info.Target()
timeout := config.Timeout
timeout := session.Config.Timeout
conn, err := common.WrapperTcpWithTimeout("tcp", target, timeout)
conn, err := session.DialTCP(ctx, "tcp", target, timeout)
if err != nil {
state.IncrementTCPFailedPacketCount()
return &ScanResult{
Success: false,
Service: "redis",
@@ -302,7 +297,6 @@ func (p *RedisPlugin) identifyService(ctx context.Context, info *common.HostInfo
banner = "Redis服务"
}
state.IncrementTCPSuccessPacketCount()
common.LogSuccess(i18n.Tr("redis_service_identified", target, banner)) //nolint:govet
return &ScanResult{
+17 -25
View File
@@ -30,17 +30,16 @@ func NewRsyncPlugin() *RsyncPlugin {
func (p *RsyncPlugin) Scan(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult {
config := session.Config
state := session.State
target := info.Target()
if config.DisableBrute {
return p.identifyService(ctx, info, config, state)
return p.identifyService(ctx, info, session)
}
var findings []string
// 检测未授权访问
if result := p.testUnauthorizedAccess(ctx, info, config, state); result != nil && result.Success {
if result := p.testUnauthorizedAccess(ctx, info, session); result != nil && result.Success {
common.LogSuccess(i18n.Tr("rsync_service", target, result.Banner))
findings = append(findings, result.Banner)
}
@@ -70,7 +69,7 @@ func (p *RsyncPlugin) Scan(ctx context.Context, info *common.HostInfo, session *
}
// 使用公共框架进行并发凭据测试
authFn := p.createAuthFunc(info, config, state)
authFn := p.createAuthFunc(info, session)
testConfig := DefaultConcurrentTestConfig(config)
result := TestCredentialsConcurrently(ctx, creds, authFn, "rsync", testConfig)
@@ -97,16 +96,16 @@ func (p *RsyncPlugin) Scan(ctx context.Context, info *common.HostInfo, session *
}
// createAuthFunc 创建Rsync认证函数
func (p *RsyncPlugin) createAuthFunc(info *common.HostInfo, config *common.Config, state *common.State) AuthFunc {
func (p *RsyncPlugin) createAuthFunc(info *common.HostInfo, session *common.ScanSession) AuthFunc {
return func(ctx context.Context, cred Credential) *AuthResult {
return p.doRsyncAuth(ctx, info, cred, config, state)
return p.doRsyncAuth(ctx, info, cred, session)
}
}
// doRsyncAuth 执行Rsync认证
func (p *RsyncPlugin) doRsyncAuth(ctx context.Context, info *common.HostInfo, cred Credential, config *common.Config, state *common.State) *AuthResult {
func (p *RsyncPlugin) doRsyncAuth(ctx context.Context, info *common.HostInfo, cred Credential, session *common.ScanSession) *AuthResult {
// 先获取可用模块列表
conn := p.connectToRsync(ctx, info, config, state)
conn := p.connectToRsync(ctx, info, session)
if conn == nil {
return &AuthResult{
Success: false,
@@ -114,7 +113,7 @@ func (p *RsyncPlugin) doRsyncAuth(ctx context.Context, info *common.HostInfo, cr
Error: fmt.Errorf("无法连接到Rsync服务"),
}
}
modules := p.getModules(conn, config)
modules := p.getModules(conn, session.Config)
_ = conn.Close()
if len(modules) == 0 {
@@ -142,7 +141,6 @@ func (p *RsyncPlugin) doRsyncAuth(ctx context.Context, info *common.HostInfo, cr
)
if err != nil {
state.IncrementTCPFailedPacketCount()
errMsg := err.Error()
if common.ContainsAny(errMsg, "auth", "password") {
return &AuthResult{
@@ -158,7 +156,6 @@ func (p *RsyncPlugin) doRsyncAuth(ctx context.Context, info *common.HostInfo, cr
}
}
state.IncrementTCPSuccessPacketCount()
return &AuthResult{
Success: true,
Conn: &rsyncConnWrapper{},
@@ -208,14 +205,14 @@ func classifyRsyncErrorType(err error) ErrorType {
}
// testUnauthorizedAccess 测试未授权访问
func (p *RsyncPlugin) testUnauthorizedAccess(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult {
conn := p.connectToRsync(ctx, info, config, state)
func (p *RsyncPlugin) testUnauthorizedAccess(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult {
conn := p.connectToRsync(ctx, info, session)
if conn == nil {
return nil
}
defer func() { _ = conn.Close() }()
modules := p.getModules(conn, config)
modules := p.getModules(conn, session.Config)
if len(modules) > 0 {
banner := fmt.Sprintf("未授权访问 - 可用模块: %s", strings.Join(modules, ", "))
@@ -231,22 +228,18 @@ func (p *RsyncPlugin) testUnauthorizedAccess(ctx context.Context, info *common.H
}
// connectToRsync 连接到Rsync服务
func (p *RsyncPlugin) connectToRsync(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) net.Conn {
func (p *RsyncPlugin) connectToRsync(ctx context.Context, info *common.HostInfo, session *common.ScanSession) net.Conn {
target := info.Target()
timeout := session.Config.Timeout
connChan := make(chan net.Conn, 1)
go func() {
timeout := config.Timeout
conn, err := common.WrapperTcpWithTimeout("tcp", target, timeout)
conn, err := session.DialTCP(ctx, "tcp", target, timeout)
if err != nil {
state.IncrementTCPFailedPacketCount()
connChan <- nil
return
}
state.IncrementTCPSuccessPacketCount()
_ = conn.SetDeadline(time.Now().Add(timeout))
connChan <- conn
}()
@@ -255,7 +248,6 @@ func (p *RsyncPlugin) connectToRsync(ctx context.Context, info *common.HostInfo,
case conn := <-connChan:
return conn
case <-ctx.Done():
// context 被取消,启动清理协程等待并关闭可能创建的连接
go func() {
conn := <-connChan
if conn != nil {
@@ -328,10 +320,10 @@ func (p *RsyncPlugin) getModules(conn net.Conn, config *common.Config) []string
}
// identifyService Rsync服务识别
func (p *RsyncPlugin) identifyService(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult {
func (p *RsyncPlugin) identifyService(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult {
target := info.Target()
conn := p.connectToRsync(ctx, info, config, state)
conn := p.connectToRsync(ctx, info, session)
if conn == nil {
return &ScanResult{
Success: false,
@@ -341,7 +333,7 @@ func (p *RsyncPlugin) identifyService(ctx context.Context, info *common.HostInfo
}
defer func() { _ = conn.Close() }()
timeout := config.Timeout
timeout := session.Config.Timeout
_ = conn.SetWriteDeadline(time.Now().Add(timeout))
if _, err := conn.Write([]byte("\n")); err != nil {
+6 -12
View File
@@ -39,23 +39,21 @@ func (p *SmbPlugin) Scan(ctx context.Context, info *common.HostInfo, session *co
}
// 1. 协议探测和信息收集
smbTarget, err := probeTarget(info.Host, info.Port, config.Timeout)
smbTarget, err := probeTarget(ctx, info.Host, info.Port, config.Timeout, session)
if err != nil {
state.IncrementTCPFailedPacketCount()
return &ScanResult{
Success: false,
Service: "smb",
Error: fmt.Errorf("SMB协议探测失败: %w", err),
}
}
state.IncrementTCPSuccessPacketCount()
// 输出信息收集结果
p.logSMBInfo(target, smbTarget)
// 2. 漏洞检测 (仅SMBv2+且端口445)
if smbTarget.Protocol == SMBProtocol2 && info.Port == 445 {
if checkSMBGhost(info.Host, config.Timeout) {
if checkSMBGhost(ctx, info.Host, config.Timeout, session) {
smbTarget.Vulnerable = &SMBVuln{CVE20200796: true}
common.LogVuln(i18n.Tr("smbghost_vuln", target))
}
@@ -92,7 +90,7 @@ func (p *SmbPlugin) Scan(ctx context.Context, info *common.HostInfo, session *co
creds[i] = Credential{Username: c.Username, Password: c.Password}
}
authFn := p.createAuthFunc(info, auth, config, state)
authFn := p.createAuthFunc(info, auth, session)
testConfig := DefaultConcurrentTestConfig(config)
result := TestCredentialsConcurrently(ctx, creds, authFn, "smb", testConfig)
@@ -119,14 +117,10 @@ func (p *SmbPlugin) getAuthenticator(protocol SMBProtocol) SMBAuthenticator {
}
// createAuthFunc 创建认证函数
func (p *SmbPlugin) createAuthFunc(info *common.HostInfo, auth SMBAuthenticator, config *common.Config, state *common.State) AuthFunc {
func (p *SmbPlugin) createAuthFunc(info *common.HostInfo, auth SMBAuthenticator, session *common.ScanSession) AuthFunc {
config := session.Config
return func(ctx context.Context, cred Credential) *AuthResult {
result, _ := auth.Authenticate(ctx, info.Host, info.Port, cred, config.Credentials.Domain, config.Timeout)
if result.Success {
state.IncrementTCPSuccessPacketCount()
} else {
state.IncrementTCPFailedPacketCount()
}
result, _ := auth.Authenticate(ctx, info.Host, info.Port, cred, config.Credentials.Domain, config.Timeout, session)
return result
}
}
+11 -11
View File
@@ -201,10 +201,10 @@ var (
)
// probeTarget 探测目标SMB信息(协议版本、系统信息)
func probeTarget(host string, port int, timeout time.Duration) (*SMBTarget, error) {
func probeTarget(ctx context.Context, host string, port int, timeout time.Duration, session *common.ScanSession) (*SMBTarget, error) {
target := fmt.Sprintf("%s:%d", host, port)
conn, err := common.WrapperTcpWithTimeout("tcp", target, timeout)
conn, err := session.DialTCP(ctx, "tcp", target, timeout)
if err != nil {
return nil, fmt.Errorf("连接失败: %w", err)
}
@@ -230,7 +230,7 @@ func probeTarget(host string, port int, timeout time.Duration) (*SMBTarget, erro
}
// SMBv2路径
return probeSMBv2(target, timeout)
return probeSMBv2(ctx, target, timeout, session)
}
// probeSMBv1 处理SMBv1协议信息收集
@@ -288,8 +288,8 @@ func probeSMBv1(conn net.Conn, target string, timeout time.Duration) (*SMBTarget
}
// probeSMBv2 处理SMBv2协议信息收集
func probeSMBv2(target string, timeout time.Duration) (*SMBTarget, error) {
conn2, err := common.WrapperTcpWithTimeout("tcp", target, timeout)
func probeSMBv2(ctx context.Context, target string, timeout time.Duration, session *common.ScanSession) (*SMBTarget, error) {
conn2, err := session.DialTCP(ctx, "tcp", target, timeout)
if err != nil {
return nil, fmt.Errorf("SMBv2连接失败: %w", err)
}
@@ -354,10 +354,10 @@ func probeSMBv2(target string, timeout time.Duration) (*SMBTarget, error) {
}
// checkSMBGhost 检测CVE-2020-0796漏洞
func checkSMBGhost(host string, timeout time.Duration) bool {
func checkSMBGhost(ctx context.Context, host string, timeout time.Duration, session *common.ScanSession) bool {
addr := fmt.Sprintf("%s:445", host)
conn, err := common.WrapperTcpWithTimeout("tcp", addr, timeout)
conn, err := session.DialTCP(ctx, "tcp", addr, timeout)
if err != nil {
return false
}
@@ -390,7 +390,7 @@ func checkSMBGhost(host string, timeout time.Duration) bool {
// SMBAuthenticator 统一认证接口
type SMBAuthenticator interface {
Authenticate(ctx context.Context, host string, port int, cred Credential, domain string, timeout time.Duration) (*AuthResult, error)
Authenticate(ctx context.Context, host string, port int, cred Credential, domain string, timeout time.Duration, session *common.ScanSession) (*AuthResult, error)
ListShares(ctx context.Context, host string, port int, cred Credential, domain string, timeout time.Duration) ([]string, error)
}
@@ -398,7 +398,7 @@ type SMBAuthenticator interface {
type SMB1Authenticator struct{}
// Authenticate 执行SMB1认证
func (a *SMB1Authenticator) Authenticate(ctx context.Context, host string, port int, cred Credential, domain string, timeout time.Duration) (*AuthResult, error) {
func (a *SMB1Authenticator) Authenticate(ctx context.Context, host string, port int, cred Credential, domain string, timeout time.Duration, session *common.ScanSession) (*AuthResult, error) {
options := smb.Options{
Host: host,
Port: port,
@@ -480,11 +480,11 @@ func (a *SMB1Authenticator) ListShares(ctx context.Context, host string, port in
type SMB2Authenticator struct{}
// Authenticate 执行SMB2认证
func (a *SMB2Authenticator) Authenticate(ctx context.Context, host string, port int, cred Credential, domain string, timeout time.Duration) (*AuthResult, error) {
func (a *SMB2Authenticator) Authenticate(ctx context.Context, host string, port int, cred Credential, domain string, timeout time.Duration, session *common.ScanSession) (*AuthResult, error) {
timeoutCtx, cancel := context.WithTimeout(ctx, timeout)
defer cancel()
conn, err := common.WrapperTcpWithTimeout("tcp", fmt.Sprintf("%s:%d", host, port), timeout)
conn, err := session.DialTCP(ctx, "tcp", fmt.Sprintf("%s:%d", host, port), timeout)
if err != nil {
return &AuthResult{
Success: false,
+29 -47
View File
@@ -27,15 +27,14 @@ func NewSMTPPlugin() *SMTPPlugin {
func (p *SMTPPlugin) Scan(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult {
config := session.Config
state := session.State
target := info.Target()
if config.DisableBrute {
return p.identifyService(ctx, info, config, state)
return p.identifyService(ctx, info, session)
}
// 检测未授权访问
if result := p.testUnauthorizedAccess(ctx, info, config, state); result != nil && result.Success {
if result := p.testUnauthorizedAccess(ctx, info, session); result != nil && result.Success {
common.LogSuccess(i18n.Tr("smtp_service", target, result.Banner))
return result
}
@@ -57,7 +56,7 @@ func (p *SMTPPlugin) Scan(ctx context.Context, info *common.HostInfo, session *c
}
// 使用公共框架进行并发凭据测试
authFn := p.createAuthFunc(info, config, state)
authFn := p.createAuthFunc(info, session)
testConfig := DefaultConcurrentTestConfig(config)
result := TestCredentialsConcurrently(ctx, creds, authFn, "smtp", testConfig)
@@ -70,23 +69,22 @@ func (p *SMTPPlugin) Scan(ctx context.Context, info *common.HostInfo, session *c
}
// createAuthFunc 创建SMTP认证函数
func (p *SMTPPlugin) createAuthFunc(info *common.HostInfo, config *common.Config, state *common.State) AuthFunc {
func (p *SMTPPlugin) createAuthFunc(info *common.HostInfo, session *common.ScanSession) AuthFunc {
return func(ctx context.Context, cred Credential) *AuthResult {
return p.doSMTPAuth(ctx, info, cred, config, state)
return p.doSMTPAuth(ctx, info, cred, session)
}
}
// doSMTPAuth 执行SMTP认证
func (p *SMTPPlugin) doSMTPAuth(ctx context.Context, info *common.HostInfo, cred Credential, config *common.Config, state *common.State) *AuthResult {
func (p *SMTPPlugin) doSMTPAuth(ctx context.Context, info *common.HostInfo, cred Credential, session *common.ScanSession) *AuthResult {
target := info.Target()
timeout := config.Timeout
timeout := session.Config.Timeout
resultChan := make(chan *AuthResult, 1)
go func() {
conn, err := common.WrapperTcpWithTimeout("tcp", target, timeout)
conn, err := session.DialTCP(ctx, "tcp", target, timeout)
if err != nil {
state.IncrementTCPFailedPacketCount()
resultChan <- &AuthResult{
Success: false,
ErrorType: classifySMTPErrorType(err),
@@ -100,7 +98,6 @@ func (p *SMTPPlugin) doSMTPAuth(ctx context.Context, info *common.HostInfo, cred
client, err := smtp.NewClient(conn, info.Host)
if err != nil {
_ = conn.Close()
state.IncrementTCPFailedPacketCount()
resultChan <- &AuthResult{
Success: false,
ErrorType: classifySMTPErrorType(err),
@@ -113,7 +110,6 @@ func (p *SMTPPlugin) doSMTPAuth(ctx context.Context, info *common.HostInfo, cred
auth := smtp.PlainAuth("", cred.Username, cred.Password, info.Host)
if err := client.Auth(auth); err != nil {
_ = client.Close()
state.IncrementTCPFailedPacketCount()
resultChan <- &AuthResult{
Success: false,
ErrorType: classifySMTPErrorType(err),
@@ -125,7 +121,6 @@ func (p *SMTPPlugin) doSMTPAuth(ctx context.Context, info *common.HostInfo, cred
if err := client.Mail("[email protected]"); err != nil {
_ = client.Close()
state.IncrementTCPFailedPacketCount()
resultChan <- &AuthResult{
Success: false,
ErrorType: classifySMTPErrorType(err),
@@ -134,7 +129,6 @@ func (p *SMTPPlugin) doSMTPAuth(ctx context.Context, info *common.HostInfo, cred
return
}
state.IncrementTCPSuccessPacketCount()
resultChan <- &AuthResult{
Success: true,
Conn: &smtpClientWrapper{client},
@@ -211,24 +205,24 @@ func classifySMTPErrorType(err error) ErrorType {
}
// testUnauthorizedAccess 测试SMTP未授权访问
func (p *SMTPPlugin) testUnauthorizedAccess(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult {
func (p *SMTPPlugin) testUnauthorizedAccess(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult {
// 测试匿名访问
if result := p.testAnonymousAccess(ctx, info, config, state); result != nil {
if result := p.testAnonymousAccess(ctx, info, session); result != nil {
return result
}
// 测试开放中继
if result := p.testOpenRelay(ctx, info, config, state); result != nil {
if result := p.testOpenRelay(ctx, info, session); result != nil {
return result
}
// 测试VRFY命令
if result := p.testVRFYCommand(ctx, info, config, state); result != nil {
if result := p.testVRFYCommand(ctx, info, session); result != nil {
return result
}
// 测试EXPN命令
if result := p.testEXPNCommand(ctx, info, config, state); result != nil {
if result := p.testEXPNCommand(ctx, info, session); result != nil {
return result
}
@@ -236,15 +230,14 @@ func (p *SMTPPlugin) testUnauthorizedAccess(ctx context.Context, info *common.Ho
}
// testAnonymousAccess 测试匿名邮件发送
func (p *SMTPPlugin) testAnonymousAccess(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult {
func (p *SMTPPlugin) testAnonymousAccess(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult {
target := info.Target()
resultChan := make(chan *ScanResult, 1)
go func() {
conn, err := common.WrapperTcpWithTimeout("tcp", target, config.Timeout)
conn, err := session.DialTCP(ctx, "tcp", target, session.Config.Timeout)
if err != nil {
state.IncrementTCPFailedPacketCount()
resultChan <- nil
return
}
@@ -272,7 +265,6 @@ func (p *SMTPPlugin) testAnonymousAccess(ctx context.Context, info *common.HostI
return
}
state.IncrementTCPSuccessPacketCount()
resultChan <- &ScanResult{
Success: true,
Type: plugins.ResultTypeVuln,
@@ -290,15 +282,14 @@ func (p *SMTPPlugin) testAnonymousAccess(ctx context.Context, info *common.HostI
}
// testOpenRelay 测试开放中继
func (p *SMTPPlugin) testOpenRelay(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult {
func (p *SMTPPlugin) testOpenRelay(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult {
target := info.Target()
resultChan := make(chan *ScanResult, 1)
go func() {
conn, err := common.WrapperTcpWithTimeout("tcp", target, config.Timeout)
conn, err := session.DialTCP(ctx, "tcp", target, session.Config.Timeout)
if err != nil {
state.IncrementTCPFailedPacketCount()
resultChan <- nil
return
}
@@ -326,7 +317,6 @@ func (p *SMTPPlugin) testOpenRelay(ctx context.Context, info *common.HostInfo, c
return
}
state.IncrementTCPSuccessPacketCount()
resultChan <- &ScanResult{
Success: true,
Type: plugins.ResultTypeVuln,
@@ -344,21 +334,20 @@ func (p *SMTPPlugin) testOpenRelay(ctx context.Context, info *common.HostInfo, c
}
// testVRFYCommand 测试VRFY命令用户枚举
func (p *SMTPPlugin) testVRFYCommand(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult {
func (p *SMTPPlugin) testVRFYCommand(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult {
target := info.Target()
resultChan := make(chan *ScanResult, 1)
go func() {
conn, err := common.WrapperTcpWithTimeout("tcp", target, config.Timeout)
conn, err := session.DialTCP(ctx, "tcp", target, session.Config.Timeout)
if err != nil {
state.IncrementTCPFailedPacketCount()
resultChan <- nil
return
}
defer func() { _ = conn.Close() }()
_ = conn.SetDeadline(time.Now().Add(config.Timeout))
_ = conn.SetDeadline(time.Now().Add(session.Config.Timeout))
if _, heloWriteErr := fmt.Fprintf(conn, "HELO fscan.test\r\n"); heloWriteErr != nil {
resultChan <- nil
@@ -393,7 +382,6 @@ func (p *SMTPPlugin) testVRFYCommand(ctx context.Context, info *common.HostInfo,
vrfyResponse := strings.TrimSpace(string(buffer[:n]))
if strings.HasPrefix(vrfyResponse, "250") {
state.IncrementTCPSuccessPacketCount()
resultChan <- &ScanResult{
Success: true,
Type: plugins.ResultTypeVuln,
@@ -416,21 +404,20 @@ func (p *SMTPPlugin) testVRFYCommand(ctx context.Context, info *common.HostInfo,
}
// testEXPNCommand 测试EXPN命令邮件列表枚举
func (p *SMTPPlugin) testEXPNCommand(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult {
func (p *SMTPPlugin) testEXPNCommand(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult {
target := info.Target()
resultChan := make(chan *ScanResult, 1)
go func() {
conn, err := common.WrapperTcpWithTimeout("tcp", target, config.Timeout)
conn, err := session.DialTCP(ctx, "tcp", target, session.Config.Timeout)
if err != nil {
state.IncrementTCPFailedPacketCount()
resultChan <- nil
return
}
defer func() { _ = conn.Close() }()
_ = conn.SetDeadline(time.Now().Add(config.Timeout))
_ = conn.SetDeadline(time.Now().Add(session.Config.Timeout))
if _, heloWriteErr := fmt.Fprintf(conn, "HELO fscan.test\r\n"); heloWriteErr != nil {
resultChan <- nil
@@ -465,7 +452,6 @@ func (p *SMTPPlugin) testEXPNCommand(ctx context.Context, info *common.HostInfo,
expnResponse := strings.TrimSpace(string(buffer[:n]))
if strings.HasPrefix(expnResponse, "250") {
state.IncrementTCPSuccessPacketCount()
resultChan <- &ScanResult{
Success: true,
Type: plugins.ResultTypeVuln,
@@ -488,21 +474,20 @@ func (p *SMTPPlugin) testEXPNCommand(ctx context.Context, info *common.HostInfo,
}
// getServerInfo 获取SMTP服务器信息
func (p *SMTPPlugin) getServerInfo(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) string {
func (p *SMTPPlugin) getServerInfo(ctx context.Context, info *common.HostInfo, session *common.ScanSession) string {
target := info.Target()
resultChan := make(chan string, 1)
go func() {
conn, err := common.SafeTCPDial(target, config.Timeout)
conn, err := session.DialTCP(ctx, "tcp", target, session.Config.Timeout)
if err != nil {
state.IncrementTCPFailedPacketCount()
resultChan <- ""
return
}
defer func() { _ = conn.Close() }()
_ = conn.SetReadDeadline(time.Now().Add(config.Timeout))
_ = conn.SetReadDeadline(time.Now().Add(session.Config.Timeout))
buffer := make([]byte, 1024)
n, err := conn.Read(buffer)
if err != nil {
@@ -510,7 +495,6 @@ func (p *SMTPPlugin) getServerInfo(ctx context.Context, info *common.HostInfo, c
return
}
state.IncrementTCPSuccessPacketCount()
welcome := strings.TrimSpace(string(buffer[:n]))
if strings.HasPrefix(welcome, "220") {
@@ -531,18 +515,17 @@ func (p *SMTPPlugin) getServerInfo(ctx context.Context, info *common.HostInfo, c
}
// identifyService SMTP服务识别
func (p *SMTPPlugin) identifyService(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult {
func (p *SMTPPlugin) identifyService(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult {
target := info.Target()
serverInfo := p.getServerInfo(ctx, info, config, state)
serverInfo := p.getServerInfo(ctx, info, session)
var banner string
if serverInfo != "" {
banner = fmt.Sprintf("SMTP邮件服务 (%s)", serverInfo)
} else {
conn, err := common.SafeTCPDial(target, config.Timeout)
conn, err := session.DialTCP(ctx, "tcp", target, session.Config.Timeout)
if err != nil {
state.IncrementTCPFailedPacketCount()
return &ScanResult{
Success: false,
Service: "smtp",
@@ -550,7 +533,6 @@ func (p *SMTPPlugin) identifyService(ctx context.Context, info *common.HostInfo,
}
}
defer func() { _ = conn.Close() }()
state.IncrementTCPSuccessPacketCount()
banner = "SMTP邮件服务"
}
+14 -19
View File
@@ -36,12 +36,11 @@ func NewSSHPlugin() *SSHPlugin {
// Scan 执行SSH扫描
func (p *SSHPlugin) Scan(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult {
config := session.Config
state := session.State
target := info.Target()
// 如果指定了SSH密钥,优先使用密钥认证
if config.Credentials.SSHKeyPath != "" {
if result := p.scanWithKey(ctx, info, config, state); result != nil && result.Success {
if result := p.scanWithKey(ctx, info, session); result != nil && result.Success {
common.LogVuln(i18n.Tr("ssh_key_auth_success", target, result.Username)) //nolint:govet
return result
}
@@ -49,7 +48,7 @@ func (p *SSHPlugin) Scan(ctx context.Context, info *common.HostInfo, session *co
// 如果禁用暴力破解,只做服务识别
if config.DisableBrute {
return p.identifyService(info, config, state)
return p.identifyService(ctx, info, session)
}
// 生成测试凭据
@@ -65,7 +64,7 @@ func (p *SSHPlugin) Scan(ctx context.Context, info *common.HostInfo, session *co
}
// 使用公共框架进行并发凭据测试
authFn := p.createAuthFunc(info, config, state)
authFn := p.createAuthFunc(info, session)
testConfig := DefaultConcurrentTestConfig(config)
result := TestCredentialsConcurrently(ctx, credentials, authFn, "ssh", testConfig)
@@ -79,14 +78,15 @@ func (p *SSHPlugin) Scan(ctx context.Context, info *common.HostInfo, session *co
}
// createAuthFunc 创建SSH认证函数
func (p *SSHPlugin) createAuthFunc(info *common.HostInfo, config *common.Config, state *common.State) AuthFunc {
func (p *SSHPlugin) createAuthFunc(info *common.HostInfo, session *common.ScanSession) AuthFunc {
return func(ctx context.Context, cred Credential) *AuthResult {
return p.doSSHAuth(ctx, info, cred, config, state)
return p.doSSHAuth(ctx, info, cred, session)
}
}
// doSSHAuth 执行SSH认证
func (p *SSHPlugin) doSSHAuth(ctx context.Context, info *common.HostInfo, cred Credential, config *common.Config, state *common.State) *AuthResult {
func (p *SSHPlugin) doSSHAuth(ctx context.Context, info *common.HostInfo, cred Credential, session *common.ScanSession) *AuthResult {
config := session.Config
target := info.Target()
// 创建SSH配置
@@ -113,9 +113,8 @@ func (p *SSHPlugin) doSSHAuth(ctx context.Context, info *common.HostInfo, cred C
}
// 建立TCP连接
conn, err := common.WrapperTcpWithTimeout("tcp", target, config.Timeout)
conn, err := session.DialTCP(ctx, "tcp", target, config.Timeout)
if err != nil {
state.IncrementTCPFailedPacketCount()
return &AuthResult{
Success: false,
ErrorType: classifySSHErrorType(err),
@@ -127,7 +126,6 @@ func (p *SSHPlugin) doSSHAuth(ctx context.Context, info *common.HostInfo, cred C
sshConn, chans, reqs, err := ssh.NewClientConn(conn, target, sshConfig)
if err != nil {
_ = conn.Close()
state.IncrementTCPFailedPacketCount()
return &AuthResult{
Success: false,
ErrorType: classifySSHErrorType(err),
@@ -138,7 +136,6 @@ func (p *SSHPlugin) doSSHAuth(ctx context.Context, info *common.HostInfo, cred C
// 创建SSH客户端
client := ssh.NewClient(sshConn, chans, reqs)
state.IncrementTCPSuccessPacketCount()
return &AuthResult{
Success: true,
Conn: &sshClientWrapper{client},
@@ -181,7 +178,8 @@ func classifySSHErrorType(err error) ErrorType {
}
// scanWithKey 使用SSH私钥扫描
func (p *SSHPlugin) scanWithKey(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult {
func (p *SSHPlugin) scanWithKey(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult {
config := session.Config
keyData, err := os.ReadFile(config.Credentials.SSHKeyPath)
if err != nil {
common.LogError(i18n.Tr("ssh_key_read_failed", err)) //nolint:govet
@@ -206,7 +204,7 @@ func (p *SSHPlugin) scanWithKey(ctx context.Context, info *common.HostInfo, conf
KeyData: keyData,
}
result := p.doSSHAuth(ctx, info, cred, config, state)
result := p.doSSHAuth(ctx, info, cred, session)
if result.Success {
if result.Conn != nil {
_ = result.Conn.Close()
@@ -224,12 +222,11 @@ func (p *SSHPlugin) scanWithKey(ctx context.Context, info *common.HostInfo, conf
}
// identifyService 服务识别
func (p *SSHPlugin) identifyService(info *common.HostInfo, config *common.Config, state *common.State) *ScanResult {
func (p *SSHPlugin) identifyService(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult {
target := info.Target()
conn, err := common.SafeTCPDial(target, config.Timeout)
conn, err := session.DialTCP(ctx, "tcp", target, session.Config.Timeout)
if err != nil {
state.IncrementTCPFailedPacketCount()
return &ScanResult{
Success: false,
Service: "ssh",
@@ -238,8 +235,7 @@ func (p *SSHPlugin) identifyService(info *common.HostInfo, config *common.Config
}
defer func() { _ = conn.Close() }()
if banner := p.readSSHBanner(conn, config); banner != "" {
state.IncrementTCPSuccessPacketCount()
if banner := p.readSSHBanner(conn, session.Config); banner != "" {
common.LogSuccess(i18n.Tr("ssh_service_identified", target, banner)) //nolint:govet
return &ScanResult{
Type: plugins.ResultTypeService,
@@ -249,7 +245,6 @@ func (p *SSHPlugin) identifyService(info *common.HostInfo, config *common.Config
}
}
state.IncrementTCPFailedPacketCount()
return &ScanResult{
Success: false,
Service: "ssh",
+19 -28
View File
@@ -56,14 +56,14 @@ func (p *TelnetPlugin) Scan(ctx context.Context, info *common.HostInfo, session
target := info.Target()
if config.DisableBrute {
return p.identifyService(ctx, info, config, state)
return p.identifyService(ctx, info, session)
}
// 检测未授权访问
if result := p.testUnauthAccess(ctx, info, config, state); result != nil && result.Success {
if result := p.testUnauthAccess(ctx, info, session); result != nil && result.Success {
common.LogVuln(i18n.Tr("telnet_service", target, result.Banner))
// 验证命令执行能力
if ok, osType, evidence := p.verifyCommandExecution(ctx, info, "", "", config, state); ok {
if ok, osType, evidence := p.verifyCommandExecution(ctx, info, "", "", session); ok {
common.LogVuln(i18n.Tr("telnet_unauth_rce", target, osType, evidence))
}
return result
@@ -103,7 +103,7 @@ func (p *TelnetPlugin) Scan(ctx context.Context, info *common.HostInfo, session
}
// 使用公共框架进行并发凭据测试
authFn := p.createAuthFunc(info, config, state)
authFn := p.createAuthFunc(info, session)
testConfig := DefaultConcurrentTestConfig(config)
result := TestCredentialsConcurrently(ctx, creds, authFn, "telnet", testConfig)
@@ -111,7 +111,7 @@ func (p *TelnetPlugin) Scan(ctx context.Context, info *common.HostInfo, session
if result.Success {
common.LogVuln(i18n.Tr("telnet_credential", target, result.Username, result.Password))
// 验证命令执行能力
if ok, osType, evidence := p.verifyCommandExecution(ctx, info, result.Username, result.Password, config, state); ok {
if ok, osType, evidence := p.verifyCommandExecution(ctx, info, result.Username, result.Password, session); ok {
common.LogVuln(i18n.Tr("telnet_credential_rce", target, result.Username, result.Password, osType, evidence))
}
}
@@ -120,22 +120,21 @@ func (p *TelnetPlugin) Scan(ctx context.Context, info *common.HostInfo, session
}
// createAuthFunc 创建Telnet认证函数
func (p *TelnetPlugin) createAuthFunc(info *common.HostInfo, config *common.Config, state *common.State) AuthFunc {
func (p *TelnetPlugin) createAuthFunc(info *common.HostInfo, session *common.ScanSession) AuthFunc {
return func(ctx context.Context, cred Credential) *AuthResult {
return p.doTelnetAuth(ctx, info, cred, config, state)
return p.doTelnetAuth(ctx, info, cred, session)
}
}
// doTelnetAuth 执行Telnet认证
func (p *TelnetPlugin) doTelnetAuth(ctx context.Context, info *common.HostInfo, cred Credential, config *common.Config, state *common.State) *AuthResult {
func (p *TelnetPlugin) doTelnetAuth(ctx context.Context, info *common.HostInfo, cred Credential, session *common.ScanSession) *AuthResult {
target := info.Target()
resultChan := make(chan *AuthResult, 1)
go func() {
conn, err := common.WrapperTcpWithTimeout("tcp", target, config.Timeout)
conn, err := session.DialTCP(ctx, "tcp", target, session.Config.Timeout)
if err != nil {
state.IncrementTCPFailedPacketCount()
resultChan <- &AuthResult{
Success: false,
ErrorType: classifyTelnetErrorType(err),
@@ -144,10 +143,9 @@ func (p *TelnetPlugin) doTelnetAuth(ctx context.Context, info *common.HostInfo,
return
}
_ = conn.SetDeadline(time.Now().Add(config.Timeout))
_ = conn.SetDeadline(time.Now().Add(session.Config.Timeout))
if p.performTelnetAuth(conn, cred.Username, cred.Password) {
state.IncrementTCPSuccessPacketCount()
resultChan <- &AuthResult{
Success: true,
Conn: &telnetConnWrapper{conn},
@@ -156,7 +154,6 @@ func (p *TelnetPlugin) doTelnetAuth(ctx context.Context, info *common.HostInfo,
}
} else {
_ = conn.Close()
state.IncrementTCPFailedPacketCount()
resultChan <- &AuthResult{
Success: false,
ErrorType: ErrorTypeAuth,
@@ -224,21 +221,20 @@ func classifyTelnetErrorType(err error) ErrorType {
}
// testUnauthAccess 测试Telnet未授权访问
func (p *TelnetPlugin) testUnauthAccess(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult {
func (p *TelnetPlugin) testUnauthAccess(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult {
target := info.Target()
resultChan := make(chan *ScanResult, 1)
go func() {
conn, err := common.WrapperTcpWithTimeout("tcp", target, config.Timeout)
conn, err := session.DialTCP(ctx, "tcp", target, session.Config.Timeout)
if err != nil {
state.IncrementTCPFailedPacketCount()
resultChan <- nil
return
}
defer func() { _ = conn.Close() }()
_ = conn.SetDeadline(time.Now().Add(config.Timeout))
_ = conn.SetDeadline(time.Now().Add(session.Config.Timeout))
buffer := make([]byte, 1024)
attempts := 0
@@ -261,7 +257,6 @@ func (p *TelnetPlugin) testUnauthAccess(ctx context.Context, info *common.HostIn
p.handleIACNegotiation(conn, buffer[:n])
if p.isShellPrompt(cleaned) {
state.IncrementTCPSuccessPacketCount()
resultChan <- &ScanResult{
Success: true,
Type: plugins.ResultTypeVuln,
@@ -521,15 +516,14 @@ func (p *TelnetPlugin) isLoginFailed(data string) bool {
}
// identifyService Telnet服务识别
func (p *TelnetPlugin) identifyService(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult {
func (p *TelnetPlugin) identifyService(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult {
target := info.Target()
resultChan := make(chan *ScanResult, 1)
go func() {
conn, err := common.WrapperTcpWithTimeout("tcp", target, config.Timeout)
conn, err := session.DialTCP(ctx, "tcp", target, session.Config.Timeout)
if err != nil {
state.IncrementTCPFailedPacketCount()
resultChan <- &ScanResult{
Success: false,
Service: "telnet",
@@ -539,12 +533,11 @@ func (p *TelnetPlugin) identifyService(ctx context.Context, info *common.HostInf
}
defer func() { _ = conn.Close() }()
_ = conn.SetDeadline(time.Now().Add(config.Timeout))
_ = conn.SetDeadline(time.Now().Add(session.Config.Timeout))
buffer := make([]byte, 2048)
n, err := conn.Read(buffer)
if err != nil {
state.IncrementTCPFailedPacketCount()
resultChan <- &ScanResult{
Success: false,
Service: "telnet",
@@ -553,8 +546,6 @@ func (p *TelnetPlugin) identifyService(ctx context.Context, info *common.HostInf
return
}
state.IncrementTCPSuccessPacketCount()
p.handleIACNegotiation(conn, buffer[:n])
cleaned := p.cleanResponse(string(buffer[:n]))
cleanedLower := strings.ToLower(cleaned)
@@ -606,7 +597,7 @@ func (p *TelnetPlugin) identifyService(ctx context.Context, info *common.HostInf
}
// verifyCommandExecution 验证Telnet命令执行能力(RCE检测)
func (p *TelnetPlugin) verifyCommandExecution(ctx context.Context, info *common.HostInfo, username, password string, config *common.Config, state *common.State) (bool, string, string) {
func (p *TelnetPlugin) verifyCommandExecution(ctx context.Context, info *common.HostInfo, username, password string, session *common.ScanSession) (bool, string, string) {
target := info.Target()
type rceResult struct {
@@ -618,14 +609,14 @@ func (p *TelnetPlugin) verifyCommandExecution(ctx context.Context, info *common.
resultChan := make(chan rceResult, 1)
go func() {
conn, err := common.WrapperTcpWithTimeout("tcp", target, config.Timeout)
conn, err := session.DialTCP(ctx, "tcp", target, session.Config.Timeout)
if err != nil {
resultChan <- rceResult{}
return
}
defer func() { _ = conn.Close() }()
_ = conn.SetDeadline(time.Now().Add(config.Timeout + telnetRCEExtraTimeout))
_ = conn.SetDeadline(time.Now().Add(session.Config.Timeout + telnetRCEExtraTimeout))
// 需要认证时先登录
if username != "" || password != "" {
+9 -14
View File
@@ -26,11 +26,10 @@ func NewVNCPlugin() *VNCPlugin {
func (p *VNCPlugin) Scan(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult {
config := session.Config
state := session.State
target := info.Target()
// 检查未授权访问
if result := p.testUnauthAccess(ctx, info, config, state); result != nil && result.Success {
if result := p.testUnauthAccess(ctx, info, session); result != nil && result.Success {
common.LogVuln(i18n.Tr("vnc_unauth", target))
return result
}
@@ -49,7 +48,7 @@ func (p *VNCPlugin) Scan(ctx context.Context, info *common.HostInfo, session *co
}
// 使用公共框架进行并发凭据测试
authFn := p.createAuthFunc(info, config, state)
authFn := p.createAuthFunc(info, session)
testConfig := DefaultConcurrentTestConfig(config)
result := TestCredentialsConcurrently(ctx, credentials, authFn, "vnc", testConfig)
@@ -62,22 +61,21 @@ func (p *VNCPlugin) Scan(ctx context.Context, info *common.HostInfo, session *co
}
// createAuthFunc 创建VNC认证函数
func (p *VNCPlugin) createAuthFunc(info *common.HostInfo, config *common.Config, state *common.State) AuthFunc {
func (p *VNCPlugin) createAuthFunc(info *common.HostInfo, session *common.ScanSession) AuthFunc {
return func(ctx context.Context, cred Credential) *AuthResult {
return p.doVNCAuth(ctx, info, cred, config, state)
return p.doVNCAuth(ctx, info, cred, session)
}
}
// doVNCAuth 执行VNC认证
func (p *VNCPlugin) doVNCAuth(ctx context.Context, info *common.HostInfo, cred Credential, config *common.Config, state *common.State) *AuthResult {
func (p *VNCPlugin) doVNCAuth(ctx context.Context, info *common.HostInfo, cred Credential, session *common.ScanSession) *AuthResult {
target := info.Target()
resultChan := make(chan *AuthResult, 1)
go func() {
conn, err := common.WrapperTcpWithTimeout("tcp", target, config.Timeout)
conn, err := session.DialTCP(ctx, "tcp", target, session.Config.Timeout)
if err != nil {
state.IncrementTCPFailedPacketCount()
resultChan <- &AuthResult{
Success: false,
ErrorType: classifyVNCErrorType(err),
@@ -86,7 +84,7 @@ func (p *VNCPlugin) doVNCAuth(ctx context.Context, info *common.HostInfo, cred C
return
}
_ = conn.SetDeadline(time.Now().Add(config.Timeout))
_ = conn.SetDeadline(time.Now().Add(session.Config.Timeout))
vncConfig := &vnc.ClientConfig{
Auth: []vnc.ClientAuth{
@@ -97,7 +95,6 @@ func (p *VNCPlugin) doVNCAuth(ctx context.Context, info *common.HostInfo, cred C
client, err := vnc.Client(conn, vncConfig)
if err != nil {
_ = conn.Close()
state.IncrementTCPFailedPacketCount()
resultChan <- &AuthResult{
Success: false,
ErrorType: classifyVNCErrorType(err),
@@ -106,8 +103,6 @@ func (p *VNCPlugin) doVNCAuth(ctx context.Context, info *common.HostInfo, cred C
return
}
state.IncrementTCPSuccessPacketCount()
resultChan <- &AuthResult{
Success: true,
Conn: &vncClientWrapper{client, conn},
@@ -175,9 +170,9 @@ func classifyVNCErrorType(err error) ErrorType {
return ClassifyError(err, nil, CommonNetworkErrors)
}
func (p *VNCPlugin) testUnauthAccess(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult {
func (p *VNCPlugin) testUnauthAccess(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult {
cred := Credential{Username: "", Password: ""}
result := p.doVNCAuth(ctx, info, cred, config, state)
result := p.doVNCAuth(ctx, info, cred, session)
if result.Success {
if result.Conn != nil {