diff --git a/Common/Parse.go b/Common/Parse.go index eeb104f..ad8d2e3 100644 --- a/Common/Parse.go +++ b/Common/Parse.go @@ -272,6 +272,10 @@ func updateGlobalVariables(config *parsers.ParsedConfig, info *HostInfo) error { if len(config.Targets.URLs) > 0 { URLs = config.Targets.URLs + // 如果info.Url为空且只有一个URL,将其设置到info.Url + if info.Url == "" && len(config.Targets.URLs) == 1 { + info.Url = config.Targets.URLs[0] + } } if len(config.Targets.Ports) > 0 { diff --git a/Common/parsers/constants.go b/Common/parsers/constants.go index b99b172..42f1e4a 100644 --- a/Common/parsers/constants.go +++ b/Common/parsers/constants.go @@ -140,7 +140,7 @@ const ( // 正则表达式模式 IPv4RegexPattern = `^(\d{1,3}\.){3}\d{1,3}$` PortRangeRegexPattern = `^(\d+)(-(\d+))?$` - URLValidationRegexPattern = `^https?://[^\s/$.?#].[^\s]*$` + URLValidationRegexPattern = `^https?://[^\s]+$` DomainRegexPattern = `^[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?)*$` CookieRegexPattern = `^[^=;\s]+(=[^;\s]*)?(\s*;\s*[^=;\s]+(=[^;\s]*)?)*$` diff --git a/core/BaseScanStrategy.go b/core/BaseScanStrategy.go index 96d534b..f5183c9 100644 --- a/core/BaseScanStrategy.go +++ b/core/BaseScanStrategy.go @@ -164,8 +164,13 @@ func (b *BaseScanStrategy) IsPluginApplicableByName(pluginName string, targetHos return false } - // 对于Web插件,即使没有端口限制,也必须通过智能检测才能执行 + // 对于Web插件的特殊处理 if metadata.Category == "web" { + // Web扫描策略下直接允许Web插件执行(用户明确指定了Web目标) + if b.filterType == FilterWeb { + return true + } + // 其他策略下必须通过智能检测才能执行 return false } diff --git a/core/WebScanner.go b/core/WebScanner.go index 97f9932..dc0faef 100644 --- a/core/WebScanner.go +++ b/core/WebScanner.go @@ -1,6 +1,8 @@ package core import ( + "fmt" + "net/url" "github.com/shadow1ng/fscan/common" "github.com/shadow1ng/fscan/common/i18n" "strings" @@ -54,16 +56,55 @@ func (s *WebScanStrategy) Execute(info common.HostInfo, ch *chan struct{}, wg *s func (s *WebScanStrategy) PrepareTargets(baseInfo common.HostInfo) []common.HostInfo { var targetInfos []common.HostInfo - for _, url := range common.URLs { - urlInfo := baseInfo - // 确保URL包含协议头 - if !strings.HasPrefix(url, "http://") && !strings.HasPrefix(url, "https://") { - url = "http://" + url + // 首先从common.URLs获取目标 + for _, urlStr := range common.URLs { + urlInfo := s.createTargetFromURL(baseInfo, urlStr) + if urlInfo != nil { + targetInfos = append(targetInfos, *urlInfo) + } + } + + // 如果common.URLs为空但baseInfo.Url有值,使用baseInfo.Url + if len(targetInfos) == 0 && baseInfo.Url != "" { + urlInfo := s.createTargetFromURL(baseInfo, baseInfo.Url) + if urlInfo != nil { + targetInfos = append(targetInfos, *urlInfo) } - urlInfo.Url = url - targetInfos = append(targetInfos, urlInfo) } return targetInfos } +// createTargetFromURL 从URL创建目标信息 +func (s *WebScanStrategy) createTargetFromURL(baseInfo common.HostInfo, urlStr string) *common.HostInfo { + // 确保URL包含协议头 + if !strings.HasPrefix(urlStr, "http://") && !strings.HasPrefix(urlStr, "https://") { + urlStr = "http://" + urlStr + } + + // 解析URL获取Host和Port信息 + parsedURL, err := url.Parse(urlStr) + if err != nil { + common.LogError(fmt.Sprintf("解析URL失败: %s - %v", urlStr, err)) + return nil + } + + urlInfo := baseInfo + urlInfo.Url = urlStr + urlInfo.Host = parsedURL.Hostname() + + // 设置端口 + port := parsedURL.Port() + if port == "" { + // 根据协议设置默认端口 + if parsedURL.Scheme == "https" { + port = "443" + } else { + port = "80" + } + } + urlInfo.Ports = port + + return &urlInfo +} +