mirror of
https://github.com/SleepingBag945/dddd.git
synced 2025-06-07 21:46:39 +00:00
566 lines
17 KiB
Go
Executable File
566 lines
17 KiB
Go
Executable File
package callnuclei
|
||
|
||
import (
|
||
"fmt"
|
||
"github.com/projectdiscovery/nuclei/v3/pkg/output"
|
||
"os"
|
||
"os/signal"
|
||
"runtime"
|
||
"runtime/pprof"
|
||
"time"
|
||
|
||
"github.com/projectdiscovery/goflags"
|
||
"github.com/projectdiscovery/gologger"
|
||
"github.com/projectdiscovery/gologger/levels"
|
||
"github.com/projectdiscovery/nuclei/v3/pkg/catalog/config"
|
||
"github.com/projectdiscovery/nuclei/v3/pkg/exportrunner"
|
||
"github.com/projectdiscovery/nuclei/v3/pkg/operators/common/dsl"
|
||
"github.com/projectdiscovery/nuclei/v3/pkg/types"
|
||
"github.com/projectdiscovery/nuclei/v3/pkg/utils/monitor"
|
||
errorutil "github.com/projectdiscovery/utils/errors"
|
||
fileutil "github.com/projectdiscovery/utils/file"
|
||
)
|
||
|
||
var (
|
||
cfgFile string
|
||
memProfile string // optional profile file path
|
||
options = &types.Options{}
|
||
)
|
||
|
||
func CallNuclei(TargetAndPocsName map[string][]string,
|
||
proxy string,
|
||
callBack func(result output.ResultEvent),
|
||
nameForSearch string,
|
||
NoInteractsh bool) []output.ResultEvent {
|
||
|
||
// 设置结果回调
|
||
output.AddResultCallback = callBack
|
||
if err := exportrunner.ExportRunnerConfigureOptions(); err != nil {
|
||
gologger.Fatal().Msgf("Could not initialize options: %s\n", err)
|
||
}
|
||
|
||
readConfig(TargetAndPocsName, proxy, nameForSearch, NoInteractsh)
|
||
// configPath, _ := flagSet.GetConfigFilePath()
|
||
|
||
if options.ListDslSignatures {
|
||
gologger.Info().Msgf("The available custom DSL functions are:")
|
||
fmt.Println(dsl.GetPrintableDslFunctionSignatures(options.NoColor))
|
||
return []output.ResultEvent{}
|
||
}
|
||
|
||
// Profiling related code
|
||
if memProfile != "" {
|
||
f, err := os.Create(memProfile)
|
||
if err != nil {
|
||
gologger.Fatal().Msgf("profile: could not create memory profile %q: %v", memProfile, err)
|
||
}
|
||
old := runtime.MemProfileRate
|
||
runtime.MemProfileRate = 4096
|
||
gologger.Print().Msgf("profile: memory profiling enabled (rate %d), %s", runtime.MemProfileRate, memProfile)
|
||
|
||
defer func() {
|
||
_ = pprof.Lookup("heap").WriteTo(f, 0)
|
||
f.Close()
|
||
runtime.MemProfileRate = old
|
||
gologger.Print().Msgf("profile: memory profiling disabled, %s", memProfile)
|
||
}()
|
||
}
|
||
|
||
exportrunner.ExportRunnerParseOptions(options)
|
||
|
||
if options.HangMonitor {
|
||
cancel := monitor.NewStackMonitor(10 * time.Second)
|
||
defer cancel()
|
||
}
|
||
|
||
nucleiRunner, err := exportrunner.ExportRunnerNew(options)
|
||
if err != nil {
|
||
gologger.Fatal().Msgf("Could not create runner: %s\n", err)
|
||
}
|
||
if nucleiRunner == nil {
|
||
return []output.ResultEvent{}
|
||
}
|
||
|
||
// Setup graceful exits
|
||
resumeFileName := types.DefaultResumeFilePath()
|
||
c := make(chan os.Signal, 1)
|
||
defer close(c)
|
||
signal.Notify(c, os.Interrupt)
|
||
go func() {
|
||
for range c {
|
||
gologger.Info().Msgf("CTRL+C pressed: Exiting\n")
|
||
nucleiRunner.Close()
|
||
os.Exit(1)
|
||
}
|
||
}()
|
||
|
||
if err := nucleiRunner.RunEnumeration(TargetAndPocsName); err != nil {
|
||
if options.Validate {
|
||
gologger.Fatal().Msgf("Could not validate templates: %s\n", err)
|
||
} else {
|
||
gologger.Fatal().Msgf("Could not run nuclei: %s\n", err)
|
||
}
|
||
}
|
||
nucleiRunner.Close()
|
||
// on successful execution remove the resume file in case it exists
|
||
if fileutil.FileExists(resumeFileName) {
|
||
os.Remove(resumeFileName)
|
||
}
|
||
return output.Results
|
||
}
|
||
|
||
func readConfig(TargetAndPocsName map[string][]string, proxy string, nameForSearch string, NoInteractsh bool) {
|
||
|
||
pwd, _ := os.Getwd()
|
||
|
||
// target URLs/hosts to scan
|
||
// 扫描目标
|
||
var targets []string
|
||
for k, _ := range TargetAndPocsName {
|
||
targets = append(targets, k)
|
||
}
|
||
options.Targets = targets
|
||
|
||
options.ExcludeTargets = []string{}
|
||
|
||
// path to file containing a list of target URLs/hosts to scan (one per line)
|
||
// 包含要扫描的目标URL/主机列表的文件路径(每行一个)
|
||
options.TargetsFilePath = ""
|
||
|
||
// resume scan using resume.cfg (clustering will be disabled)
|
||
// 使用resume.cfg恢复扫描(将禁用群集)
|
||
options.Resume = ""
|
||
|
||
// scan all the IP's associated with dns record
|
||
// 扫描与DNS记录相关联的所有IP
|
||
options.ScanAllIPs = false
|
||
|
||
// IP version to scan of hostname (4,6) - (default 4)
|
||
// 要扫描主机名的IP版本(4,6)-(默认为4)
|
||
options.IPVersion = nil
|
||
|
||
// run only new templates added in latest nuclei-templates release
|
||
// 仅运行在最新版本的nuclei-templates中添加的新模板
|
||
options.NewTemplates = false
|
||
|
||
// run new templates added in specific version
|
||
// 运行指定版本添加的模板
|
||
options.NewTemplatesWithVersion = nil
|
||
|
||
// automatic web scan using wappalyzer technology detection to tags mapping
|
||
// 使用wappalyzer技术检测tags,自动web扫描
|
||
// 这里被魔改了,根据提供的目标与Pocs的映射进行自动扫描
|
||
// 必须设置为true
|
||
options.AutomaticScan = true
|
||
|
||
// list of template or template directory to run (comma-separated, file)
|
||
// 要运行的模板或模板目录列表(逗号分隔,文件) -t 指定的模板目录
|
||
// 不嵌入可执行文件是为了方便增删poc。内网版本嵌入
|
||
options.Templates = []string{pwd + "/config/pocs/"}
|
||
|
||
// list of template urls to run (comma-separated, file)
|
||
// 要运行的模板url列表(逗号分隔,文件)
|
||
options.TemplateURLs = nil
|
||
|
||
// list of workflow or workflow directory to run (comma-separated, file)
|
||
// 要运行的工作流或工作流目录列表(逗号分隔,文件) -w 指定
|
||
options.Workflows = nil
|
||
|
||
// list of workflow urls to run (comma-separated, file)
|
||
// 要运行的工作流URL列表(逗号分隔,文件)
|
||
options.WorkflowURLs = nil
|
||
|
||
// validate the passed templates to nuclei
|
||
// 验证通过的模板
|
||
options.Validate = false
|
||
|
||
// disable strict syntax check on templates
|
||
// 禁用模板的严格检查
|
||
options.NoStrictSyntax = false
|
||
|
||
// displays the templates content
|
||
// 显示模板内容
|
||
options.TemplateDisplay = false
|
||
|
||
// list all available templates
|
||
// 列出所有可用的模板
|
||
options.TemplateList = false
|
||
|
||
// allowed domain list to load remote templates from
|
||
// 允许域列表从以下位置加载远程模板
|
||
options.RemoteTemplateDomainList = []string{"templates.nuclei.sh"}
|
||
|
||
// templates to run based on authors (comma-separated, file)
|
||
// 执行指定作者的模板(逗号分隔,文件)
|
||
options.Authors = nil
|
||
|
||
// templates to run based on tags (comma-separated, file)
|
||
// 执行有标记的模板子集(逗号分隔,文件)
|
||
options.Tags = nil
|
||
|
||
// templates to exclude based on tags (comma-separated, file)
|
||
// 排除执行带有标记的模板(逗号分隔,文件)
|
||
options.ExcludeTags = nil
|
||
|
||
// tags to be executed even if they are excluded either by default or configuration
|
||
// 执行默认或者配置排除的标记模板
|
||
options.IncludeTags = nil
|
||
|
||
// templates to run based on template ids (comma-separated, file)
|
||
// 执行指定ID的模板(逗号分隔,文件)
|
||
options.IncludeIds = nil
|
||
|
||
// templates to exclude based on template ids (comma-separated, file)
|
||
// 执行排除指定ID的模板(逗号分隔,文件)
|
||
options.ExcludeIds = nil
|
||
|
||
// templates to be executed even if they are excluded either by default or configuration
|
||
// 执行默认或配置中排除的模板
|
||
options.IncludeTemplates = nil
|
||
|
||
// template or template directory to exclude (comma-separated, file)
|
||
// 要排除的模板或者模板目录(逗号分隔,文件)
|
||
options.ExcludedTemplates = nil
|
||
|
||
// template matchers to exclude in result
|
||
// 在结果中排除指定模板
|
||
options.ExcludeMatchers = nil
|
||
|
||
// templates to run based on severity
|
||
// 根据严重程度运行模板,可候选的值有:info,low,medium,high,critical
|
||
options.Severities = nil
|
||
|
||
// templates to exclude based on severity
|
||
// 根据严重程度排除模板,可候选的值有:info,low,medium,high,critical
|
||
options.ExcludeSeverities = nil
|
||
|
||
// templates to run based on protocol type
|
||
// 根据协议运行模板,可候选的值有:dns, file, http, headless, network, workflow, ssl, websocket, whois
|
||
options.Protocols = nil
|
||
|
||
// templates to exclude based on protocol type
|
||
// 根据协议排除模板,可候选的值有:dns, file, http, headless, network, workflow, ssl, websocket, whois
|
||
options.ExcludeProtocols = nil
|
||
|
||
// templates to run based on expression condition
|
||
// 根据表达式运行模板
|
||
options.IncludeConditions = nil
|
||
|
||
// output file to write found issues/vulnerabilities
|
||
// 输出发现的问题到文件 -o 参数
|
||
options.Output = ""
|
||
|
||
// store all request/response passed through nuclei to output directory
|
||
// 是否将nuclei的所有请求和响应输出到目录
|
||
options.StoreResponse = false
|
||
|
||
// store all request/response passed through nuclei to custom directory
|
||
// 将nuclei的所有请求和响应输出到指定目录(默认:output)
|
||
options.StoreResponseDir = "output"
|
||
|
||
// display findings only
|
||
// 只显示结果
|
||
options.Silent = false
|
||
|
||
// disable output content coloring (ANSI escape codes)
|
||
// 禁用输出内容着色(ANSI转义码)
|
||
options.NoColor = false
|
||
|
||
// write output in JSON(Lines) format
|
||
// 输出为jsonL(ines)
|
||
options.JSONL = false
|
||
|
||
// include request/response pairs in the JSONL output (for findings only)
|
||
// 在JSON中输出对应的请求和相应(仅结果)
|
||
options.JSONRequests = false
|
||
|
||
// disable printing result metadata in cli output
|
||
// 不显示匹配的元数据
|
||
options.NoMeta = false
|
||
|
||
// enables printing timestamp in cli output
|
||
options.Timestamp = false
|
||
|
||
// nuclei reporting database (always use this to persist report data)
|
||
options.ReportingDB = ""
|
||
|
||
// display match failure status
|
||
// 显示匹配失败状态
|
||
options.MatcherStatus = false
|
||
|
||
// directory to export results in markdown format
|
||
// 以markdown导出结果
|
||
options.MarkdownExportDirectory = ""
|
||
|
||
// file to export results in SARIF format
|
||
// 以SARIF导出结果
|
||
options.SarifExport = ""
|
||
|
||
// file to export results in JSON format
|
||
options.JSONExport = ""
|
||
|
||
// 指定Nuclei的配置文件
|
||
cfgFile = ""
|
||
|
||
// 为HTTP模板启用重定向
|
||
options.FollowRedirects = false
|
||
|
||
// 在同一主机上重定向
|
||
options.FollowHostRedirects = false
|
||
|
||
// HTTP模板最大重定向次数(默认:10)
|
||
options.MaxRedirects = 10
|
||
|
||
// 为HTTP模板禁用重定向
|
||
options.DisableRedirects = false
|
||
|
||
// 指定Nuclei报告模板文件
|
||
options.ReportingConfig = ""
|
||
|
||
// 指定header、cookie,以header:value的方式(cli,文件)
|
||
options.CustomHeaders = nil
|
||
|
||
// 通过key=value指定var值
|
||
options.Vars = goflags.RuntimeMap{}
|
||
|
||
// 指定Nuclei的解析文件
|
||
options.ResolversFile = ""
|
||
|
||
// 当DNS错误时使用系统DNS
|
||
options.SystemResolvers = false
|
||
|
||
options.DisableClustering = false
|
||
|
||
// 启用被动扫描处理HTTP响应
|
||
options.OfflineHTTP = false
|
||
|
||
// 在模板中使用环境变量
|
||
options.EnvironmentVariables = false
|
||
|
||
// 用于对扫描的主机进行身份验证的客户端证书文件(PEM 编码)
|
||
options.ClientCertFile = ""
|
||
|
||
// 用于对扫描的主机进行身份验证的客户端密钥文件(PEM 编码)
|
||
options.ClientKeyFile = ""
|
||
|
||
// 用于对扫描的主机进行身份验证的客户端证书颁发机构文件(PEM 编码)
|
||
options.ClientCAFile = ""
|
||
|
||
// 显示文件模板的匹配值,只适用于提取器
|
||
options.ShowMatchLine = false
|
||
|
||
// 对ztls自动退回到tls13
|
||
options.ZTLS = false
|
||
|
||
// 指定tls sni的主机名(默认为输入的域名)
|
||
options.SNI = ""
|
||
|
||
options.AllowLocalFileAccess = false
|
||
|
||
options.RestrictLocalNetworkAccess = false
|
||
|
||
// 指定网卡
|
||
options.Interface = ""
|
||
|
||
// type of payload combinations to perform (batteringram,pitchfork,clusterbomb)
|
||
// 指定payload 组合方式
|
||
options.AttackType = ""
|
||
|
||
// 源IP
|
||
options.SourceIP = ""
|
||
|
||
// 最大读取响应大小(默认:10 * 1024 * 1024字节)
|
||
options.ResponseReadSize = 10 * 1024 * 1024
|
||
|
||
// 最大储存响应大小(默认:1 * 1024 * 1024字节)
|
||
options.ResponseSaveSize = 1 * 1024 * 1024
|
||
|
||
options.TlsImpersonate = false
|
||
|
||
// 使用interactsh反连检测平台(默认为oast.pro,oast.live,oast.site,oast.online,oast.fun,oast.me)
|
||
options.InteractshURL = ""
|
||
|
||
// 指定反连检测平台的身份凭证
|
||
options.InteractshToken = ""
|
||
|
||
// 指定保存在交互缓存中的请求数(默认:5000)
|
||
options.InteractionsCacheSize = 5000
|
||
|
||
// 从缓存中删除请求前等待的时间(默认为60秒)
|
||
options.InteractionsEviction = 60
|
||
|
||
// 每个轮询前等待时间(默认为5秒)
|
||
options.InteractionsPollDuration = 5
|
||
|
||
// 退出轮询前的等待时间(默认为5秒)
|
||
options.InteractionsCoolDownPeriod = 5
|
||
|
||
// 禁用反连检测平台,同时排除基于反连检测的模板
|
||
options.NoInteractsh = NoInteractsh
|
||
|
||
// overrides fuzzing type set in template (replace, prefix, postfix, infix)
|
||
// 覆盖模板中设置的模糊类型(替换、前缀、后缀、中缀)
|
||
options.FuzzingType = ""
|
||
|
||
// overrides fuzzing mode set in template (multiple, single)
|
||
// 覆盖模板中设置的模糊模式(多个、单个)
|
||
options.FuzzingMode = ""
|
||
|
||
// 启用网络空间搜索引擎
|
||
options.Uncover = false
|
||
// 网络空间搜索引擎请求
|
||
options.UncoverQuery = nil
|
||
// 网络空间搜索引擎 fofa/shodan
|
||
options.UncoverEngine = nil
|
||
// uncover fields to return (ip,port,host)
|
||
options.UncoverField = "ip:port"
|
||
// uncover results to return
|
||
options.UncoverLimit = 100
|
||
// delay between uncover query requests in seconds (0 to disable)
|
||
options.UncoverRateLimit = 60
|
||
|
||
// 每秒最大请求量(默认:150)
|
||
options.RateLimit = 150
|
||
// 每分钟最大请求量
|
||
options.RateLimitMinute = 0
|
||
// 每个模板最大并行检测数(默认:25)
|
||
options.BulkSize = 64
|
||
// 并行执行的最大模板数量(默认:25)
|
||
options.TemplateThreads = 64
|
||
// 每个模板并行运行的无头主机最大数量(默认:10)
|
||
options.HeadlessBulkSize = 10
|
||
// 并行指定无头主机最大数量(默认:10)
|
||
options.HeadlessTemplateThreads = 10
|
||
|
||
// 超时时间(默认为10秒)
|
||
options.Timeout = 12
|
||
// 重试次数(默认:1)设置2为降低糟糕网络环境的影响
|
||
options.Retries = 2
|
||
// 指定HTTP/HTTPS默认端口(例如:host:80,host:443)
|
||
options.LeaveDefaultPorts = false
|
||
// 某主机扫描失败次数,跳过该主机(默认:30)
|
||
options.MaxHostError = 50
|
||
// 将给定错误添加到最大主机错误监视列表(标准、文件)
|
||
options.TrackError = nil
|
||
// 关闭主机基于错误的跳过
|
||
options.NoHostErrors = false
|
||
// 使用项目文件夹避免多次发送同一请求
|
||
options.Project = false // 去重复,导致file missing
|
||
// 设置特定的项目文件夹
|
||
options.ProjectPath = os.TempDir()
|
||
// 得到一个结果后停止(或许会中断模板和工作流的逻辑)
|
||
options.StopAtFirstMatch = false
|
||
// 流模式 - 在不整理输入的情况下详细描述
|
||
options.Stream = false
|
||
// 扫描策略 auto/host-spray/template-spray
|
||
// options.ScanStrategy = "auto"
|
||
options.ScanStrategy = "auto"
|
||
// 输入读取超时时间(默认:3分钟)
|
||
options.InputReadTimeout = time.Duration(3 * time.Minute)
|
||
// 禁用httpx
|
||
options.DisableHTTPProbe = true
|
||
// 禁用标准输入
|
||
options.DisableStdin = false
|
||
|
||
// 启用需要无界面浏览器的模板
|
||
options.Headless = false
|
||
// 在无界面下超时秒数(默认:20)
|
||
options.PageTimeout = 20
|
||
// 在无界面浏览器运行模板时,显示浏览器
|
||
options.ShowBrowser = false
|
||
// 不使用Nuclei自带的浏览器,使用本地浏览器
|
||
options.UseInstalledChrome = false
|
||
// 展示无界面浏览器的操作
|
||
options.ShowActions = false
|
||
|
||
// 显示所有请求和响应
|
||
options.Debug = gologger.Audit
|
||
// 显示所有请求
|
||
options.DebugRequests = false
|
||
// 显示所有响应
|
||
options.DebugResponse = false
|
||
// 使用http/socks5代理(逗号分隔,文件)
|
||
if proxy == "" {
|
||
options.Proxy = nil
|
||
} else {
|
||
options.Proxy = []string{proxy}
|
||
}
|
||
// 代理所有请求
|
||
options.ProxyInternal = false
|
||
// 列出所有支持的DSL函数签名
|
||
options.ListDslSignatures = false
|
||
// 写入跟踪日志到文件
|
||
options.TraceLogFile = ""
|
||
// 写入错误日志到文件
|
||
options.ErrorLogFile = ""
|
||
// 启用Nuclei的监控
|
||
options.HangMonitor = false
|
||
// 显示详细信息
|
||
options.Verbose = false
|
||
// 将Nuclei的内存转储成文件
|
||
memProfile = ""
|
||
// 显示额外的详细信息
|
||
options.VerboseVerbose = false
|
||
// 启用pprof调试服务器
|
||
options.EnablePprof = false
|
||
// 运行诊断检查
|
||
options.HealthCheck = false
|
||
|
||
config.DefaultConfig.DisableUpdateCheck()
|
||
|
||
// 更新Nuclei模板到最新版
|
||
options.UpdateTemplates = false
|
||
// 覆盖安装模板
|
||
options.NewTemplatesDirectory = pwd + "/config/pocs/nuclei-templates/"
|
||
|
||
// 显示正在扫描的统计信息
|
||
options.EnableProgressBar = true
|
||
// 将统计信息以JSONL格式输出到文件
|
||
options.StatsJSON = false
|
||
// 显示统计信息更新的间隔秒数(默认:5)
|
||
options.StatsInterval = 20
|
||
// 显示Nuclei端口信息
|
||
options.Metrics = false
|
||
// 更改Nuclei默认端口(默认:9092)
|
||
options.MetricsPort = 9092
|
||
|
||
options.OmitTemplate = false
|
||
|
||
// network请求超时时间
|
||
options.DialerTimeout = 0
|
||
|
||
// network请求的keep-alive持续时间
|
||
options.DialerKeepAlive = 0
|
||
|
||
// 启用加载基于代码协议的模板
|
||
options.EnableCodeTemplates = false
|
||
|
||
// 将扫描结果上传到pdcp仪表板 敏感环境高危
|
||
options.EnableCloudUpload = false
|
||
|
||
options.SignTemplates = false
|
||
|
||
options.PocNameForSearch = nameForSearch
|
||
|
||
gologger.DefaultLogger.SetTimestamp(options.Timestamp, levels.LevelDebug)
|
||
|
||
cleanupOldResumeFiles()
|
||
}
|
||
|
||
// cleanupOldResumeFiles cleans up resume files older than 10 days.
|
||
func cleanupOldResumeFiles() {
|
||
root := config.DefaultConfig.GetConfigDir()
|
||
filter := fileutil.FileFilters{
|
||
OlderThan: 24 * time.Hour * 10, // cleanup on the 10th day
|
||
Prefix: "resume-",
|
||
}
|
||
_ = fileutil.DeleteFilesOlderThan(root, filter)
|
||
}
|
||
|
||
func init() {
|
||
// print stacktrace of errors in debug mode
|
||
if os.Getenv("DEBUG") != "" {
|
||
errorutil.ShowStackTrace = true
|
||
}
|
||
}
|