mirror of
https://github.com/shadow1ng/fscan.git
synced 2026-09-26 13:11:53 +08:00
fix web result protocol output (#577)
This commit is contained in:
+15
-14
@@ -196,13 +196,7 @@ func (w *TXTWriter) formatWebServiceLine(result *ScanResult) string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protocol := "http"
|
url := fmt.Sprintf("%s://%s", w.webProtocol(result, target), target)
|
||||||
service := w.getDetailStr(result, "service")
|
|
||||||
if service == "https" || strings.Contains(target, ":443") {
|
|
||||||
protocol = "https"
|
|
||||||
}
|
|
||||||
|
|
||||||
url := fmt.Sprintf("%s://%s", protocol, target)
|
|
||||||
title := w.getDetailStr(result, "title")
|
title := w.getDetailStr(result, "title")
|
||||||
status := w.getDetail(result, "status")
|
status := w.getDetail(result, "status")
|
||||||
server := w.getDetailStr(result, "server")
|
server := w.getDetailStr(result, "server")
|
||||||
@@ -375,13 +369,7 @@ func (w *TXTWriter) writeWebServices() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protocol := "http"
|
urls = append(urls, fmt.Sprintf("%s://%s", w.webProtocol(result, target), target))
|
||||||
service := w.getDetailStr(result, "service")
|
|
||||||
if service == "https" || strings.Contains(target, ":443") {
|
|
||||||
protocol = "https"
|
|
||||||
}
|
|
||||||
|
|
||||||
urls = append(urls, fmt.Sprintf("%s://%s", protocol, target))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(urls) == 0 {
|
if len(urls) == 0 {
|
||||||
@@ -410,6 +398,19 @@ func (w *TXTWriter) isWebService(result *ScanResult) bool {
|
|||||||
return service == "http" || service == "https"
|
return service == "http" || service == "https"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *TXTWriter) webProtocol(result *ScanResult, target string) string {
|
||||||
|
protocol := strings.ToLower(w.getDetailStr(result, "protocol"))
|
||||||
|
if protocol == "http" || protocol == "https" {
|
||||||
|
return protocol
|
||||||
|
}
|
||||||
|
|
||||||
|
service := strings.ToLower(w.getDetailStr(result, "service"))
|
||||||
|
if service == "https" || strings.Contains(target, ":443") {
|
||||||
|
return "https"
|
||||||
|
}
|
||||||
|
return "http"
|
||||||
|
}
|
||||||
|
|
||||||
// GetFormat 获取格式类型
|
// GetFormat 获取格式类型
|
||||||
func (w *TXTWriter) GetFormat() Format {
|
func (w *TXTWriter) GetFormat() Format {
|
||||||
return FormatTXT
|
return FormatTXT
|
||||||
|
|||||||
@@ -1230,6 +1230,44 @@ func TestCSVWriter_WebServiceFields(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTXTWriter_WebServiceProtocolFromDetails(t *testing.T) {
|
||||||
|
dir := createTestDir(t)
|
||||||
|
filePath := filepath.Join(dir, "test_web_protocol.txt")
|
||||||
|
|
||||||
|
writer, err := NewTXTWriter(filePath)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("创建TXTWriter失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
result := createTestResult(
|
||||||
|
TypeService,
|
||||||
|
"192.168.1.1:8443",
|
||||||
|
"web",
|
||||||
|
map[string]interface{}{
|
||||||
|
"plugin": "webtitle",
|
||||||
|
"is_web": true,
|
||||||
|
"port": 8443,
|
||||||
|
"protocol": "https",
|
||||||
|
"title": "Home",
|
||||||
|
"status": 200,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err := writer.Write(result); err != nil {
|
||||||
|
t.Fatalf("Write()失败: %v", err)
|
||||||
|
}
|
||||||
|
if err := writer.Close(); err != nil {
|
||||||
|
t.Fatalf("Close()失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
content := readFileContent(t, filePath)
|
||||||
|
if !strings.Contains(content, "https://192.168.1.1:8443") {
|
||||||
|
t.Fatalf("TXT输出缺少HTTPS URL,内容:\n%s", content)
|
||||||
|
}
|
||||||
|
if strings.Contains(content, "http://192.168.1.1:8443") {
|
||||||
|
t.Fatalf("TXT输出不应把HTTPS目标降级为HTTP,内容:\n%s", content)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TestJSONWriter_FlushAndFormat 测试JSON的Flush和GetFormat
|
// TestJSONWriter_FlushAndFormat 测试JSON的Flush和GetFormat
|
||||||
func TestJSONWriter_FlushAndFormat(t *testing.T) {
|
func TestJSONWriter_FlushAndFormat(t *testing.T) {
|
||||||
dir := createTestDir(t)
|
dir := createTestDir(t)
|
||||||
|
|||||||
+9
-1
@@ -3,6 +3,7 @@ package core
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -340,9 +341,16 @@ var resultSerializers = map[plugins.ResultType]resultSerializer{
|
|||||||
plugins.ResultTypeWeb: {
|
plugins.ResultTypeWeb: {
|
||||||
outputType: output.TypeService,
|
outputType: output.TypeService,
|
||||||
getStatus: func(_ *plugins.Result, _ *common.HostInfo) string { return "web" },
|
getStatus: func(_ *plugins.Result, _ *common.HostInfo) string { return "web" },
|
||||||
fillDetail: func(_ *plugins.Result, info *common.HostInfo, d map[string]interface{}) {
|
fillDetail: func(r *plugins.Result, info *common.HostInfo, d map[string]interface{}) {
|
||||||
d["is_web"] = true
|
d["is_web"] = true
|
||||||
d["port"] = info.Port
|
d["port"] = info.Port
|
||||||
|
if r.Output == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
d["url"] = r.Output
|
||||||
|
if parsed, err := url.Parse(r.Output); err == nil && (parsed.Scheme == "http" || parsed.Scheme == "https") {
|
||||||
|
d["protocol"] = parsed.Scheme
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/shadow1ng/fscan/common"
|
"github.com/shadow1ng/fscan/common"
|
||||||
|
"github.com/shadow1ng/fscan/plugins"
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -35,6 +36,26 @@ scanner_test.go - Scanner核心逻辑测试
|
|||||||
// 核心逻辑测试:策略选择
|
// 核心逻辑测试:策略选择
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
||||||
|
func TestWebResultSerializerPreservesDetectedProtocol(t *testing.T) {
|
||||||
|
serializer := resultSerializers[plugins.ResultTypeWeb]
|
||||||
|
details := map[string]interface{}{}
|
||||||
|
result := &plugins.Result{
|
||||||
|
Type: plugins.ResultTypeWeb,
|
||||||
|
Success: true,
|
||||||
|
Output: "https://192.168.1.1:8443",
|
||||||
|
}
|
||||||
|
info := &common.HostInfo{Host: "192.168.1.1", Port: 8443}
|
||||||
|
|
||||||
|
serializer.fillDetail(result, info, details)
|
||||||
|
|
||||||
|
if details["protocol"] != "https" {
|
||||||
|
t.Fatalf("protocol = %v, 期望 https", details["protocol"])
|
||||||
|
}
|
||||||
|
if details["url"] != "https://192.168.1.1:8443" {
|
||||||
|
t.Fatalf("url = %v, 期望检测出的URL", details["url"])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TestSelectStrategy 测试策略选择逻辑
|
// TestSelectStrategy 测试策略选择逻辑
|
||||||
func TestSelectStrategy(t *testing.T) {
|
func TestSelectStrategy(t *testing.T) {
|
||||||
// 保存原始配置
|
// 保存原始配置
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ func (p *WebTitlePlugin) Scan(ctx context.Context, info *common.HostInfo, sessio
|
|||||||
return &WebScanResult{
|
return &WebScanResult{
|
||||||
Type: plugins.ResultTypeWeb,
|
Type: plugins.ResultTypeWeb,
|
||||||
Success: true,
|
Success: true,
|
||||||
|
Output: url,
|
||||||
Title: title,
|
Title: title,
|
||||||
Status: status,
|
Status: status,
|
||||||
Server: server,
|
Server: server,
|
||||||
|
|||||||
Reference in New Issue
Block a user