-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathhttp.go
120 lines (97 loc) · 2.97 KB
/
http.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
114
115
116
117
118
119
120
package udig
import (
"crypto/tls"
"fmt"
"net"
"net/http"
)
var (
// DefaultHTTPHeaders is a list of default HTTP header names that we look for.
DefaultHTTPHeaders = [...]string{
"access-control-allow-origin",
"alt-svc",
"content-security-policy",
"content-security-policy-report-only",
}
)
// fetchHeaders connects to a given URL and on successful connection returns
// a map of HTTP headers in the response.
func fetchHeaders(url string) http.Header {
transport := http.DefaultTransport.(*http.Transport)
transport.DialContext = (&net.Dialer{
Timeout: DefaultTimeout,
KeepAlive: DefaultTimeout,
}).DialContext
transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
transport.TLSHandshakeTimeout = DefaultTimeout
client := &http.Client{
Transport: transport,
Timeout: DefaultTimeout,
}
response, err := client.Get(url)
if err != nil {
// Don't bother trying to find CSP on non-TLS sites.
LogErr("HTTP: Could not GET %s - the cause was: %s.", url, err.Error())
return map[string][]string{}
}
return response.Header
}
/////////////////////////////////////////
// HTTP RESOLVER
/////////////////////////////////////////
// NewHTTPResolver creates a new HTTPResolver with sensible defaults.
func NewHTTPResolver() *HTTPResolver {
transport := http.DefaultTransport.(*http.Transport)
transport.DialContext = (&net.Dialer{
Timeout: DefaultTimeout,
KeepAlive: DefaultTimeout,
}).DialContext
transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
transport.TLSHandshakeTimeout = DefaultTimeout
client := &http.Client{
Transport: transport,
Timeout: DefaultTimeout,
}
return &HTTPResolver{
Headers: DefaultHTTPHeaders[:],
Client: client,
}
}
// Type returns "HTTP".
func (resolver *HTTPResolver) Type() ResolutionType {
return TypeHTTP
}
// ResolveDomain resolves a given domain to a list of corresponding HTTP headers.
func (resolver *HTTPResolver) ResolveDomain(domain string) Resolution {
resolution := &HTTPResolution{
ResolutionBase: &ResolutionBase{query: domain},
}
headers := fetchHeaders("https://" + domain)
for _, name := range resolver.Headers {
value := headers[http.CanonicalHeaderKey(name)]
if len(DissectDomainsFromStrings(value)) > 0 {
resolution.Headers = append(resolution.Headers, HTTPHeader{name, value})
}
}
return resolution
}
/////////////////////////////////////////
// HTTP RESOLUTION
/////////////////////////////////////////
// Type returns "HTTP".
func (res *HTTPResolution) Type() ResolutionType {
return TypeHTTP
}
// Domains returns a list of domains discovered in records within this Resolution.
func (res *HTTPResolution) Domains() (domains []string) {
for _, header := range res.Headers {
domains = append(domains, DissectDomainsFromStrings(header.Value)...)
}
return domains
}
/////////////////////////////////////////
// HTTP HEADER
/////////////////////////////////////////
func (header *HTTPHeader) String() string {
return fmt.Sprintf("%s: %v", header.Name, header.Value)
}