Skip to content
Closed
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ noscope.txt
benchmarking
# Added by goreleaser init:
dist/
recording.pws
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ Usage: hacker-scoper --file /path/to/targets [--company company | --inscopes-fil
| -f | --file | Path to your file containing URLs/domains/IPs |
| -ins | --inscope-file | Path to a custom plaintext file containing scopes |
| -oos | --outofscope-file | Path to a custom plaintext file containing scopes exclusions |
| -e | --inscope-explicit-level int<br>--noscope-explicit-level int| How explicit we expect the scopes to be: <br> 1 (default): Include subdomains in the scope even if there's not a wildcard in the scope. <br> 2: Include subdomains in the scope only if there's a wildcard in the scope. <br> 3: Include subdomains/IPs in the scope only if they are explicitly within the scope. CIDR ranges and wildcards are disabled. |
| -ie<br>-oe | --inscope-explicit-level int<br>--noscope-explicit-level int| How explicit we expect the scopes to be: <br> 1 (default): Include subdomains in the scope even if there's not a wildcard in the scope. <br> 2: Include subdomains in the scope only if there's a wildcard in the scope. <br> 3: Include subdomains/IPs in the scope only if they are explicitly within the scope. CIDR ranges and wildcards are disabled. |
| | --enable-private-tlds | Set this flag to enable the use of company scope domains with private TLDs. This essentially disables the bug-bounty-program misconfiguration detection. |
| -ch | --chain-mode | In "chain-mode" we only output the important information. No decorations. Default: false |
| --database | | Custom path to the cached firebounty database |
Expand Down
60 changes: 50 additions & 10 deletions src/hacker-scoper/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ import (
"os"
"path/filepath"
"regexp"
"runtime"
"strconv"
"strings"
"sync"
"time"

"golang.org/x/net/publicsuffix"
Expand Down Expand Up @@ -74,6 +76,12 @@ type firebountySearchMatch struct {
companyName string
}

type parseResult struct {
value interface{}
line string
err error
}

var chainMode bool

const colorReset = "\033[0m"
Expand Down Expand Up @@ -987,24 +995,56 @@ func parseLine(line string, isScope bool) (interface{}, error) {
func parseAllLines(lines []string, isScopes bool) ([]interface{}, error) {
parsed := []interface{}{}

for i, line := range lines {
parsedTemp, err := parseLine(line, isScopes)
if err != nil {
if !chainMode {
warning("Unable to parse line number " + strconv.Itoa(i) + " as a scope: \"" + line + "\"")
numWorkers := runtime.NumCPU()
inputChan := make(chan string, numWorkers)
outputChan := make(chan parseResult, len(lines))

var wg sync.WaitGroup

// Start workers
for i := 0; i < numWorkers; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for line := range inputChan {
result, err := parseLine(line, isScopes)
if err != nil {
outputChan <- parseResult{value: result, line: line, err: err}
} else {
outputChan <- parseResult{value: result, line: "", err: err}
}
}
} else {
parsed = append(parsed, parsedTemp)
}()
}

// Feed lines to workers
go func() {
for _, line := range lines {
inputChan <- line
}
close(inputChan)
}()

// Wait for workers to finish
go func() {
wg.Wait()
close(outputChan)
}()

for res := range outputChan {
if res.err != nil {
if !chainMode {
warning("Unable to parse line: \"" + res.line + "\"")
}
} else if res.value != nil {
parsed = append(parsed, res.value)
}
}

if len(parsed) == 0 {
return nil, errors.New("unable to parse any lines as scopes")
} else {
return parsed, nil
}

return parsed, nil
}

func isInscope(inscopeScopes *[]interface{}, target *interface{}, explicitLevel *int) (result bool) {
Expand Down