package core import ( "fmt" "net/url" "github.com/shadow1ng/fscan/common" "github.com/shadow1ng/fscan/common/i18n" "strings" "sync" ) // WebScanStrategy Web扫描策略 type WebScanStrategy struct { *BaseScanStrategy } // NewWebScanStrategy 创建新的Web扫描策略 func NewWebScanStrategy() *WebScanStrategy { return &WebScanStrategy{ BaseScanStrategy: NewBaseScanStrategy("Web扫描", FilterWeb), } } // Name 返回策略名称 func (s *WebScanStrategy) Name() string { return i18n.GetText("scan_strategy_web_name") } // Description 返回策略描述 func (s *WebScanStrategy) Description() string { return i18n.GetText("scan_strategy_web_desc") } // Execute 执行Web扫描策略 func (s *WebScanStrategy) Execute(info common.HostInfo, ch *chan struct{}, wg *sync.WaitGroup) { // 输出扫描开始信息 s.LogScanStart() // 验证插件配置 if err := s.ValidateConfiguration(); err != nil { common.LogError(err.Error()) return } // 准备URL目标 targets := s.PrepareTargets(info) // 输出插件信息 s.LogPluginInfo() // 执行扫描任务 ExecuteScanTasks(targets, s, ch, wg) } // PrepareTargets 准备URL目标列表 func (s *WebScanStrategy) PrepareTargets(baseInfo common.HostInfo) []common.HostInfo { var targetInfos []common.HostInfo // 首先从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) } } 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 }