这是indexloc提供的服务,不要输入任何密码
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ This will display help for the tool. Here are all the switches it supports.
| Flag | Description | Example |
| ---------------- | ---------------------------------------------------------- | -------------------------------------- |
| -all | Use all sources (slow) for enumeration | subfinder -d uber.com -all |
| -b | IP address to be used as local bind | subfinder -b 172.16.0.1 |
| -config | Configuration file for API Keys, etc | subfinder -config config.yaml |
| -d | Domain to find subdomains for | subfinder -d uber.com |
| -dL | File containing list of domains to enumerate | subfinder -dL hackerone-hosts.txt |
Expand Down Expand Up @@ -210,6 +211,30 @@ https://docs.hackerone.com
http://mta-sts.managed.hackerone.com
```

If your enterprise uses source routing to choose network output, or your computer has many public network interfaces (eg: public Wi-Fi + 4G connection + Ethernet Wire + VPN), you might want to choose your output network by binding IP source. In this case, you can use `-b` option.
In the example below, we have 3 network interfaces able to communicate to the Internet through 3 different outputs. Each output is chosen by binding one source IP with `-b` option.
```sh
▶ ip addr
[...]
3: wlp3s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether e8:b1:fc:50:90:a0 brd ff:ff:ff:ff:ff:ff
inet 192.168.1.87/24 brd 192.168.1.255 scope global dynamic noprefixroute wlp3s0
valid_lft 62538sec preferred_lft 62538sec
4: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 100
link/none
inet 192.168.254.70 peer 192.168.254.69/32 scope global tun0
valid_lft forever preferred_lft forever
5: enx0c5b8f279a64: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 0c:5b:8f:a5:63:25 brd ff:ff:ff:ff:ff:ff
inet 192.168.8.100/24 brd 192.168.8.255 scope global dynamic noprefixroute enx0c5b8f279a64
valid_lft 86396sec preferred_lft 86396sec

▶ subfinder -d hackerone.com -b 192.168.1.87
▶ subfinder -d hackerone.com -b 192.168.254.70
▶ subfinder -d hackerone.com -b 192.168.8.100
```


<table>
<tr>
<td>
Expand Down
5 changes: 3 additions & 2 deletions v2/pkg/passive/passive.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package passive
import (
"context"
"fmt"
"net"
"sync"
"time"

Expand All @@ -11,11 +12,11 @@ import (
)

// EnumerateSubdomains enumerates all the subdomains for a given domain
func (a *Agent) EnumerateSubdomains(domain string, keys *subscraping.Keys, timeout int, maxEnumTime time.Duration) chan subscraping.Result {
func (a *Agent) EnumerateSubdomains(domain string, keys *subscraping.Keys, timeout int, maxEnumTime time.Duration, localIP net.IP) chan subscraping.Result {
results := make(chan subscraping.Result)

go func() {
session, err := subscraping.NewSession(domain, keys, timeout)
session, err := subscraping.NewSession(domain, keys, timeout, localIP)
if err != nil {
results <- subscraping.Result{Type: subscraping.Error, Error: fmt.Errorf("could not init passive session for %s: %s", domain, err)}
}
Expand Down
2 changes: 1 addition & 1 deletion v2/pkg/runner/enumerate.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func (r *Runner) EnumerateSingleDomain(ctx context.Context, domain string, outpu

// Run the passive subdomain enumeration
now := time.Now()
passiveResults := r.passiveAgent.EnumerateSubdomains(domain, &keys, r.options.Timeout, time.Duration(r.options.MaxEnumerationTime)*time.Minute)
passiveResults := r.passiveAgent.EnumerateSubdomains(domain, &keys, r.options.Timeout, time.Duration(r.options.MaxEnumerationTime)*time.Minute, r.options.LocalIP)

wg := &sync.WaitGroup{}
wg.Add(1)
Expand Down
4 changes: 4 additions & 0 deletions v2/pkg/runner/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package runner
import (
"flag"
"io"
"net"
"os"
"path"
"reflect"
Expand Down Expand Up @@ -38,6 +39,8 @@ type Options struct {
ExcludeSources string // ExcludeSources contains the comma-separated sources to not include in the enumeration process
Resolvers string // Resolvers is the comma-separated resolvers to use for enumeration
ResolverList string // ResolverList is a text file containing list of resolvers to use for enumeration
LocalIP net.IP // LocalIP is the IP address used as local bind
LocalIPString string // LocalIPString is the IP address in string format got from command line
ConfigFile string // ConfigFile contains the location of the config file

YAMLConfig ConfigFile // YAMLConfig contains the unmarshalled yaml config file
Expand Down Expand Up @@ -75,6 +78,7 @@ func ParseOptions() *Options {
flag.StringVar(&options.Resolvers, "r", "", "Comma-separated list of resolvers to use")
flag.StringVar(&options.ResolverList, "rL", "", "Text file containing list of resolvers to use")
flag.BoolVar(&options.RemoveWildcard, "nW", false, "Remove Wildcard & Dead Subdomains from output")
flag.StringVar(&options.LocalIPString, "b", "", "IP address to be used as local bind")
flag.StringVar(&options.ConfigFile, "config", path.Join(config, "config.yaml"), "Configuration file for API Keys, etc")
flag.BoolVar(&options.Version, "version", false, "Show version of subfinder")
flag.Parse()
Expand Down
9 changes: 9 additions & 0 deletions v2/pkg/runner/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package runner

import (
"errors"
"net"

"github.com/projectdiscovery/gologger"
"github.com/projectdiscovery/gologger/formatter"
Expand Down Expand Up @@ -34,6 +35,14 @@ func (options *Options) validateOptions() error {
return errors.New("hostip flag must be used with RemoveWildcard option")
}

// Check local IP address
if options.LocalIPString != "" {
options.LocalIP = net.ParseIP(options.LocalIPString)
if options.LocalIP == nil {
return errors.New("local bind ip is malformed")
}
}

return nil
}

Expand Down
10 changes: 9 additions & 1 deletion v2/pkg/subscraping/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"fmt"
"io"
"io/ioutil"
"net"
"net/http"
"net/url"
"time"
Expand All @@ -14,14 +15,21 @@ import (
)

// NewSession creates a new session object for a domain
func NewSession(domain string, keys *Keys, timeout int) (*Session, error) {
func NewSession(domain string, keys *Keys, timeout int, localIP net.IP) (*Session, error) {
dialer := &net.Dialer{
LocalAddr: &net.TCPAddr{
IP: localIP,
},
}

client := &http.Client{
Transport: &http.Transport{
MaxIdleConns: 100,
MaxIdleConnsPerHost: 100,
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
DialContext: dialer.DialContext,
},
Timeout: time.Duration(timeout) * time.Second,
}
Expand Down