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 {
|
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
|
// 1. 快速路径:常见Web端口直接返回true
|
||||||
if w.IsCommonWebPort(port) {
|
if w.IsCommonWebPort(port) {
|
||||||
common.LogDebug(fmt.Sprintf("端口 %d 是常见Web端口,启用Web插件", 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()
|
w.cacheMutex.RUnlock()
|
||||||
|
|
||||||
// 3. 智能路径:对非常见端口进行HTTP协议探测
|
// 3. 回退路径:对非常见端口进行HTTP协议探测(仅在服务指纹识别失败时使用)
|
||||||
common.LogDebug(fmt.Sprintf("对端口 %d 进行智能Web检测", port))
|
common.LogDebug(fmt.Sprintf("端口 %d 未通过服务指纹识别为Web服务,回退到HTTP协议探测", port))
|
||||||
result := w.detectHTTPService(host, port)
|
result := w.detectHTTPService(host, port)
|
||||||
|
|
||||||
// 4. 缓存结果
|
// 4. 缓存结果
|
||||||
@ -129,7 +136,7 @@ func (w *WebPortDetector) IsWebService(host string, port int) bool {
|
|||||||
w.detectionCache[cacheKey] = result
|
w.detectionCache[cacheKey] = result
|
||||||
w.cacheMutex.Unlock()
|
w.cacheMutex.Unlock()
|
||||||
|
|
||||||
common.LogDebug(fmt.Sprintf("端口 %d 智能检测结果: %v", port, result))
|
common.LogDebug(fmt.Sprintf("端口 %d HTTP协议探测结果: %v", port, result))
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -420,4 +427,106 @@ func min(a, b int) int {
|
|||||||
return b
|
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