-
Notifications
You must be signed in to change notification settings - Fork 129
/
intigriti.go
169 lines (143 loc) · 4.49 KB
/
intigriti.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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
package intigriti
import (
"fmt"
"log"
"strings"
"time"
"github.com/sw33tLie/bbscope/internal/utils"
"github.com/sw33tLie/bbscope/pkg/scope"
"github.com/sw33tLie/bbscope/pkg/whttp"
"github.com/tidwall/gjson"
)
func GetCategoryID(input string) []int {
categories := map[string][]int{
"url": {1},
"cidr": {4},
"mobile": {2, 3},
"android": {2},
"apple": {3},
"device": {5},
"other": {6},
"wildcard": {7},
"all": {1, 2, 3, 4, 5, 6, 7},
}
selectedCategory, ok := categories[strings.ToLower(input)]
if !ok {
log.Fatal("Invalid category")
}
return selectedCategory
}
func GetProgramScope(token string, programID string, categories string, bbpOnly bool, includeOOS bool) (pData scope.ProgramData) {
res, err := whttp.SendHTTPRequest(
&whttp.WHTTPReq{
Method: "GET",
URL: "https://api.intigriti.com/external/researcher/v1/programs/" + programID,
Headers: []whttp.WHTTPHeader{
{Name: "Authorization", Value: "Bearer " + token},
},
}, nil)
if err != nil {
log.Fatal("HTTP request failed: ", err)
}
if res.StatusCode == 401 {
utils.Log.Fatal("Invalid auth token")
}
if strings.Contains(res.BodyString, "Request blocked") {
utils.Log.Info("Rate limited. Retrying...")
time.Sleep(2 * time.Second)
return GetProgramScope(token, programID, categories, bbpOnly, includeOOS)
}
// Use gjson to get the content array
contentArray := gjson.Get(res.BodyString, "domains.content")
// Iterate over each item in the array
contentArray.ForEach(func(key, value gjson.Result) bool {
endpoint := value.Get("endpoint").String()
categoryID := value.Get("type.id").Int()
categoryValue := value.Get("type.value").Str
tierID := value.Get("tier.id").Int()
description := value.Get("description").Str
// Check if the tier ID is not 5 (out of scope)
if tierID != 5 {
if !bbpOnly || (bbpOnly && tierID != 1) {
// Check if this element belongs to one of the categories the user chose
if isInArray(int(categoryID), GetCategoryID(categories)) {
pData.InScope = append(pData.InScope, scope.ScopeElement{
Target: endpoint,
Description: strings.ReplaceAll(description, "\n", " "),
Category: categoryValue,
})
}
}
} else {
// TODO: This isn't being printed
if includeOOS {
pData.OutOfScope = append(pData.InScope, scope.ScopeElement{
Target: endpoint,
Description: strings.ReplaceAll(description, "\n", " "),
Category: categoryValue,
})
}
}
return true // Keep iterating
})
return pData
}
func GetAllProgramsScope(token string, bbpOnly bool, pvtOnly bool, categories, outputFlags, delimiterCharacter string, includeOOS, printRealTime bool) (programs []scope.ProgramData) {
offset := 0
limit := 500
total := 0
for {
res, err := whttp.SendHTTPRequest(
&whttp.WHTTPReq{
Method: "GET",
URL: fmt.Sprintf("https://api.intigriti.com/external/researcher/v1/programs?statusId=3&limit=%d&offset=%d", limit, offset),
Headers: []whttp.WHTTPHeader{
{Name: "Authorization", Value: "Bearer " + token},
},
}, nil)
if err != nil {
utils.Log.Fatal("HTTP request failed: ", err)
}
if res.StatusCode == 401 {
utils.Log.Fatal("Invalid auth token")
}
bodyString := string(res.BodyString)
if offset == 0 {
total = int(gjson.Get(bodyString, "maxCount").Int())
utils.Log.Info("Total Programs available: ", total)
}
records := gjson.Get(bodyString, "records").Array()
for _, record := range records {
id := record.Get("id").String()
maxBounty := record.Get("maxBounty.value").Int()
confidentialityLevel := record.Get("confidentialityLevel.id").Int()
programPath := strings.Split(record.Get("webLinks.detail").String(), "=")[1]
// Types of confidentialityLevel: 1 InviteOnly, 2 Application, 3 Registered, 4 Public.
// We assume privates are 1, 2 and 3.
if (pvtOnly && confidentialityLevel != 4) || !pvtOnly {
if (bbpOnly && maxBounty != 0) || !bbpOnly {
pData := GetProgramScope(token, id, categories, bbpOnly, includeOOS)
pData.Url = "https://app.intigriti.com/researcher" + programPath
if printRealTime {
scope.PrintProgramScope(pData, outputFlags, delimiterCharacter, includeOOS)
}
programs = append(programs, pData)
}
}
}
offset += len(records)
if offset >= total {
break
}
}
return programs
}
// Function to check if an int is in a slice of ints
func isInArray(val int, array []int) bool {
for _, item := range array {
if item == val {
return true
}
}
return false
}