diff --git a/cmd/httpx/httpx.go b/cmd/httpx/httpx.go index d442b9e..3415b90 100644 --- a/cmd/httpx/httpx.go +++ b/cmd/httpx/httpx.go @@ -14,6 +14,7 @@ import ( customport "github.com/projectdiscovery/httpx/common/customports" "github.com/projectdiscovery/httpx/common/fileutil" "github.com/projectdiscovery/httpx/common/httpx" + "github.com/projectdiscovery/httpx/common/iputil" "github.com/projectdiscovery/httpx/common/stringz" "github.com/remeh/sizedwaitgroup" ) @@ -111,29 +112,29 @@ func main() { } for sc.Scan() { - target := stringz.TrimProtocol(sc.Text()) + for target := range targets(stringz.TrimProtocol(sc.Text())) { + // if no custom ports specified then test the default ones + if len(customport.Ports) == 0 { + wg.Add() + go func(target string) { + defer wg.Done() + analyze(hp, protocol, target, 0, &scanopts, output) + }(target) + } - // if no custom ports specified then test the default ones - if len(customport.Ports) == 0 { - wg.Add() - go func(target string) { - defer wg.Done() - analyze(hp, protocol, target, 0, &scanopts, output) - }(target) - } + // the host name shouldn't have any semicolon - in case remove the port + semicolonPosition := strings.LastIndex(target, ":") + if semicolonPosition > 0 { + target = target[:semicolonPosition] + } - // the host name shouldn't have any semicolon - in case remove the port - semicolonPosition := strings.LastIndex(target, ":") - if semicolonPosition > 0 { - target = target[:semicolonPosition] - } - - for port := range customport.Ports { - wg.Add() - go func(port int) { - defer wg.Done() - analyze(hp, protocol, target, port, &scanopts, output) - }(port) + for port := range customport.Ports { + wg.Add() + go func(port int) { + defer wg.Done() + analyze(hp, protocol, target, port, &scanopts, output) + }(port) + } } } @@ -144,6 +145,29 @@ func main() { wgoutput.Wait() } +// returns all the targets within a cidr range or the single target +func targets(target string) chan string { + results := make(chan string) + go func() { + defer close(results) + + // test if the target is a cidr + if iputil.IsCidr(target) { + cidrIps, err := iputil.Ips(target) + if err != nil { + return + } + for _, ip := range cidrIps { + results <- ip + } + } else { + results <- target + } + + }() + return results +} + type scanOptions struct { Method string VHost bool diff --git a/common/iputil/iputil.go b/common/iputil/iputil.go new file mode 100644 index 0000000..f717c56 --- /dev/null +++ b/common/iputil/iputil.go @@ -0,0 +1,42 @@ +package iputil + +import "net" + +// IsCidr determines if the given ip is a cidr range +func IsCidr(ip string) bool { + _, _, err := net.ParseCIDR(ip) + if err != nil { + return false + } + + return true +} + +// IsIP determines if the given string is a valid ip +func IsIP(ip string) bool { + return net.ParseIP(ip) != nil +} + +// Ips of a cidr +func Ips(cidr string) ([]string, error) { + ip, ipnet, err := net.ParseCIDR(cidr) + if err != nil { + return nil, err + } + + var ips []string + for ip := ip.Mask(ipnet.Mask); ipnet.Contains(ip); inc(ip) { + ips = append(ips, ip.String()) + } + // remove network address and broadcast address + return ips[1 : len(ips)-1], nil +} + +func inc(ip net.IP) { + for j := len(ip) - 1; j >= 0; j-- { + ip[j]++ + if ip[j] > 0 { + break + } + } +} diff --git a/go.mod b/go.mod index d829f9b..83ec27c 100644 --- a/go.mod +++ b/go.mod @@ -12,5 +12,5 @@ require ( github.com/projectdiscovery/retryablehttp-go v1.0.1 github.com/remeh/sizedwaitgroup v1.0.0 github.com/rs/xid v1.2.1 - golang.org/x/net v0.0.0-20200528225125-3c3fba18258b + golang.org/x/net v0.0.0-20200602114024-627f9648deb9 ) diff --git a/go.sum b/go.sum index a02a06d..947cc64 100644 --- a/go.sum +++ b/go.sum @@ -32,8 +32,8 @@ golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200528225125-3c3fba18258b h1:IYiJPiJfzktmDAO1HQiwjMjwjlYKHAL7KzeD544RJPs= -golang.org/x/net v0.0.0-20200528225125-3c3fba18258b/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200602114024-627f9648deb9 h1:pNX+40auqi2JqRfOP1akLGtYcn15TUbkhwuCO3foqqM= +golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=