mirror of https://github.com/daffainfo/nuclei.git
commit
952058c202
|
@ -28,6 +28,7 @@ type Options struct {
|
||||||
CustomHeaders requests.CustomHeaders // Custom global headers
|
CustomHeaders requests.CustomHeaders // Custom global headers
|
||||||
UpdateTemplates bool // UpdateTemplates updates the templates installed at startup
|
UpdateTemplates bool // UpdateTemplates updates the templates installed at startup
|
||||||
TemplatesDirectory string // TemplatesDirectory is the directory to use for storing templates
|
TemplatesDirectory string // TemplatesDirectory is the directory to use for storing templates
|
||||||
|
JSON bool // JSON writes json output to files
|
||||||
|
|
||||||
Stdin bool // Stdin specifies whether stdin input was given to the process
|
Stdin bool // Stdin specifies whether stdin input was given to the process
|
||||||
}
|
}
|
||||||
|
@ -53,6 +54,7 @@ func ParseOptions() *Options {
|
||||||
flag.BoolVar(&options.Debug, "debug", false, "Allow debugging of request/responses")
|
flag.BoolVar(&options.Debug, "debug", false, "Allow debugging of request/responses")
|
||||||
flag.BoolVar(&options.UpdateTemplates, "update-templates", false, "Update Templates updates the installed templates (optional)")
|
flag.BoolVar(&options.UpdateTemplates, "update-templates", false, "Update Templates updates the installed templates (optional)")
|
||||||
flag.StringVar(&options.TemplatesDirectory, "templates-directory", "", "Directory to use for storing nuclei-templates")
|
flag.StringVar(&options.TemplatesDirectory, "templates-directory", "", "Directory to use for storing nuclei-templates")
|
||||||
|
flag.BoolVar(&options.JSON, "json", false, "Write json output to files")
|
||||||
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
|
|
|
@ -253,6 +253,7 @@ func (r *Runner) processTemplateWithList(template *templates.Template, request i
|
||||||
Template: template,
|
Template: template,
|
||||||
DNSRequest: value,
|
DNSRequest: value,
|
||||||
Writer: writer,
|
Writer: writer,
|
||||||
|
JSON: r.options.JSON,
|
||||||
})
|
})
|
||||||
case *requests.HTTPRequest:
|
case *requests.HTTPRequest:
|
||||||
httpExecutor, err = executor.NewHTTPExecutor(&executor.HTTPOptions{
|
httpExecutor, err = executor.NewHTTPExecutor(&executor.HTTPOptions{
|
||||||
|
@ -265,6 +266,7 @@ func (r *Runner) processTemplateWithList(template *templates.Template, request i
|
||||||
ProxyURL: r.options.ProxyURL,
|
ProxyURL: r.options.ProxyURL,
|
||||||
ProxySocksURL: r.options.ProxySocksURL,
|
ProxySocksURL: r.options.ProxySocksURL,
|
||||||
CustomHeaders: r.options.CustomHeaders,
|
CustomHeaders: r.options.CustomHeaders,
|
||||||
|
JSON: r.options.JSON,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -30,6 +30,7 @@ import (
|
||||||
type HTTPExecutor struct {
|
type HTTPExecutor struct {
|
||||||
debug bool
|
debug bool
|
||||||
results uint32
|
results uint32
|
||||||
|
jsonOutput bool
|
||||||
httpClient *retryablehttp.Client
|
httpClient *retryablehttp.Client
|
||||||
template *templates.Template
|
template *templates.Template
|
||||||
httpRequest *requests.HTTPRequest
|
httpRequest *requests.HTTPRequest
|
||||||
|
@ -48,6 +49,7 @@ type HTTPOptions struct {
|
||||||
ProxyURL string
|
ProxyURL string
|
||||||
ProxySocksURL string
|
ProxySocksURL string
|
||||||
Debug bool
|
Debug bool
|
||||||
|
JSON bool
|
||||||
CustomHeaders requests.CustomHeaders
|
CustomHeaders requests.CustomHeaders
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,6 +72,7 @@ func NewHTTPExecutor(options *HTTPOptions) (*HTTPExecutor, error) {
|
||||||
|
|
||||||
executer := &HTTPExecutor{
|
executer := &HTTPExecutor{
|
||||||
debug: options.Debug,
|
debug: options.Debug,
|
||||||
|
jsonOutput: options.JSON,
|
||||||
results: 0,
|
results: 0,
|
||||||
httpClient: client,
|
httpClient: client,
|
||||||
template: options.Template,
|
template: options.Template,
|
||||||
|
|
|
@ -19,6 +19,7 @@ import (
|
||||||
// for a template.
|
// for a template.
|
||||||
type DNSExecutor struct {
|
type DNSExecutor struct {
|
||||||
debug bool
|
debug bool
|
||||||
|
jsonOutput bool
|
||||||
results uint32
|
results uint32
|
||||||
dnsClient *retryabledns.Client
|
dnsClient *retryabledns.Client
|
||||||
template *templates.Template
|
template *templates.Template
|
||||||
|
@ -38,6 +39,7 @@ var DefaultResolvers = []string{
|
||||||
// DNSOptions contains configuration options for the DNS executor.
|
// DNSOptions contains configuration options for the DNS executor.
|
||||||
type DNSOptions struct {
|
type DNSOptions struct {
|
||||||
Debug bool
|
Debug bool
|
||||||
|
JSON bool
|
||||||
Template *templates.Template
|
Template *templates.Template
|
||||||
DNSRequest *requests.DNSRequest
|
DNSRequest *requests.DNSRequest
|
||||||
Writer *bufio.Writer
|
Writer *bufio.Writer
|
||||||
|
@ -50,6 +52,7 @@ func NewDNSExecutor(options *DNSOptions) *DNSExecutor {
|
||||||
|
|
||||||
executer := &DNSExecutor{
|
executer := &DNSExecutor{
|
||||||
debug: options.Debug,
|
debug: options.Debug,
|
||||||
|
jsonOutput: options.JSON,
|
||||||
results: 0,
|
results: 0,
|
||||||
dnsClient: dnsClient,
|
dnsClient: dnsClient,
|
||||||
template: options.Template,
|
template: options.Template,
|
||||||
|
|
|
@ -6,6 +6,16 @@ import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type jsonOutput struct {
|
||||||
|
Template string `json:"template"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
Matched string `json:"matched"`
|
||||||
|
MatcherName string `json:"matcher_name,omitempty"`
|
||||||
|
ExtractedResults []string `json:"extracted_results,omitempty"`
|
||||||
|
Severity string `json:"severity"`
|
||||||
|
Author string `json:"author"`
|
||||||
|
}
|
||||||
|
|
||||||
// unsafeToString converts byte slice to string with zero allocations
|
// unsafeToString converts byte slice to string with zero allocations
|
||||||
func unsafeToString(bs []byte) string {
|
func unsafeToString(bs []byte) string {
|
||||||
return *(*string)(unsafe.Pointer(&bs))
|
return *(*string)(unsafe.Pointer(&bs))
|
||||||
|
|
|
@ -3,12 +3,43 @@ package executor
|
||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
jsoniter "github.com/json-iterator/go"
|
||||||
"github.com/projectdiscovery/gologger"
|
"github.com/projectdiscovery/gologger"
|
||||||
"github.com/projectdiscovery/nuclei/pkg/matchers"
|
"github.com/projectdiscovery/nuclei/pkg/matchers"
|
||||||
)
|
)
|
||||||
|
|
||||||
// writeOutputDNS writes dns output to streams
|
// writeOutputDNS writes dns output to streams
|
||||||
func (e *DNSExecutor) writeOutputDNS(domain string, matcher *matchers.Matcher, extractorResults []string) {
|
func (e *DNSExecutor) writeOutputDNS(domain string, matcher *matchers.Matcher, extractorResults []string) {
|
||||||
|
if e.jsonOutput {
|
||||||
|
output := jsonOutput{
|
||||||
|
Template: e.template.ID,
|
||||||
|
Type: "dns",
|
||||||
|
Matched: domain,
|
||||||
|
Severity: e.template.Info.Severity,
|
||||||
|
Author: e.template.Info.Author,
|
||||||
|
}
|
||||||
|
if matcher != nil && len(matcher.Name) > 0 {
|
||||||
|
output.MatcherName = matcher.Name
|
||||||
|
}
|
||||||
|
if len(extractorResults) > 0 {
|
||||||
|
output.ExtractedResults = extractorResults
|
||||||
|
}
|
||||||
|
data, err := jsoniter.Marshal(output)
|
||||||
|
if err != nil {
|
||||||
|
gologger.Warningf("Could not marshal json output: %s\n", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
gologger.Silentf("%s", string(data))
|
||||||
|
|
||||||
|
if e.writer != nil {
|
||||||
|
e.outputMutex.Lock()
|
||||||
|
e.writer.Write(data)
|
||||||
|
e.writer.WriteRune('\n')
|
||||||
|
e.outputMutex.Unlock()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
builder := &strings.Builder{}
|
builder := &strings.Builder{}
|
||||||
builder.WriteRune('[')
|
builder.WriteRune('[')
|
||||||
builder.WriteString(e.template.ID)
|
builder.WriteString(e.template.ID)
|
||||||
|
|
|
@ -3,6 +3,7 @@ package executor
|
||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
jsoniter "github.com/json-iterator/go"
|
||||||
"github.com/projectdiscovery/gologger"
|
"github.com/projectdiscovery/gologger"
|
||||||
"github.com/projectdiscovery/nuclei/pkg/matchers"
|
"github.com/projectdiscovery/nuclei/pkg/matchers"
|
||||||
"github.com/projectdiscovery/nuclei/pkg/requests"
|
"github.com/projectdiscovery/nuclei/pkg/requests"
|
||||||
|
@ -10,6 +11,38 @@ import (
|
||||||
|
|
||||||
// writeOutputHTTP writes http output to streams
|
// writeOutputHTTP writes http output to streams
|
||||||
func (e *HTTPExecutor) writeOutputHTTP(req *requests.CompiledHTTP, matcher *matchers.Matcher, extractorResults []string) {
|
func (e *HTTPExecutor) writeOutputHTTP(req *requests.CompiledHTTP, matcher *matchers.Matcher, extractorResults []string) {
|
||||||
|
URL := req.Request.URL.String()
|
||||||
|
|
||||||
|
if e.jsonOutput {
|
||||||
|
output := jsonOutput{
|
||||||
|
Template: e.template.ID,
|
||||||
|
Type: "http",
|
||||||
|
Matched: URL,
|
||||||
|
Severity: e.template.Info.Severity,
|
||||||
|
Author: e.template.Info.Author,
|
||||||
|
}
|
||||||
|
if matcher != nil && len(matcher.Name) > 0 {
|
||||||
|
output.MatcherName = matcher.Name
|
||||||
|
}
|
||||||
|
if len(extractorResults) > 0 {
|
||||||
|
output.ExtractedResults = extractorResults
|
||||||
|
}
|
||||||
|
data, err := jsoniter.Marshal(output)
|
||||||
|
if err != nil {
|
||||||
|
gologger.Warningf("Could not marshal json output: %s\n", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
gologger.Silentf("%s", string(data))
|
||||||
|
|
||||||
|
if e.writer != nil {
|
||||||
|
e.outputMutex.Lock()
|
||||||
|
e.writer.Write(data)
|
||||||
|
e.writer.WriteRune('\n')
|
||||||
|
e.outputMutex.Unlock()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
builder := &strings.Builder{}
|
builder := &strings.Builder{}
|
||||||
|
|
||||||
builder.WriteRune('[')
|
builder.WriteRune('[')
|
||||||
|
@ -21,7 +54,6 @@ func (e *HTTPExecutor) writeOutputHTTP(req *requests.CompiledHTTP, matcher *matc
|
||||||
builder.WriteString("] [http] ")
|
builder.WriteString("] [http] ")
|
||||||
|
|
||||||
// Escape the URL by replacing all % with %%
|
// Escape the URL by replacing all % with %%
|
||||||
URL := req.Request.URL.String()
|
|
||||||
escapedURL := strings.Replace(URL, "%", "%%", -1)
|
escapedURL := strings.Replace(URL, "%", "%%", -1)
|
||||||
builder.WriteString(escapedURL)
|
builder.WriteString(escapedURL)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue