This repository was archived by the owner on Apr 9, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathcrawl.go
113 lines (89 loc) · 3.2 KB
/
crawl.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
// Author: Liam Stanley <me@liamstanley.io>
// Docs: https://marill.liam.sh/
// Repo: https://github.com/lrstanley/marill
package main
import (
"fmt"
"github.com/lrstanley/marill/domfinder"
"github.com/lrstanley/marill/scraper"
)
// Scan is a wrapper for all state related to the crawl process
type Scan struct {
finder *domfinder.Finder
crawler *scraper.Crawler
results []*TestResult
tests []*Test
successful int
failed int
}
func crawl() (*Scan, error) {
var err error
res := &Scan{}
// fetch the tests ahead of time to ensure there are no syntax errors or anything
res.tests = genTests()
res.crawler = &scraper.Crawler{Log: logger}
res.finder = &domfinder.Finder{Log: logger}
if conf.scan.ManualList != "" {
logger.Println("manually supplied url list")
res.crawler.Cnf.Domains, err = parseManualList()
if err != nil {
return nil, NewErr{Code: ErrDomains, deepErr: err}
}
} else {
logger.Println("checking for running webservers")
if err := res.finder.GetWebservers(); err != nil {
return nil, NewErr{Code: ErrProcList, deepErr: err}
}
if outlist := ""; len(res.finder.Procs) > 0 {
for _, proc := range res.finder.Procs {
outlist += fmt.Sprintf("[%s:%s] ", proc.Name, proc.PID)
}
logger.Printf("found %d procs matching a webserver: %s", len(res.finder.Procs), outlist)
out.Printf("found %d procs matching a webserver", len(res.finder.Procs))
}
// start crawling for domains
if err := res.finder.GetDomains(); err != nil {
return nil, NewErr{Code: ErrGetDomains, deepErr: err}
}
res.finder.Filter(domfinder.DomainFilter{
IgnoreHTTP: conf.scan.IgnoreHTTP,
IgnoreHTTPS: conf.scan.IgnoreHTTPS,
IgnoreMatch: conf.scan.IgnoreMatch,
MatchOnly: conf.scan.MatchOnly,
})
if len(res.finder.Domains) == 0 {
return nil, NewErr{Code: ErrNoDomainsFound}
}
logger.Printf("found %d domains on webserver %s (exe: %s, pid: %s)", len(res.finder.Domains), res.finder.MainProc.Name, res.finder.MainProc.Exe, res.finder.MainProc.PID)
for _, domain := range res.finder.Domains {
res.crawler.Cnf.Domains = append(res.crawler.Cnf.Domains, &scraper.Domain{URL: domain.URL, IP: domain.IP})
}
}
res.crawler.Cnf.Assets = conf.scan.Assets
res.crawler.Cnf.NoRemote = conf.scan.IgnoreRemote
res.crawler.Cnf.Delay = conf.scan.Delay
res.crawler.Cnf.AllowInsecure = conf.scan.AllowInsecure
res.crawler.Cnf.HTTPTimeout = conf.scan.HTTPTimeout
logger.Print("starting crawler...")
out.Printf("starting scan on %d domains", len(res.crawler.Cnf.Domains))
res.crawler.Crawl()
out.Println("{lightgreen}scan complete{c}")
// print out a fairly large amount of debugging information here
for i := 0; i < len(res.crawler.Results); i++ {
logger.Print(res.crawler.Results[i])
for r := 0; r < len(res.crawler.Results[i].Assets); r++ {
logger.Printf("%s => %s", res.crawler.Results[i].URL, res.crawler.Results[i].Assets[r])
}
}
out.Println("{lightblue}starting tests{c}")
res.results = checkTests(res.crawler.Results, res.tests)
for i := 0; i < len(res.results); i++ {
if res.results[i].Result.Error != nil {
res.failed++
continue
}
res.successful++
}
out.Printf("%d successful, %d failed", res.successful, res.failed)
return res, nil
}