diff --git a/cmd/nuclei/main.go b/cmd/nuclei/main.go index a4ba02ddd3..c62245ce3d 100644 --- a/cmd/nuclei/main.go +++ b/cmd/nuclei/main.go @@ -236,6 +236,7 @@ on extensive configurability, massive extensibility and ease of use.`) flagSet.StringVarP(&options.TargetsFilePath, "list", "l", "", "path to file containing a list of target URLs/hosts to scan (one per line)"), flagSet.StringSliceVarP(&options.ExcludeTargets, "exclude-hosts", "eh", nil, "hosts to exclude to scan from the input list (ip, cidr, hostname)", goflags.FileCommaSeparatedStringSliceOptions), flagSet.StringVar(&options.Resume, "resume", "", "resume scan using resume.cfg (clustering will be disabled)"), + flagSet.BoolVarP(&options.SpecifyIP, "specify-ip", "ip", false, "scan the specified IP address (items provided as IP,URL)"), flagSet.BoolVarP(&options.ScanAllIPs, "scan-all-ips", "sa", false, "scan all the IP's associated with dns record"), flagSet.StringSliceVarP(&options.IPVersion, "ip-version", "iv", nil, "IP version to scan of hostname (4,6) - (default 4)", goflags.CommaSeparatedStringSliceOptions), ) diff --git a/pkg/input/provider/list/hmap.go b/pkg/input/provider/list/hmap.go index edf3729193..9dfe0d7791 100644 --- a/pkg/input/provider/list/hmap.go +++ b/pkg/input/provider/list/hmap.go @@ -72,6 +72,7 @@ func New(opts *Options) (*ListInputProvider, error) { input := &ListInputProvider{ hostMap: hm, ipOptions: &ipOptions{ + SpecifyIP: options.SpecifyIP, ScanAllIPs: options.ScanAllIPs, IPV4: sliceutil.Contains(options.IPVersion, "4"), IPV6: sliceutil.Contains(options.IPVersion, "6"), @@ -140,6 +141,18 @@ func (i *ListInputProvider) Iterate(callback func(value *contextargs.MetaInput) // Set normalizes and stores passed input values func (i *ListInputProvider) Set(value string) { + if i.ipOptions.SpecifyIP { + valueParsed := strings.SplitN(value, ",", 2) + if len(valueParsed) == 2 { + metaInput := contextargs.NewMetaInput() + metaInput.Input = strings.TrimSpace(valueParsed[1]) + metaInput.CustomIP = strings.TrimSpace(valueParsed[0]) + i.setItem(metaInput) + return + } + // if no comma, let's process the URL normally + } + URL := strings.TrimSpace(value) if URL == "" { return @@ -372,6 +385,18 @@ func (i *ListInputProvider) isExcluded(URL string) bool { } func (i *ListInputProvider) Del(value string) { + if i.ipOptions.SpecifyIP { + valueParsed := strings.SplitN(value, ",", 2) + if len(valueParsed) == 2 { + metaInput := contextargs.NewMetaInput() + metaInput.Input = strings.TrimSpace(valueParsed[1]) + metaInput.CustomIP = strings.TrimSpace(valueParsed[0]) + i.delItem(metaInput) + return + } + // if no comma, let's process the URL normally + } + URL := strings.TrimSpace(value) if URL == "" { return diff --git a/pkg/input/provider/list/utils.go b/pkg/input/provider/list/utils.go index 221b40a88f..31685330db 100644 --- a/pkg/input/provider/list/utils.go +++ b/pkg/input/provider/list/utils.go @@ -1,6 +1,7 @@ package list type ipOptions struct { + SpecifyIP bool ScanAllIPs bool IPV4 bool IPV6 bool diff --git a/pkg/types/types.go b/pkg/types/types.go index aa43683ecd..d703e0ba9f 100644 --- a/pkg/types/types.go +++ b/pkg/types/types.go @@ -321,6 +321,8 @@ type Options struct { UncoverLimit int // Uncover search delay UncoverRateLimit int + // Provide IP address with the URL, as IP,URL + SpecifyIP bool // ScanAllIPs associated to a dns record ScanAllIPs bool // IPVersion to scan (4,6)