mirror of
https://github.com/shadow1ng/fscan.git
synced 2025-09-14 14:06:44 +08:00
feat: 实现智能Web服务检测系统
- 扩展Web端口识别范围至40+个常见端口 - 新增HTTP/HTTPS协议智能探测机制 - 实现并发协议检测提升性能 - 添加精确错误分析避免误判 - 完善插件过滤确保Web插件仅在检测到Web服务时执行 - 支持端口模式匹配和响应头分析
This commit is contained in:
parent
0cc29afbeb
commit
338dd60c3e
@ -108,7 +108,8 @@ func (b *BaseScanStrategy) isPluginTypeMatchedByName(pluginName string) bool {
|
|||||||
case FilterLocal:
|
case FilterLocal:
|
||||||
return metadata.Category == "local"
|
return metadata.Category == "local"
|
||||||
case FilterService:
|
case FilterService:
|
||||||
return metadata.Category == "service"
|
// 服务扫描允许service类型,以及通过智能检测的web类型(在上层逻辑中处理)
|
||||||
|
return metadata.Category == "service" || metadata.Category == "web"
|
||||||
case FilterWeb:
|
case FilterWeb:
|
||||||
return metadata.Category == "web"
|
return metadata.Category == "web"
|
||||||
default:
|
default:
|
||||||
@ -122,6 +123,7 @@ func (b *BaseScanStrategy) isPluginTypeMatched(plugin common.ScanPlugin) bool {
|
|||||||
case FilterLocal:
|
case FilterLocal:
|
||||||
return plugin.HasType(common.PluginTypeLocal)
|
return plugin.HasType(common.PluginTypeLocal)
|
||||||
case FilterService:
|
case FilterService:
|
||||||
|
// 服务扫描排除本地插件,允许服务和Web插件
|
||||||
return !plugin.HasType(common.PluginTypeLocal)
|
return !plugin.HasType(common.PluginTypeLocal)
|
||||||
case FilterWeb:
|
case FilterWeb:
|
||||||
return plugin.HasType(common.PluginTypeWeb)
|
return plugin.HasType(common.PluginTypeWeb)
|
||||||
@ -131,7 +133,7 @@ func (b *BaseScanStrategy) isPluginTypeMatched(plugin common.ScanPlugin) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// IsPluginApplicableByName 根据插件名称判断是否适用(新方法)
|
// IsPluginApplicableByName 根据插件名称判断是否适用(新方法)
|
||||||
func (b *BaseScanStrategy) IsPluginApplicableByName(pluginName string, targetPort int, isCustomMode bool) bool {
|
func (b *BaseScanStrategy) IsPluginApplicableByName(pluginName string, targetHost string, targetPort int, isCustomMode bool) bool {
|
||||||
// 自定义模式下运行所有明确指定的插件
|
// 自定义模式下运行所有明确指定的插件
|
||||||
if isCustomMode {
|
if isCustomMode {
|
||||||
return true
|
return true
|
||||||
@ -143,7 +145,7 @@ func (b *BaseScanStrategy) IsPluginApplicableByName(pluginName string, targetPor
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 智能Web插件检测:如果是Web插件且检测到Web服务,则包含Web插件
|
// 智能Web插件检测:如果是Web插件且检测到Web服务,则包含Web插件
|
||||||
if b.shouldIncludeWebPlugin(metadata, targetPort) {
|
if b.shouldIncludeWebPlugin(metadata, targetHost, targetPort) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,11 +164,16 @@ func (b *BaseScanStrategy) IsPluginApplicableByName(pluginName string, targetPor
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 对于Web插件,即使没有端口限制,也必须通过智能检测才能执行
|
||||||
|
if metadata.Category == "web" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// shouldIncludeWebPlugin 判断是否应该包含Web插件(智能检测)
|
// shouldIncludeWebPlugin 判断是否应该包含Web插件(智能检测)
|
||||||
func (b *BaseScanStrategy) shouldIncludeWebPlugin(metadata *base.PluginMetadata, targetPort int) bool {
|
func (b *BaseScanStrategy) shouldIncludeWebPlugin(metadata *base.PluginMetadata, targetHost string, targetPort int) bool {
|
||||||
// 只对服务扫描策略启用Web插件智能检测
|
// 只对服务扫描策略启用Web插件智能检测
|
||||||
if b.filterType != FilterService {
|
if b.filterType != FilterService {
|
||||||
return false
|
return false
|
||||||
@ -187,14 +194,14 @@ func (b *BaseScanStrategy) shouldIncludeWebPlugin(metadata *base.PluginMetadata,
|
|||||||
globalWebDetector = NewWebPortDetector()
|
globalWebDetector = NewWebPortDetector()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检测是否为Web服务(这里暂时只检查常见端口,避免每次都进行HTTP探测)
|
// 检测是否为Web服务(使用完整的智能检测,包括HTTP协议探测)
|
||||||
return globalWebDetector.IsCommonWebPort(targetPort)
|
return globalWebDetector.IsWebService(targetHost, targetPort)
|
||||||
}
|
}
|
||||||
|
|
||||||
// globalWebDetector Web检测器全局实例
|
// globalWebDetector Web检测器全局实例
|
||||||
var globalWebDetector *WebPortDetector
|
var globalWebDetector *WebPortDetector
|
||||||
|
|
||||||
// IsPluginApplicable 判断插件是否适用(通用实现)
|
// IsPluginApplicable 判断插件是否适用(通用实现,传统插件系统)
|
||||||
func (b *BaseScanStrategy) IsPluginApplicable(plugin common.ScanPlugin, targetPort int, isCustomMode bool) bool {
|
func (b *BaseScanStrategy) IsPluginApplicable(plugin common.ScanPlugin, targetPort int, isCustomMode bool) bool {
|
||||||
// 自定义模式下运行所有明确指定的插件
|
// 自定义模式下运行所有明确指定的插件
|
||||||
if isCustomMode {
|
if isCustomMode {
|
||||||
@ -206,6 +213,21 @@ func (b *BaseScanStrategy) IsPluginApplicable(plugin common.ScanPlugin, targetPo
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 对于服务扫描中的Web插件,需要进行智能检测(传统插件系统)
|
||||||
|
if b.filterType == FilterService && plugin.HasType(common.PluginTypeWeb) {
|
||||||
|
// 获取Web检测器实例(延迟初始化)
|
||||||
|
if globalWebDetector == nil {
|
||||||
|
globalWebDetector = NewWebPortDetector()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 注意:传统插件系统无法传递host参数,使用空字符串
|
||||||
|
// 这是传统插件系统的限制,新插件系统已经解决了这个问题
|
||||||
|
if targetPort > 0 {
|
||||||
|
return globalWebDetector.IsWebService("", targetPort)
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// 对于服务扫描,还需检查端口匹配
|
// 对于服务扫描,还需检查端口匹配
|
||||||
if b.filterType == FilterService {
|
if b.filterType == FilterService {
|
||||||
// 无端口限制的插件适用于所有端口
|
// 无端口限制的插件适用于所有端口
|
||||||
|
@ -19,7 +19,7 @@ type ScanStrategy interface {
|
|||||||
// 插件管理方法
|
// 插件管理方法
|
||||||
GetPlugins() ([]string, bool)
|
GetPlugins() ([]string, bool)
|
||||||
IsPluginApplicable(plugin common.ScanPlugin, targetPort int, isCustomMode bool) bool
|
IsPluginApplicable(plugin common.ScanPlugin, targetPort int, isCustomMode bool) bool
|
||||||
IsPluginApplicableByName(pluginName string, targetPort int, isCustomMode bool) bool
|
IsPluginApplicableByName(pluginName string, targetHost string, targetPort int, isCustomMode bool) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// selectStrategy 根据扫描配置选择适当的扫描策略
|
// selectStrategy 根据扫描配置选择适当的扫描策略
|
||||||
@ -125,7 +125,7 @@ func ExecuteScanTasks(targets []common.HostInfo, strategy ScanStrategy, ch *chan
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 检查插件是否适用于当前目标
|
// 检查插件是否适用于当前目标
|
||||||
if strategy.IsPluginApplicableByName(pluginName, targetPort, isCustomMode) {
|
if strategy.IsPluginApplicableByName(pluginName, target.Host, targetPort, isCustomMode) {
|
||||||
executeScanTask(pluginName, target, ch, wg)
|
executeScanTask(pluginName, target, ch, wg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -143,7 +143,7 @@ func countApplicableTasks(targets []common.HostInfo, pluginsToRun []string, isCu
|
|||||||
|
|
||||||
for _, pluginName := range pluginsToRun {
|
for _, pluginName := range pluginsToRun {
|
||||||
if GlobalPluginAdapter.PluginExists(pluginName) &&
|
if GlobalPluginAdapter.PluginExists(pluginName) &&
|
||||||
strategy.IsPluginApplicableByName(pluginName, targetPort, isCustomMode) {
|
strategy.IsPluginApplicableByName(pluginName, target.Host, targetPort, isCustomMode) {
|
||||||
count++
|
count++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,17 @@
|
|||||||
package core
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
"crypto/tls"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/shadow1ng/fscan/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
// WebPortDetector Web端口检测器
|
// WebPortDetector Web端口检测器
|
||||||
@ -10,49 +20,336 @@ type WebPortDetector struct {
|
|||||||
commonWebPorts map[int]bool
|
commonWebPorts map[int]bool
|
||||||
// HTTP检测超时时间
|
// HTTP检测超时时间
|
||||||
httpTimeout time.Duration
|
httpTimeout time.Duration
|
||||||
|
// HTTP客户端
|
||||||
|
httpClient *http.Client
|
||||||
|
// HTTPS客户端
|
||||||
|
httpsClient *http.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewWebPortDetector 创建Web端口检测器
|
// NewWebPortDetector 创建Web端口检测器
|
||||||
func NewWebPortDetector() *WebPortDetector {
|
func NewWebPortDetector() *WebPortDetector {
|
||||||
// 定义常见Web端口
|
timeout := 3 * time.Second
|
||||||
|
|
||||||
|
// 定义常见Web端口(扩展列表)
|
||||||
commonPorts := map[int]bool{
|
commonPorts := map[int]bool{
|
||||||
|
// 标准Web端口
|
||||||
80: true, // HTTP
|
80: true, // HTTP
|
||||||
443: true, // HTTPS
|
443: true, // HTTPS
|
||||||
8080: true, // HTTP alternate
|
8080: true, // HTTP alternate
|
||||||
8443: true, // HTTPS alternate
|
8443: true, // HTTPS alternate
|
||||||
|
|
||||||
|
// 开发服务器端口
|
||||||
|
3000: true, // Node.js dev server
|
||||||
|
4000: true, // Ruby dev server
|
||||||
|
5000: true, // Python dev server
|
||||||
8000: true, // Development server
|
8000: true, // Development server
|
||||||
8888: true, // Common dev port
|
8888: true, // Common dev port
|
||||||
9000: true, // Common dev port
|
9000: true, // Common dev port
|
||||||
9090: true, // Common dev port
|
9090: true, // Common dev port
|
||||||
3000: true, // Node.js dev server
|
|
||||||
4000: true, // Ruby dev server
|
// Web服务器alternate端口
|
||||||
5000: true, // Python dev server
|
8081: true, 8082: true, 8083: true, 8084: true, 8085: true,
|
||||||
8081: true, // HTTP alternate
|
8086: true, 8087: true, 8088: true, 8089: true,
|
||||||
8082: true, // HTTP alternate
|
|
||||||
8083: true, // HTTP alternate
|
// 企业级Web端口
|
||||||
8084: true, // HTTP alternate
|
9080: true, // WebSphere
|
||||||
8085: true, // HTTP alternate
|
9443: true, // WebSphere SSL
|
||||||
8086: true, // HTTP alternate
|
7001: true, // WebLogic
|
||||||
8087: true, // HTTP alternate
|
7002: true, // WebLogic SSL
|
||||||
8088: true, // HTTP alternate
|
|
||||||
8089: true, // HTTP alternate
|
// 应用服务器端口
|
||||||
|
8180: true, // Tomcat alternate
|
||||||
|
8181: true, // Tomcat alternate
|
||||||
|
8282: true, // Common alternate
|
||||||
|
8383: true, // Common alternate
|
||||||
|
8484: true, // Common alternate
|
||||||
|
8585: true, // Common alternate
|
||||||
|
|
||||||
|
// 代理和负载均衡端口
|
||||||
|
3128: true, // Squid proxy
|
||||||
|
8008: true, // HTTP proxy
|
||||||
|
8118: true, // Privoxy
|
||||||
|
|
||||||
|
// 监控和管理界面
|
||||||
|
9200: true, // Elasticsearch
|
||||||
|
5601: true, // Kibana
|
||||||
|
3001: true, // Grafana alternate
|
||||||
|
9091: true, // Prometheus
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建HTTP客户端
|
||||||
|
httpClient := &http.Client{
|
||||||
|
Timeout: timeout,
|
||||||
|
Transport: &http.Transport{
|
||||||
|
DialContext: (&net.Dialer{
|
||||||
|
Timeout: timeout,
|
||||||
|
}).DialContext,
|
||||||
|
MaxIdleConns: 10,
|
||||||
|
IdleConnTimeout: 30 * time.Second,
|
||||||
|
DisableKeepAlives: true,
|
||||||
|
MaxConnsPerHost: 5,
|
||||||
|
},
|
||||||
|
CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
||||||
|
return http.ErrUseLastResponse // 不跟随重定向,减少检测时间
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建HTTPS客户端(跳过证书验证)
|
||||||
|
httpsClient := &http.Client{
|
||||||
|
Timeout: timeout,
|
||||||
|
Transport: &http.Transport{
|
||||||
|
DialContext: (&net.Dialer{
|
||||||
|
Timeout: timeout,
|
||||||
|
}).DialContext,
|
||||||
|
TLSClientConfig: &tls.Config{
|
||||||
|
InsecureSkipVerify: true,
|
||||||
|
},
|
||||||
|
MaxIdleConns: 10,
|
||||||
|
IdleConnTimeout: 30 * time.Second,
|
||||||
|
DisableKeepAlives: true,
|
||||||
|
MaxConnsPerHost: 5,
|
||||||
|
},
|
||||||
|
CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
||||||
|
return http.ErrUseLastResponse
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
return &WebPortDetector{
|
return &WebPortDetector{
|
||||||
commonWebPorts: commonPorts,
|
commonWebPorts: commonPorts,
|
||||||
httpTimeout: 2 * time.Second, // 2秒超时,快速检测
|
httpTimeout: timeout,
|
||||||
|
httpClient: httpClient,
|
||||||
|
httpsClient: httpsClient,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 已移除未使用的 IsWebService 方法
|
// IsWebService 智能检测端口是否运行Web服务
|
||||||
|
func (w *WebPortDetector) IsWebService(host string, port int) bool {
|
||||||
|
// 1. 快速路径:常见Web端口直接返回true
|
||||||
|
if w.IsCommonWebPort(port) {
|
||||||
|
common.LogDebug(fmt.Sprintf("端口 %d 是常见Web端口,启用Web插件", port))
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 智能路径:对非常见端口进行HTTP协议探测
|
||||||
|
common.LogDebug(fmt.Sprintf("对端口 %d 进行智能Web检测", port))
|
||||||
|
result := w.detectHTTPService(host, port)
|
||||||
|
common.LogDebug(fmt.Sprintf("端口 %d 智能检测结果: %v", port, result))
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
// IsCommonWebPort 检查是否为常见Web端口
|
// IsCommonWebPort 检查是否为常见Web端口
|
||||||
func (w *WebPortDetector) IsCommonWebPort(port int) bool {
|
func (w *WebPortDetector) IsCommonWebPort(port int) bool {
|
||||||
return w.commonWebPorts[port]
|
return w.commonWebPorts[port]
|
||||||
}
|
}
|
||||||
|
|
||||||
// 已移除未使用的 detectHTTPService 方法
|
// detectHTTPService 检测HTTP服务(真正的智能检测)
|
||||||
|
func (w *WebPortDetector) detectHTTPService(host string, port int) bool {
|
||||||
|
// 创建检测上下文,避免长时间阻塞
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), w.httpTimeout)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
// 已移除未使用的 tryHTTPConnection 方法
|
// 并发检测HTTP和HTTPS
|
||||||
|
httpChan := make(chan bool, 1)
|
||||||
|
httpsChan := make(chan bool, 1)
|
||||||
|
|
||||||
// 已移除未使用的 GetCommonWebPorts 方法
|
// 检测HTTP
|
||||||
|
go func() {
|
||||||
|
httpChan <- w.tryHTTPConnection(ctx, host, port, "http")
|
||||||
|
}()
|
||||||
|
|
||||||
|
// 检测HTTPS(对于高端口常见)
|
||||||
|
go func() {
|
||||||
|
httpsChan <- w.tryHTTPConnection(ctx, host, port, "https")
|
||||||
|
}()
|
||||||
|
|
||||||
|
// 等待任一协议检测成功
|
||||||
|
select {
|
||||||
|
case result := <-httpChan:
|
||||||
|
if result {
|
||||||
|
common.LogDebug(fmt.Sprintf("端口 %d 检测到HTTP服务", port))
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case <-ctx.Done():
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
case result := <-httpsChan:
|
||||||
|
if result {
|
||||||
|
common.LogDebug(fmt.Sprintf("端口 %d 检测到HTTPS服务", port))
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case <-ctx.Done():
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// tryHTTPConnection 尝试HTTP连接
|
||||||
|
func (w *WebPortDetector) tryHTTPConnection(ctx context.Context, host string, port int, protocol string) bool {
|
||||||
|
// 构造URL
|
||||||
|
var url string
|
||||||
|
if (port == 80 && protocol == "http") || (port == 443 && protocol == "https") {
|
||||||
|
url = fmt.Sprintf("%s://%s", protocol, host)
|
||||||
|
} else {
|
||||||
|
url = fmt.Sprintf("%s://%s:%d", protocol, host, port)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 选择客户端
|
||||||
|
var client *http.Client
|
||||||
|
if protocol == "https" {
|
||||||
|
client = w.httpsClient
|
||||||
|
} else {
|
||||||
|
client = w.httpClient
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发送HEAD请求,最小化网络开销
|
||||||
|
req, err := http.NewRequestWithContext(ctx, "HEAD", url, nil)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Header.Set("User-Agent", "fscan-web-detector/2.2")
|
||||||
|
req.Header.Set("Accept", "*/*")
|
||||||
|
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
// 检查错误类型,某些错误也表明是HTTP服务
|
||||||
|
return w.analyzeHTTPError(err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
// 分析HTTP响应
|
||||||
|
return w.analyzeHTTPResponse(resp, url)
|
||||||
|
}
|
||||||
|
|
||||||
|
// analyzeHTTPError 分析HTTP错误,判断是否表明存在HTTP服务
|
||||||
|
func (w *WebPortDetector) analyzeHTTPError(err error) bool {
|
||||||
|
errStr := strings.ToLower(err.Error())
|
||||||
|
|
||||||
|
// 先检查明确的非Web服务错误
|
||||||
|
nonWebErrors := []string{
|
||||||
|
"connection refused",
|
||||||
|
"no such host",
|
||||||
|
"network unreachable",
|
||||||
|
"timeout",
|
||||||
|
"deadline exceeded",
|
||||||
|
"connection reset",
|
||||||
|
"eof",
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, nonWebErr := range nonWebErrors {
|
||||||
|
if strings.Contains(errStr, nonWebErr) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 这些错误表明连接到了HTTP服务器,只是协议或其他问题
|
||||||
|
webIndicators := []string{
|
||||||
|
"malformed http response",
|
||||||
|
"unexpected http response",
|
||||||
|
"ssl handshake",
|
||||||
|
"certificate",
|
||||||
|
"tls",
|
||||||
|
"bad request",
|
||||||
|
"method not allowed",
|
||||||
|
"server gave http response",
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, indicator := range webIndicators {
|
||||||
|
if strings.Contains(errStr, indicator) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// analyzeHTTPResponse 分析HTTP响应,判断是否为Web服务
|
||||||
|
func (w *WebPortDetector) analyzeHTTPResponse(resp *http.Response, url string) bool {
|
||||||
|
// 任何HTTP状态码都表明这是Web服务
|
||||||
|
if resp.StatusCode > 0 {
|
||||||
|
// 分析响应头获取更多信息
|
||||||
|
serverHeader := resp.Header.Get("Server")
|
||||||
|
contentType := resp.Header.Get("Content-Type")
|
||||||
|
|
||||||
|
// 记录检测到的Web服务器信息
|
||||||
|
if serverHeader != "" {
|
||||||
|
common.LogDebug(fmt.Sprintf("检测到Web服务器: %s (Server: %s)", url, serverHeader))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 特殊处理:某些非Web服务也会返回HTTP响应
|
||||||
|
if w.isNonWebHTTPService(serverHeader, contentType) {
|
||||||
|
common.LogDebug(fmt.Sprintf("端口返回HTTP响应但可能不是Web服务: %s", url))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// isNonWebHTTPService 判断是否为非Web的HTTP服务
|
||||||
|
func (w *WebPortDetector) isNonWebHTTPService(serverHeader, contentType string) bool {
|
||||||
|
// 某些服务使用HTTP协议但不是传统Web服务
|
||||||
|
nonWebServices := []string{
|
||||||
|
"docker",
|
||||||
|
"kubernetes",
|
||||||
|
"consul",
|
||||||
|
"etcd",
|
||||||
|
"vault",
|
||||||
|
"nomad",
|
||||||
|
}
|
||||||
|
|
||||||
|
serverLower := strings.ToLower(serverHeader)
|
||||||
|
for _, service := range nonWebServices {
|
||||||
|
if strings.Contains(serverLower, service) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetWebPortRange 获取可能的Web端口范围(用于高级扫描)
|
||||||
|
func (w *WebPortDetector) GetWebPortRange() []int {
|
||||||
|
// 返回扩展的Web端口列表,用于目标发现
|
||||||
|
var ports []int
|
||||||
|
for port := range w.commonWebPorts {
|
||||||
|
ports = append(ports, port)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加一些常见的自定义端口范围
|
||||||
|
customRanges := []int{
|
||||||
|
8090, 8091, 8092, 8093, 8094, 8095, 8096, 8097, 8098, 8099,
|
||||||
|
9001, 9002, 9003, 9004, 9005, 9006, 9007, 9008, 9009,
|
||||||
|
10000, 10001, 10002, 10003, 10004, 10005,
|
||||||
|
}
|
||||||
|
|
||||||
|
ports = append(ports, customRanges...)
|
||||||
|
return ports
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsWebPortByPattern 基于端口模式判断是否可能是Web端口
|
||||||
|
func (w *WebPortDetector) IsWebPortByPattern(port int) bool {
|
||||||
|
portStr := strconv.Itoa(port)
|
||||||
|
|
||||||
|
// Web端口的常见模式
|
||||||
|
webPatterns := []*regexp.Regexp{
|
||||||
|
regexp.MustCompile(`^80\d{2}$`), // 80xx
|
||||||
|
regexp.MustCompile(`^90\d{2}$`), // 90xx
|
||||||
|
regexp.MustCompile(`^300\d$`), // 300x
|
||||||
|
regexp.MustCompile(`^[3-9]000$`), // x000
|
||||||
|
regexp.MustCompile(`^1[0-9]000$`), // 1x000
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, pattern := range webPatterns {
|
||||||
|
if pattern.MatchString(portStr) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user