mirror of https://github.com/daffainfo/nuclei.git
This reverts commit c125df4ef6
.
dev
parent
c125df4ef6
commit
89c6e76772
|
@ -162,8 +162,9 @@ DEBUG:
|
||||||
-debug show all requests and responses
|
-debug show all requests and responses
|
||||||
-debug-req show all sent requests
|
-debug-req show all sent requests
|
||||||
-debug-resp show all received responses
|
-debug-resp show all received responses
|
||||||
-proxy string List of HTTP(s)/SOCKS5 proxy servers or path to file containing such list
|
-proxy, -proxy-url string URL of the HTTP proxy server
|
||||||
-trace-log string file to write sent requests trace log
|
-proxy-socks-url string URL of the SOCKS proxy server
|
||||||
|
-tlog, -trace-log string file to write sent requests trace log
|
||||||
-version show nuclei version
|
-version show nuclei version
|
||||||
-v, -verbose show verbose output
|
-v, -verbose show verbose output
|
||||||
-vv display extra verbose information
|
-vv display extra verbose information
|
||||||
|
|
|
@ -121,7 +121,8 @@ nuclei -h
|
||||||
|templates-version|显示已安装的模板版本|nuclei -templates-version|
|
|templates-version|显示已安装的模板版本|nuclei -templates-version|
|
||||||
|v|显示发送请求的详细信息|nuclei -v|
|
|v|显示发送请求的详细信息|nuclei -v|
|
||||||
|version|显示nuclei的版本号|nuclei -version|
|
|version|显示nuclei的版本号|nuclei -version|
|
||||||
|proxy|输入代理地址|nuclei -proxy ./proxy.txt|
|
|proxy-url|输入代理地址|nuclei -proxy-url hxxp://127.0.0.1:8080|
|
||||||
|
|proxy-socks-url|输入socks代理地址|nuclei -proxy-socks-url socks5://127.0.0.1:8080|
|
||||||
|random-agent|使用随机的UA|nuclei -random-agent|
|
|random-agent|使用随机的UA|nuclei -random-agent|
|
||||||
|H|自定义请求头|nuclei -H “x-bug-bounty:hacker”|
|
|H|自定义请求头|nuclei -H “x-bug-bounty:hacker”|
|
||||||
|
|
||||||
|
|
|
@ -134,9 +134,11 @@ on extensive configurability, massive extensibility and ease of use.`)
|
||||||
flagSet.BoolVar(&options.DebugRequests, "debug-req", false, "show all sent requests"),
|
flagSet.BoolVar(&options.DebugRequests, "debug-req", false, "show all sent requests"),
|
||||||
flagSet.BoolVar(&options.DebugResponse, "debug-resp", false, "show all received responses"),
|
flagSet.BoolVar(&options.DebugResponse, "debug-resp", false, "show all received responses"),
|
||||||
|
|
||||||
/* TODO should auto-set the HTTP_PROXY variable for the process? */
|
/* TODO why the separation? http://proxy:port vs socks5://proxy:port etc
|
||||||
flagSet.NormalizedStringSliceVarP(&options.Proxy, "proxy", "p", []string{}, "List of HTTP(s)/SOCKS5 proxy servers or path to file containing such list"),
|
TODO should auto-set the HTTP_PROXY variable for the process? */
|
||||||
flagSet.StringVar(&options.TraceLogFile, "trace-log", "", "file to write sent requests trace log"),
|
flagSet.StringVarP(&options.ProxyURL, "proxy-url", "proxy", "", "URL of the HTTP proxy server"),
|
||||||
|
flagSet.StringVar(&options.ProxySocksURL, "proxy-socks-url", "", "URL of the SOCKS proxy server"),
|
||||||
|
flagSet.StringVarP(&options.TraceLogFile, "trace-log", "tlog", "", "file to write sent requests trace log"),
|
||||||
flagSet.BoolVar(&options.Version, "version", false, "show nuclei version"),
|
flagSet.BoolVar(&options.Version, "version", false, "show nuclei version"),
|
||||||
flagSet.BoolVarP(&options.Verbose, "verbose", "v", false, "show verbose output"),
|
flagSet.BoolVarP(&options.Verbose, "verbose", "v", false, "show verbose output"),
|
||||||
flagSet.BoolVar(&options.VerboseVerbose, "vv", false, "display templates loaded for scan"),
|
flagSet.BoolVar(&options.VerboseVerbose, "vv", false, "display templates loaded for scan"),
|
||||||
|
|
|
@ -3,6 +3,7 @@ package runner
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"errors"
|
"errors"
|
||||||
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -23,6 +24,7 @@ func ParseOptions(options *types.Options) {
|
||||||
|
|
||||||
// Read the inputs and configure the logging
|
// Read the inputs and configure the logging
|
||||||
configureOutput(options)
|
configureOutput(options)
|
||||||
|
|
||||||
// Show the user the banner
|
// Show the user the banner
|
||||||
showBanner()
|
showBanner()
|
||||||
|
|
||||||
|
@ -87,10 +89,15 @@ func validateOptions(options *types.Options) error {
|
||||||
if options.Verbose && options.Silent {
|
if options.Verbose && options.Silent {
|
||||||
return errors.New("both verbose and silent mode specified")
|
return errors.New("both verbose and silent mode specified")
|
||||||
}
|
}
|
||||||
//loading the proxy server list from file or cli and test the connectivity
|
|
||||||
if err := loadProxyServers(options); err != nil {
|
if err := validateProxyURL(options.ProxyURL, "invalid http proxy format (It should be http://username:password@host:port)"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := validateProxyURL(options.ProxySocksURL, "invalid socks proxy format (It should be socks5://username:password@host:port)"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if options.Validate {
|
if options.Validate {
|
||||||
options.Headless = true // required for correct validation of headless templates
|
options.Headless = true // required for correct validation of headless templates
|
||||||
validateTemplatePaths(options.TemplatesDirectory, options.Templates, options.Workflows)
|
validateTemplatePaths(options.TemplatesDirectory, options.Templates, options.Workflows)
|
||||||
|
@ -99,6 +106,19 @@ func validateOptions(options *types.Options) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func validateProxyURL(proxyURL, message string) error {
|
||||||
|
if proxyURL != "" && !isValidURL(proxyURL) {
|
||||||
|
return errors.New(message)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func isValidURL(urlString string) bool {
|
||||||
|
_, err := url.Parse(urlString)
|
||||||
|
return err == nil
|
||||||
|
}
|
||||||
|
|
||||||
// configureOutput configures the output logging levels to be displayed on the screen
|
// configureOutput configures the output logging levels to be displayed on the screen
|
||||||
func configureOutput(options *types.Options) {
|
func configureOutput(options *types.Options) {
|
||||||
// If the user desires verbose output, show verbose output
|
// If the user desires verbose output, show verbose output
|
||||||
|
@ -144,6 +164,7 @@ func loadResolvers(options *types.Options) {
|
||||||
|
|
||||||
func validateTemplatePaths(templatesDirectory string, templatePaths, workflowPaths []string) {
|
func validateTemplatePaths(templatesDirectory string, templatePaths, workflowPaths []string) {
|
||||||
allGivenTemplatePaths := append(templatePaths, workflowPaths...)
|
allGivenTemplatePaths := append(templatePaths, workflowPaths...)
|
||||||
|
|
||||||
for _, templatePath := range allGivenTemplatePaths {
|
for _, templatePath := range allGivenTemplatePaths {
|
||||||
if templatesDirectory != templatePath && filepath.IsAbs(templatePath) {
|
if templatesDirectory != templatePath && filepath.IsAbs(templatePath) {
|
||||||
fileInfo, err := os.Stat(templatePath)
|
fileInfo, err := os.Stat(templatePath)
|
||||||
|
|
|
@ -1,123 +0,0 @@
|
||||||
package runner
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"net/url"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/projectdiscovery/fileutil"
|
|
||||||
"github.com/projectdiscovery/gologger"
|
|
||||||
"github.com/projectdiscovery/nuclei/v2/pkg/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
var proxyURLList []url.URL
|
|
||||||
|
|
||||||
// loadProxyServers load list of proxy servers from file or comma seperated
|
|
||||||
func loadProxyServers(options *types.Options) error {
|
|
||||||
if len(options.Proxy) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
for _, p := range options.Proxy {
|
|
||||||
if proxyURL, err := validateProxyURL(p); err == nil {
|
|
||||||
proxyURLList = append(proxyURLList, proxyURL)
|
|
||||||
} else if fileutil.FileExists(p) {
|
|
||||||
file, err := os.Open(p)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("could not open proxy file: %s", err)
|
|
||||||
}
|
|
||||||
defer file.Close()
|
|
||||||
scanner := bufio.NewScanner(file)
|
|
||||||
for scanner.Scan() {
|
|
||||||
proxy := scanner.Text()
|
|
||||||
if strings.TrimSpace(proxy) == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if proxyURL, err := validateProxyURL(proxy); err != nil {
|
|
||||||
return err
|
|
||||||
} else {
|
|
||||||
proxyURLList = append(proxyURLList, proxyURL)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return fmt.Errorf("invalid proxy file or URL provided for %s", p)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return processProxyList(options)
|
|
||||||
}
|
|
||||||
|
|
||||||
func processProxyList(options *types.Options) error {
|
|
||||||
if len(proxyURLList) == 0 {
|
|
||||||
return fmt.Errorf("could not find any valid proxy")
|
|
||||||
} else {
|
|
||||||
done := make(chan bool)
|
|
||||||
exitCounter := make(chan bool)
|
|
||||||
counter := 0
|
|
||||||
for _, url := range proxyURLList {
|
|
||||||
go runProxyConnectivity(url, options, done, exitCounter)
|
|
||||||
}
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-done:
|
|
||||||
{
|
|
||||||
close(done)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
case <-exitCounter:
|
|
||||||
{
|
|
||||||
if counter += 1; counter == len(proxyURLList) {
|
|
||||||
return errors.New("no reachable proxy found")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func runProxyConnectivity(proxyURL url.URL, options *types.Options, done chan bool, exitCounter chan bool) {
|
|
||||||
if err := testProxyConnection(proxyURL, options.Timeout); err == nil {
|
|
||||||
if types.ProxyURL == "" && types.ProxySocksURL == "" {
|
|
||||||
assignProxyURL(proxyURL, options)
|
|
||||||
done <- true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exitCounter <- true
|
|
||||||
}
|
|
||||||
|
|
||||||
func testProxyConnection(proxyURL url.URL, timeoutDelay int) error {
|
|
||||||
timeout := time.Duration(timeoutDelay) * time.Second
|
|
||||||
_, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%s", proxyURL.Hostname(), proxyURL.Port()), timeout)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func assignProxyURL(proxyURL url.URL, options *types.Options) {
|
|
||||||
os.Setenv(types.HTTP_PROXY_ENV, proxyURL.String())
|
|
||||||
if proxyURL.Scheme == types.HTTP || proxyURL.Scheme == types.HTTPS {
|
|
||||||
types.ProxyURL = proxyURL.String()
|
|
||||||
types.ProxySocksURL = ""
|
|
||||||
gologger.Verbose().Msgf("Using %s as proxy server", proxyURL.String())
|
|
||||||
} else if proxyURL.Scheme == types.SOCKS5 {
|
|
||||||
types.ProxyURL = ""
|
|
||||||
types.ProxySocksURL = proxyURL.String()
|
|
||||||
gologger.Verbose().Msgf("Using %s as socket proxy server", proxyURL.String())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func validateProxyURL(proxy string) (url.URL, error) {
|
|
||||||
if url, err := url.Parse(proxy); err == nil && isSupportedProtocol(url.Scheme) {
|
|
||||||
return *url, nil
|
|
||||||
}
|
|
||||||
return url.URL{}, errors.New("invalid proxy format (It should be http[s]/socks5://[username:password@]host:port)")
|
|
||||||
}
|
|
||||||
|
|
||||||
//isSupportedProtocol checks given protocols are supported
|
|
||||||
func isSupportedProtocol(value string) bool {
|
|
||||||
return value == types.HTTP || value == types.HTTPS || value == types.SOCKS5
|
|
||||||
}
|
|
|
@ -51,7 +51,8 @@ var DefaultOptions = &types.Options{
|
||||||
Targets: []string{},
|
Targets: []string{},
|
||||||
TargetsFilePath: "",
|
TargetsFilePath: "",
|
||||||
Output: "",
|
Output: "",
|
||||||
Proxy: []string{},
|
ProxyURL: "",
|
||||||
|
ProxySocksURL: "",
|
||||||
TemplatesDirectory: "",
|
TemplatesDirectory: "",
|
||||||
TraceLogFile: "",
|
TraceLogFile: "",
|
||||||
Templates: []string{},
|
Templates: []string{},
|
||||||
|
|
|
@ -63,8 +63,8 @@ func New(options *types.Options) (*Browser, error) {
|
||||||
} else {
|
} else {
|
||||||
chromeLauncher = chromeLauncher.Headless(true)
|
chromeLauncher = chromeLauncher.Headless(true)
|
||||||
}
|
}
|
||||||
if types.ProxyURL != "" {
|
if options.ProxyURL != "" {
|
||||||
chromeLauncher = chromeLauncher.Proxy(types.ProxyURL)
|
chromeLauncher = chromeLauncher.Proxy(options.ProxyURL)
|
||||||
}
|
}
|
||||||
launcherURL, err := chromeLauncher.Launch()
|
launcherURL, err := chromeLauncher.Launch()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -23,8 +23,9 @@ func newhttpClient(options *types.Options) *http.Client {
|
||||||
InsecureSkipVerify: true,
|
InsecureSkipVerify: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if types.ProxyURL != "" {
|
|
||||||
if proxyURL, err := url.Parse(types.ProxyURL); err == nil {
|
if options.ProxyURL != "" {
|
||||||
|
if proxyURL, err := url.Parse(options.ProxyURL); err == nil {
|
||||||
transport.Proxy = http.ProxyURL(proxyURL)
|
transport.Proxy = http.ProxyURL(proxyURL)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,8 +128,9 @@ func wrappedGet(options *types.Options, configuration *Configuration) (*retryabl
|
||||||
return client, nil
|
return client, nil
|
||||||
}
|
}
|
||||||
poolMutex.RUnlock()
|
poolMutex.RUnlock()
|
||||||
if types.ProxyURL != "" {
|
|
||||||
proxyURL, err = url.Parse(types.ProxyURL)
|
if options.ProxyURL != "" {
|
||||||
|
proxyURL, err = url.Parse(options.ProxyURL)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -171,24 +172,27 @@ func wrappedGet(options *types.Options, configuration *Configuration) (*retryabl
|
||||||
},
|
},
|
||||||
DisableKeepAlives: disableKeepAlives,
|
DisableKeepAlives: disableKeepAlives,
|
||||||
}
|
}
|
||||||
if proxyURL != nil {
|
|
||||||
// Attempts to overwrite the dial function with the socks proxied version
|
|
||||||
if proxyURL.Scheme == types.SOCKS5 {
|
|
||||||
var proxyAuth *proxy.Auth = &proxy.Auth{}
|
|
||||||
proxyAuth.User = proxyURL.User.Username()
|
|
||||||
proxyAuth.Password, _ = proxyURL.User.Password()
|
|
||||||
|
|
||||||
dialer, proxyErr := proxy.SOCKS5("tcp", fmt.Sprintf("%s:%s", proxyURL.Hostname(), proxyURL.Port()), proxyAuth, proxy.Direct)
|
// Attempts to overwrite the dial function with the socks proxied version
|
||||||
|
if options.ProxySocksURL != "" {
|
||||||
|
var proxyAuth *proxy.Auth
|
||||||
|
|
||||||
dc := dialer.(interface {
|
socksURL, proxyErr := url.Parse(options.ProxySocksURL)
|
||||||
DialContext(ctx context.Context, network, addr string) (net.Conn, error)
|
if proxyErr == nil {
|
||||||
})
|
proxyAuth = &proxy.Auth{}
|
||||||
if proxyErr == nil {
|
proxyAuth.User = socksURL.User.Username()
|
||||||
transport.DialContext = dc.DialContext
|
proxyAuth.Password, _ = socksURL.User.Password()
|
||||||
}
|
|
||||||
} else {
|
|
||||||
transport.Proxy = http.ProxyURL(proxyURL)
|
|
||||||
}
|
}
|
||||||
|
dialer, proxyErr := proxy.SOCKS5("tcp", fmt.Sprintf("%s:%s", socksURL.Hostname(), socksURL.Port()), proxyAuth, proxy.Direct)
|
||||||
|
dc := dialer.(interface {
|
||||||
|
DialContext(ctx context.Context, network, addr string) (net.Conn, error)
|
||||||
|
})
|
||||||
|
if proxyErr == nil {
|
||||||
|
transport.DialContext = dc.DialContext
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if proxyURL != nil {
|
||||||
|
transport.Proxy = http.ProxyURL(proxyURL)
|
||||||
}
|
}
|
||||||
|
|
||||||
var jar *cookiejar.Jar
|
var jar *cookiejar.Jar
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
package types
|
|
||||||
|
|
||||||
const (
|
|
||||||
HTTP_PROXY_ENV = "HTTP_PROXY"
|
|
||||||
SOCKS5 = "socks5"
|
|
||||||
HTTP = "http"
|
|
||||||
HTTPS = "https"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// ProxyURL is the URL for the proxy server
|
|
||||||
ProxyURL string
|
|
||||||
// ProxySocksURL is the URL for the proxy socks server
|
|
||||||
ProxySocksURL string
|
|
||||||
)
|
|
|
@ -49,8 +49,10 @@ type Options struct {
|
||||||
TargetsFilePath string
|
TargetsFilePath string
|
||||||
// Output is the file to write found results to.
|
// Output is the file to write found results to.
|
||||||
Output string
|
Output string
|
||||||
// List of HTTP(s)/SOCKS5 proxy servers or path to file containing such list
|
// ProxyURL is the URL for the proxy server
|
||||||
Proxy goflags.NormalizedStringSlice
|
ProxyURL string
|
||||||
|
// ProxySocksURL is the URL for the proxy socks server
|
||||||
|
ProxySocksURL string
|
||||||
// TemplatesDirectory is the directory to use for storing templates
|
// TemplatesDirectory is the directory to use for storing templates
|
||||||
TemplatesDirectory string
|
TemplatesDirectory string
|
||||||
// TraceLogFile specifies a file to write with the trace of all requests
|
// TraceLogFile specifies a file to write with the trace of all requests
|
||||||
|
|
Loading…
Reference in New Issue