Skip to content

Commit

Permalink
Fixing all ips probe with ports (#626)
Browse files Browse the repository at this point in the history
* Fixing all ips probe with standard ports

* using custom type for targets
  • Loading branch information
Mzack9999 authored May 19, 2022
1 parent b43b9d7 commit daf4ad6
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 45 deletions.
8 changes: 8 additions & 0 deletions common/httpx/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package httpx

// Target of the scan with ip|host header customization
type Target struct {
Host string
CustomHost string
CustomIP string
}
88 changes: 43 additions & 45 deletions runner/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -597,7 +597,7 @@ func (r *Runner) RunEnumeration() {
}
if len(r.options.OutputFilterCdn) > 0 && stringsutil.EqualFoldAny(resp.CDNName, r.options.OutputFilterCdn...) {
continue
}
}
if r.options.OutputMatchResponseTime != "" {
filterOps := FilterOperator{flag: "-mrt, -match-response-time"}
operator, value, err := filterOps.Parse(r.options.OutputMatchResponseTime)
Expand Down Expand Up @@ -738,7 +738,7 @@ func (r *Runner) process(t string, wg *sizedwaitgroup.SizedWaitGroup, hp *httpx.
for _, method := range scanopts.Methods {
for _, prot := range protocols {
wg.Add()
go func(target, method, protocol string) {
go func(target httpx.Target, method, protocol string) {
defer wg.Done()
result := r.analyze(hp, protocol, target, method, t, scanopts)
output <- result
Expand Down Expand Up @@ -779,10 +779,10 @@ func (r *Runner) process(t string, wg *sizedwaitgroup.SizedWaitGroup, hp *httpx.
for _, wantedProtocol := range wantedProtocols {
for _, method := range scanopts.Methods {
wg.Add()
go func(port int, target, method, protocol string) {
go func(port int, target httpx.Target, method, protocol string) {
defer wg.Done()
h, _ := urlutil.ChangePort(target, fmt.Sprint(port))
result := r.analyze(hp, protocol, h, method, t, scanopts)
target.Host, _ = urlutil.ChangePort(target.Host, fmt.Sprint(port))
result := r.analyze(hp, protocol, target, method, t, scanopts)
output <- result
if scanopts.TLSProbe && result.TLSData != nil {
scanopts.TLSProbe = false
Expand Down Expand Up @@ -810,16 +810,16 @@ func (r *Runner) process(t string, wg *sizedwaitgroup.SizedWaitGroup, hp *httpx.
}

// returns all the targets within a cidr range or the single target
func (r *Runner) targets(hp *httpx.HTTPX, target string) chan string {
results := make(chan string)
func (r *Runner) targets(hp *httpx.HTTPX, target string) chan httpx.Target {
results := make(chan httpx.Target)
go func() {
defer close(results)

// A valid target does not contain:
// *
// spaces
if strings.ContainsAny(target, "*") || strings.HasPrefix(target, ".") {
// trim * and/or . (prefix) from the target to return the domain instead of wildard
// trim * and/or . (prefix) from the target to return the domain instead of wilcard
target = strings.TrimPrefix(strings.Trim(target, "*"), ".")
if !r.testAndSet(target) {
return
Expand All @@ -833,74 +833,62 @@ func (r *Runner) targets(hp *httpx.HTTPX, target string) chan string {
return
}
for _, ip := range cidrIps {
results <- ip
results <- httpx.Target{Host: ip}
}
} else if r.options.ProbeAllIPS {
URL, err := urlutil.Parse(target)
if err != nil {
results <- target
results <- httpx.Target{Host: target}
}
ips, _, err := getDNSData(hp, URL.Host)
if err != nil || len(ips) == 0 {
results <- target
results <- httpx.Target{Host: target}
}
for _, ip := range ips {
results <- strings.Join([]string{ip, target}, ",")
results <- httpx.Target{Host: target, CustomIP: ip}
}
} else if idxComma := strings.Index(target, ","); idxComma > 0 {
results <- httpx.Target{Host: target[idxComma+1:], CustomHost: target[:idxComma]}
} else {
results <- target
results <- httpx.Target{Host: target}
}
}()
return results
}

func (r *Runner) analyze(hp *httpx.HTTPX, protocol, domain, method, origInput string, scanopts *scanOptions) Result {
func (r *Runner) analyze(hp *httpx.HTTPX, protocol string, target httpx.Target, method, origInput string, scanopts *scanOptions) Result {
origProtocol := protocol
if protocol == httpx.HTTPorHTTPS || protocol == httpx.HTTPandHTTPS {
protocol = httpx.HTTPS
}
retried := false
retry:
var customHost, customIP string
if scanopts.ProbeAllIPS {
parts := strings.SplitN(domain, ",", 2)
if len(parts) == 2 {
customIP = parts[0]
domain = parts[1]
}
if scanopts.VHostInput && target.CustomHost == "" {
return Result{Input: origInput}
}
if scanopts.VHostInput {
parts := strings.Split(domain, ",")
//nolint:gomnd // not a magic number
if len(parts) != 2 {
return Result{Input: origInput}
}
domain = parts[0]
customHost = parts[1]
}
URL, err := urlutil.Parse(domain)
URL, err := urlutil.Parse(target.Host)
if err != nil {
return Result{URL: domain, Input: origInput, err: err}
return Result{URL: target.Host, Input: origInput, err: err}
}

// check if we have to skip the host:port as a result of a previous failure
hostPort := net.JoinHostPort(URL.Host, URL.Port)
if r.options.HostMaxErrors >= 0 && r.HostErrorsCache.Has(hostPort) {
numberOfErrors, err := r.HostErrorsCache.GetIFPresent(hostPort)
if err == nil && numberOfErrors.(int) >= r.options.HostMaxErrors {
return Result{URL: domain, err: errors.New("skipping as previously unresponsive")}
return Result{URL: target.Host, err: errors.New("skipping as previously unresponsive")}
}
}

// check if the combination host:port should be skipped if belonging to a cdn
if r.skipCDNPort(URL.Host, URL.Port) {
gologger.Debug().Msgf("Skipping cdn target: %s:%s\n", URL.Host, URL.Port)
return Result{URL: domain, Input: origInput, err: errors.New("cdn target only allows ports 80 and 443")}
return Result{URL: target.Host, Input: origInput, err: errors.New("cdn target only allows ports 80 and 443")}
}

URL.Scheme = protocol

if !strings.Contains(domain, URL.Port) {
if !strings.Contains(target.Host, URL.Port) {
URL.Port = ""
}

Expand All @@ -915,9 +903,14 @@ retry:
URL.RequestURI += scanopts.RequestURI
}
var req *retryablehttp.Request
if customIP != "" {
customHost = URL.Host
ctx := context.WithValue(context.Background(), "ip", customIP) //nolint
if target.CustomIP != "" {
var requestIP string
if iputil.IsIPv6(target.CustomIP) {
requestIP = fmt.Sprintf("[%s]", target.CustomIP)
} else {
requestIP = target.CustomIP
}
ctx := context.WithValue(context.Background(), "ip", requestIP) //nolint
req, err = hp.NewRequestWithContext(ctx, method, URL.String())
} else {
req, err = hp.NewRequest(method, URL.String())
Expand All @@ -926,8 +919,8 @@ retry:
return Result{URL: URL.String(), Input: origInput, err: err}
}

if customHost != "" {
req.Host = customHost
if target.CustomHost != "" {
req.Host = target.CustomHost
}

if !scanopts.LeaveDefaultPorts {
Expand Down Expand Up @@ -1198,7 +1191,15 @@ retry:
r.stats.IncrementCounter("requests", 1)
}
}
ip := hp.Dialer.GetDialedIP(URL.Host)

var ip string
if target.CustomIP != "" {
ip = target.CustomIP
} else {
// hp.Dialer.GetDialedIP would return only the last dialed one
ip = hp.Dialer.GetDialedIP(URL.Host)
}

var asnResponse interface{ String() string }
if r.options.Asn {
lookupResult, err := ipisp.LookupIP(context.Background(), net.ParseIP(ip))
Expand All @@ -1222,10 +1223,7 @@ retry:
builder.WriteRune(']')
}
}
// hp.Dialer.GetDialedIP would return only the last dialed one
if customIP != "" {
ip = customIP
}

if scanopts.OutputIP || scanopts.ProbeAllIPS {
builder.WriteString(fmt.Sprintf(" [%s]", ip))
}
Expand Down

0 comments on commit daf4ad6

Please sign in to comment.