mirror of
https://github.com/shadow1ng/fscan.git
synced 2025-09-14 05:56:46 +08:00
refactor: 优化Web服务检测逻辑,优先使用指纹识别结果
功能优化: - IsWebService现在优先检查服务指纹识别的结果 - 避免对已识别为Web服务的端口进行重复HTTP探测 - 改进调试日志,区分不同检测路径 Web服务识别逻辑: 1. 优先级1: 检查指纹识别缓存 2. 优先级2: 常见Web端口快速路径 3. 优先级3: 检测缓存 4. 优先级4: HTTP协议探测(回退机制) 新增函数: - IsWebServiceByFingerprint: 基于nmap指纹智能判断Web服务 - MarkAsWebService: 缓存已识别的Web服务 - GetWebServiceInfo: 获取Web服务信息 - IsMarkedWebService: 检查端口是否已标记为Web服务 效果: - 减少重复HTTP探测请求 - 提高Web服务识别准确性 - 统一服务识别和Web检测架构
This commit is contained in:
parent
82ab894bcf
commit
1ff44d1ebc
@ -102,8 +102,15 @@ func newWebPortDetector() *WebPortDetector {
|
||||
}
|
||||
}
|
||||
|
||||
// IsWebService 智能检测端口是否运行Web服务
|
||||
// IsWebService 智能检测端口是否运行Web服务(优化版:优先使用指纹识别结果)
|
||||
func (w *WebPortDetector) IsWebService(host string, port int) bool {
|
||||
// 0. 最优先路径:检查是否已通过服务指纹识别为Web服务
|
||||
if IsMarkedWebService(host, port) {
|
||||
serviceInfo, _ := GetWebServiceInfo(host, port)
|
||||
common.LogDebug(fmt.Sprintf("端口 %d 通过服务指纹已识别为Web服务: %s", port, serviceInfo.Name))
|
||||
return true
|
||||
}
|
||||
|
||||
// 1. 快速路径:常见Web端口直接返回true
|
||||
if w.IsCommonWebPort(port) {
|
||||
common.LogDebug(fmt.Sprintf("端口 %d 是常见Web端口,启用Web插件", port))
|
||||
@ -120,8 +127,8 @@ func (w *WebPortDetector) IsWebService(host string, port int) bool {
|
||||
}
|
||||
w.cacheMutex.RUnlock()
|
||||
|
||||
// 3. 智能路径:对非常见端口进行HTTP协议探测
|
||||
common.LogDebug(fmt.Sprintf("对端口 %d 进行智能Web检测", port))
|
||||
// 3. 回退路径:对非常见端口进行HTTP协议探测(仅在服务指纹识别失败时使用)
|
||||
common.LogDebug(fmt.Sprintf("端口 %d 未通过服务指纹识别为Web服务,回退到HTTP协议探测", port))
|
||||
result := w.detectHTTPService(host, port)
|
||||
|
||||
// 4. 缓存结果
|
||||
@ -129,7 +136,7 @@ func (w *WebPortDetector) IsWebService(host string, port int) bool {
|
||||
w.detectionCache[cacheKey] = result
|
||||
w.cacheMutex.Unlock()
|
||||
|
||||
common.LogDebug(fmt.Sprintf("端口 %d 智能检测结果: %v", port, result))
|
||||
common.LogDebug(fmt.Sprintf("端口 %d HTTP协议探测结果: %v", port, result))
|
||||
return result
|
||||
}
|
||||
|
||||
@ -420,4 +427,106 @@ func min(a, b int) int {
|
||||
return b
|
||||
}
|
||||
|
||||
// ===============================
|
||||
// 统一服务识别架构 - 基于指纹的Web服务判断
|
||||
// ===============================
|
||||
|
||||
// WebServiceCache Web服务缓存,用于存储已识别的Web服务信息
|
||||
var (
|
||||
webServiceCache = make(map[string]*ServiceInfo)
|
||||
webCacheMutex sync.RWMutex
|
||||
)
|
||||
|
||||
// IsWebServiceByFingerprint 基于服务指纹智能判断是否为Web服务
|
||||
func IsWebServiceByFingerprint(serviceInfo *ServiceInfo) bool {
|
||||
if serviceInfo == nil || serviceInfo.Name == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
serviceName := strings.ToLower(serviceInfo.Name)
|
||||
|
||||
// HTTP相关服务类型列表(基于nmap服务指纹库)
|
||||
webServices := []string{
|
||||
"http", "https", "http-proxy", "http-alt", "ssl/http",
|
||||
"http-mgmt", "httpd", "nginx", "apache", "iis",
|
||||
"tomcat", "jetty", "lighttpd", "caddy", "traefik",
|
||||
"websphere", "weblogic", "jboss", "wildfly",
|
||||
"nodejs", "express", "kestrel", "gunicorn", "uvicorn",
|
||||
"cherrypy", "tornado", "flask", "django", "rails",
|
||||
"php", "php-fpm", "asp", "aspx", "jsp", "servlet",
|
||||
"cgid", "cgi", "fcgi", "wsgi", "node.js",
|
||||
}
|
||||
|
||||
// 检查服务名称是否匹配Web服务
|
||||
for _, webService := range webServices {
|
||||
if serviceName == webService || strings.Contains(serviceName, webService) {
|
||||
common.LogDebug(fmt.Sprintf("基于指纹识别为Web服务: %s -> %s", serviceName, webService))
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// 检查Banner中的Web服务器特征
|
||||
if serviceInfo.Banner != "" {
|
||||
banner := strings.ToLower(serviceInfo.Banner)
|
||||
webBanners := []string{
|
||||
"server:", "apache", "nginx", "iis", "lighttpd",
|
||||
"caddy", "traefik", "tomcat", "jetty", "nodejs",
|
||||
"content-type:", "content-length:", "http/",
|
||||
"connection:", "keep-alive", "close",
|
||||
}
|
||||
|
||||
for _, webBanner := range webBanners {
|
||||
if strings.Contains(banner, webBanner) {
|
||||
common.LogDebug(fmt.Sprintf("基于Banner识别为Web服务: %s", webBanner))
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 检查额外信息中的Web特征
|
||||
if serviceInfo.Extras != nil {
|
||||
for key, value := range serviceInfo.Extras {
|
||||
keyLower := strings.ToLower(key)
|
||||
valueLower := strings.ToLower(value)
|
||||
|
||||
if keyLower == "info" && (strings.Contains(valueLower, "web") ||
|
||||
strings.Contains(valueLower, "http") || strings.Contains(valueLower, "html")) {
|
||||
common.LogDebug(fmt.Sprintf("基于Extras识别为Web服务: %s=%s", key, value))
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
common.LogDebug(fmt.Sprintf("指纹识别为非Web服务: %s", serviceName))
|
||||
return false
|
||||
}
|
||||
|
||||
// MarkAsWebService 标记端口为Web服务,用于后续Web插件调用
|
||||
func MarkAsWebService(host string, port int, serviceInfo *ServiceInfo) {
|
||||
cacheKey := fmt.Sprintf("%s:%d", host, port)
|
||||
|
||||
webCacheMutex.Lock()
|
||||
defer webCacheMutex.Unlock()
|
||||
|
||||
webServiceCache[cacheKey] = serviceInfo
|
||||
common.LogDebug(fmt.Sprintf("标记Web服务: %s [%s]", cacheKey, serviceInfo.Name))
|
||||
}
|
||||
|
||||
// GetWebServiceInfo 获取已标记的Web服务信息
|
||||
func GetWebServiceInfo(host string, port int) (*ServiceInfo, bool) {
|
||||
cacheKey := fmt.Sprintf("%s:%d", host, port)
|
||||
|
||||
webCacheMutex.RLock()
|
||||
defer webCacheMutex.RUnlock()
|
||||
|
||||
serviceInfo, exists := webServiceCache[cacheKey]
|
||||
return serviceInfo, exists
|
||||
}
|
||||
|
||||
// IsMarkedWebService 检查端口是否已被标记为Web服务
|
||||
func IsMarkedWebService(host string, port int) bool {
|
||||
_, exists := GetWebServiceInfo(host, port)
|
||||
return exists
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user