mirror of
https://github.com/shadow1ng/fscan.git
synced 2026-09-23 03:31:53 +08:00
## 架构重构
- 全局变量消除,迁移至 Config/State 对象
- SMB 插件融合(smb/smb2/smbghost/smbinfo)
- 服务探测重构,实现 Nmap 风格 fallback 机制
- 输出系统重构,TXT 实时刷盘 + 双写机制
- i18n 框架升级至 go-i18n
## 性能优化
- 正则表达式预编译
- 内存优化 map[string]struct{}
- 并发指纹匹配
- SOCKS5 连接复用
- 滑动窗口调度 + 自适应线程池
## 新功能
- Web 管理界面
- 多格式 POC 适配(xray/afrog)
- 增强指纹库(3139条)
- Favicon hash 指纹识别
- 插件选择性编译(Build Tags)
- fscan-lab 靶场环境
- 默认端口扩展(62→133)
## 构建系统
- 添加 no_local tag 支持排除本地插件
- 多版本构建:fscan/fscan-nolocal/fscan-web
- CI 添加 snapshot 模式支持仅测试构建
## Bug 修复
- 修复 120+ 个问题,包括 RDP panic、批量扫描漏报、
JSON 输出格式、Redis 检测、Context 超时等
## 测试增强
- 单元测试覆盖率 74-100%
- 并发安全测试
- 集成测试(Web/端口/服务/SSH/ICMP)
192 lines
4.3 KiB
Go
192 lines
4.3 KiB
Go
package lib
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
)
|
|
|
|
// TestPocAdapterExample 演示多格式POC加载
|
|
func TestPocAdapterExample(t *testing.T) {
|
|
fmt.Println("\n========== 多格式 POC 适配器演示 ==========")
|
|
|
|
// 示例1: fscan原生格式
|
|
fscanYaml := `
|
|
name: poc-yaml-test-fscan
|
|
set:
|
|
rand: randomInt(10000, 99999)
|
|
rules:
|
|
- method: GET
|
|
path: /api/check?id={{rand}}
|
|
expression: |
|
|
response.status == 200 && response.body.bcontains(b"success")
|
|
detail:
|
|
author: fscan-dev
|
|
description: fscan原生格式示例
|
|
`
|
|
|
|
fmt.Println("1. 加载 fscan 原生格式 POC:")
|
|
fmt.Println(" YAML内容:", fscanYaml[:100], "...")
|
|
|
|
poc1, err := LoadUniversalPoc("test-fscan.yml", []byte(fscanYaml))
|
|
if err != nil {
|
|
t.Fatalf("加载失败: %v", err)
|
|
}
|
|
|
|
fmt.Printf(" ✓ 格式: %s\n", poc1.GetFormat())
|
|
fmt.Printf(" ✓ 名称: %s\n", poc1.GetName())
|
|
|
|
fscanPoc1, _ := poc1.ToFscanPoc()
|
|
fmt.Printf(" ✓ 规则数: %d\n", len(fscanPoc1.Rules))
|
|
fmt.Println()
|
|
|
|
// 示例2: Nuclei格式
|
|
nucleiYaml := `
|
|
id: test-nuclei-sqli
|
|
info:
|
|
name: SQL Injection Detection
|
|
author: pdteam
|
|
severity: high
|
|
description: Detects SQL injection vulnerabilities
|
|
reference:
|
|
- https://owasp.org/www-community/attacks/SQL_Injection
|
|
http:
|
|
- method: GET
|
|
path:
|
|
- "{{BaseURL}}/api/user?id=1'"
|
|
- "{{BaseURL}}/search?q=test'"
|
|
matchers:
|
|
- type: word
|
|
words:
|
|
- "SQL syntax"
|
|
- "mysql_fetch"
|
|
condition: or
|
|
- type: status
|
|
status:
|
|
- 500
|
|
`
|
|
|
|
fmt.Println("2. 加载 Nuclei 格式 POC:")
|
|
fmt.Println(" YAML内容:", nucleiYaml[:100], "...")
|
|
|
|
poc2, err := LoadUniversalPoc("test-nuclei.yaml", []byte(nucleiYaml))
|
|
if err != nil {
|
|
t.Fatalf("加载失败: %v", err)
|
|
}
|
|
|
|
fmt.Printf(" ✓ 格式: %s\n", poc2.GetFormat())
|
|
fmt.Printf(" ✓ 名称: %s\n", poc2.GetName())
|
|
|
|
fscanPoc2, _ := poc2.ToFscanPoc()
|
|
fmt.Printf(" ✓ 规则数: %d (Nuclei的2个path转为2个rule)\n", len(fscanPoc2.Rules))
|
|
fmt.Printf(" ✓ 第一条规则表达式: %s\n", fscanPoc2.Rules[0].Expression[:80]+"...")
|
|
fmt.Println()
|
|
|
|
// 示例3: 格式检测
|
|
fmt.Println("3. 自动格式检测:")
|
|
|
|
testCases := []struct {
|
|
name string
|
|
yaml string
|
|
format PocFormat
|
|
}{
|
|
{
|
|
"fscan格式",
|
|
`name: test
|
|
rules:
|
|
- method: GET`,
|
|
FormatFscan,
|
|
},
|
|
{
|
|
"Nuclei格式",
|
|
`id: test
|
|
info:
|
|
name: test`,
|
|
FormatNuclei,
|
|
},
|
|
{
|
|
"未知格式",
|
|
`unknown: field`,
|
|
FormatUnknown,
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
detected := DetectPocFormat([]byte(tc.yaml))
|
|
status := "✓"
|
|
if detected != tc.format {
|
|
status = "✗"
|
|
}
|
|
fmt.Printf(" %s %s: 检测为 %s\n", status, tc.name, detected)
|
|
}
|
|
|
|
fmt.Println("\n========== 演示结束 ==========")
|
|
}
|
|
|
|
// TestPocAdapterFeatures 展示适配器特性
|
|
func TestPocAdapterFeatures(t *testing.T) {
|
|
fmt.Println("\n========== POC 适配器特性展示 ==========")
|
|
|
|
nucleiYaml := `
|
|
id: features-demo
|
|
info:
|
|
name: Feature Demo
|
|
author: test
|
|
severity: medium
|
|
http:
|
|
- method: POST
|
|
path:
|
|
- "{{BaseURL}}/login"
|
|
headers:
|
|
Content-Type: application/json
|
|
body: '{"user":"admin","pass":"test"}'
|
|
matchers:
|
|
- type: word
|
|
words:
|
|
- "success"
|
|
- "authenticated"
|
|
condition: and
|
|
- type: status
|
|
status:
|
|
- 200
|
|
- 302
|
|
matchers-condition: and
|
|
`
|
|
|
|
fmt.Println("特性1: Nuclei matcher 转换")
|
|
poc, _ := LoadUniversalPoc("demo.yaml", []byte(nucleiYaml))
|
|
fscanPoc, _ := poc.ToFscanPoc()
|
|
|
|
fmt.Printf(" 原始: Nuclei format with 2 matchers\n")
|
|
fmt.Printf(" 转换: fscan expression\n")
|
|
fmt.Printf(" 结果: %s\n", fscanPoc.Rules[0].Expression)
|
|
fmt.Println()
|
|
|
|
fmt.Println("特性2: 多 path 处理")
|
|
multiPathYaml := `
|
|
id: multi-path-demo
|
|
info:
|
|
name: Multi Path Demo
|
|
http:
|
|
- method: GET
|
|
path:
|
|
- "{{BaseURL}}/admin"
|
|
- "{{BaseURL}}/dashboard"
|
|
- "{{BaseURL}}/config"
|
|
matchers:
|
|
- type: status
|
|
status:
|
|
- 200
|
|
`
|
|
|
|
poc2, _ := LoadUniversalPoc("multi.yaml", []byte(multiPathYaml))
|
|
fscanPoc2, _ := poc2.ToFscanPoc()
|
|
|
|
fmt.Printf(" 原始: 3个 path\n")
|
|
fmt.Printf(" 转换: %d 个 rule\n", len(fscanPoc2.Rules))
|
|
for i, rule := range fscanPoc2.Rules {
|
|
fmt.Printf(" Rule %d: %s\n", i+1, rule.Path)
|
|
}
|
|
|
|
fmt.Println("\n========== 特性展示结束 ==========")
|
|
}
|