-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbash.scanner
More file actions
242 lines (210 loc) · 7.74 KB
/
bash.scanner
File metadata and controls
242 lines (210 loc) · 7.74 KB
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
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
function scan_for_randomness() {
local file="$1" # Bash-Function-Args
echo "OK"
echo "$file"
echo "=========="
if [[ -z "$file" ]]; then
echo "Usage: scan_for_secrets <file>"
return 1
fi
if [[ ! -f "$file" ]]; then
echo "Error: File '$file' not found."
return 1
fi
while IFS= read -r line; do
measure_randomness "$line"
done < "$file"
}
function scan_for_secrets() {
local file="$1" # Bash-Function-Args
if [[ -z "$file" ]]; then
printCritical "Usage: scan_for_secrets <file>"
return 1
fi
if [[ ! -f "$file" ]]; then
printCritical "Error: File '$file' not found."
return 1
fi
#"password" # Password
#"passwd=[\"']?[^\"']{8,}[\"']?" # another common password pattern
#"passwd" # another common password pattern
#"token:[\"']?[^\"']{20,}[\"']?" # Token
#"token:" # Token
#"token" # Token
# Define patterns to search for (add/modify as needed)
local patterns=(
"([a-zA-Z0-9]){3,12}:([a-zA-Z0-9]){3,12}" #look for username:password type strings.
"key[[:space:]]*[:=][[:space:]]*[\"']?[^\"']*[\"']?" # Key pattern
"AIza[0-9a-zA-Z_-]{35}" # Google API Key
"sk_live_[0-9a-zA-Z_]{24}" # Stripe API Key
"password=[\"']?[^\"']{8,}[\"']?" # Password
"Authorization: Bearer [a-zA-Z0-9_-]+\\.[a-zA-Z0-9_-]+\\.[a-zA-Z0-9_-]+" # JWT
"AKIA[0-9A-Z]{16}" # AWS Access Key ID
"AKIA" # AWS Access Key ID
"API_KEY=[a-zA-Z0-9_-]{20,}"
"SECRET_KEY=[a-zA-Z0-9_-]{20,}"
"PASSWORD=[a-zA-Z0-9_-]{8,}"
"AWS_ACCESS_KEY_ID=[A-Z0-9]{20}"
"AWS_ACCESS_KEY_ID"
"AWS_SECRET_ACCESS_KEY=[A-Za-z0-9+/]{40}"
"AWS_SECRET_ACCESS_KEY"
"ssh-rsa [A-Za-z0-9+/=]{20,}"
"ssh-ed25519 [A-Za-z0-9+/=]{20,}"
"BEGIN RSA PRIVATE KEY"
"BEGIN PGP PRIVATE KEY BLOCK"
"BEGIN OPENSSH PRIVATE KEY"
"Bearer [A-Za-z0-9._-]{20,}"
"Authorization: Basic [A-Za-z0-9+/=]{20,}"
"Authorization: Token [A-Za-z0-9]{20,}"
"PGPASSWORD=[a-zA-Z0-9_-]{8,}" # postgres password
"DATABASE_URL=postgres://[a-zA-Z0-9_-]+:[a-zA-Z0-9_-]+@" # postgres database url, catches username and password.
"MONGO_URI=mongodb://[a-zA-Z0-9_-]+:[a-zA-Z0-9_-]+@" #mongodb uri, catches username and password
"password[[:space:]]*[:=][[:space:]]*[\"']?[^\"']*[\"']?" # Basic password pattern
"secret[[:space:]]*[:=][[:space:]]*[\"']?[^\"']*[\"']?" # Secret pattern
"AWS_ACCESS_KEY_ID[[:space:]]*[:=][[:space:]]*[\"']?[A-Z0-9]*[\"']?" # AWS Access Key ID
"AWS_SECRET_ACCESS_KEY[[:space:]]*[:=][[:space:]]*[\"']?[a-zA-Z0-9/+=]*[\"']?" # AWS Secret Access Key
"api_key[[:space:]]*[:=][[:space:]]*[\"']?[^\"']*[\"']?" # API Key pattern
"database_url[[:space:]]*[:=][[:space:]]*[\"']?[^\"']*[\"']?" # Database URL
"connection_string[[:space:]]*[:=][[:space:]]*[\"']?[^\"']*[\"']?" # Connection String
"private_key[[:space:]]*[:=][[:space:]]*[\"']?[^\"']*[\"']?" # Private Key
"client_secret[[:space:]]*[:=][[:space:]]*[\"']?[^\"']*[\"']?" # Client Secret
"oauth_token[[:space:]]*[:=][[:space:]]*[\"']?[^\"']*[\"']?" # OAuth Token
"bearer_token[[:space:]]*[:=][[:space:]]*[\"']?[^\"']*[\"']?" # Bearer Token
)
# "export [A-Z_]+=[\"']?[A-Za-z0-9_\\-./+=@$%^&*()!~`?<>:;']+" # look for exported environment variables.
local found=0
local overide=0
printDebug "SCAN: '$file'"
for pattern in "${patterns[@]}"; do
# printDebug "PATTERN: '$pattern'"
if grep -E "$pattern" "$file" > /dev/null; then
found=1
printCritical "Potential secret found in '$file' matching pattern: '$pattern'"
printCritical ""
grep --color=always -E -n "$pattern" "$file" | gawk '{print $0;print ""}'
#./finder "$pattern" "$file"
if grep -E "SCANPASS" "$file" > /dev/null; then
overide=1
found=0
else
break
fi
else
NOTHING=0
fi
done
if [[ "$overide" -eq 1 ]]; then
printCritical ""
printCritical "$(szred "************************************************")
printCritical "$(szred "** Potential secret found")
printCritical "$(szred "** Scan Pass Overides Exercised")
printCritical "$(szred "************************************************")
printCritical ""
fi
if [[ "$found" -eq 1 ]]; then
NOTHING=0
return 1
fi
#printCritical "COMPLETE COMPLETE"
if [[ "$found" -eq 0 ]]; then
NOTHING=0
#printDebug "CLEAR: '$file'"
#append_last_element "$(szgreen " OK")"
#append_last_element " OK"
fi
return 0
}
function measure_randomness_uniqueness {
local str="$1"
local length="${#str}"
if [[ -z "$str" ]]; then
echo 1 # Empty string has least randomness
return
fi
local -A char_counts
local char
for ((i=0; i<length; i++)); do
char="${str:i:1}"
((char_counts["$char"]++))
done
local max_count=0
for count in "${char_counts[@]}"; do
if [[ "$count" -gt "$max_count" ]]; then
max_count="$count"
fi
done
# Calculate a simple randomness score.
# A higher max_count (more frequent character) means less randomness.
# We normalize it to the length of the string.
local homogeneity_percentage=$(( (max_count * 100) / length ))
# Invert the homogeneity to get a randomness score.
# Scale it to be between 1 and 100.
local randomness_score=$(( 100 - homogeneity_percentage + 1 ))
echo "$randomness_score"
}
function measure_randomness {
local str="$1"
str=$(echo "$str" | sed 's/[^[:alnum:]]//g')
local length="${#str}"
local R=$(calculate_case_ratio "$str")
if [[ -z "$str" ]]; then
echo 1 # Empty string has least randomness
return
fi
local -A char_counts
local char
for ((i=0; i<length; i++)); do
char="${str:i:1}"
((char_counts["$char"]++))
done
local entropy=0.0
local probability
for count in "${char_counts[@]}"; do
probability=$(echo "scale=6; $count / $length" | bc) # Calculate probability
entropy=$(echo "scale=6; $entropy - ($probability * l($probability) / l(2))" | bc -l) # Calculate entropy
done
# Scale entropy to a 1-100 range. Maximum entropy for a given length
# occurs when all characters are unique and evenly distributed.
# We'll approximate the maximum entropy and scale relative to that.
# A more accurate approach would involve calculating the theoretical maximum
# entropy for the given string length and character set, but this approximation
# is sufficient for demonstration.
local max_entropy=$(echo "scale=6; l($length) / l(2)" | bc -l) # Approximation.
if (( $(echo "$max_entropy == 0" | bc -l) )); then
echo 1
return
fi
local randomness_score=$(echo "scale=0; 1 + (99 * $entropy / $max_entropy)" | bc)
# Ensure the score is within the desired range
if (( $(echo "$randomness_score < 1" | bc -l) )); then
randomness_score=1
elif (( $(echo "$randomness_score > 100" | bc -l) )); then
randomness_score=100
fi
echo "$randomness_score: $R: $1"
}
calculate_case_ratio() {
local input_string="$1"
local upper_count=0
local lower_count=0
# Remove all non-alphanumeric characters
local alphanumeric_string=$(echo "$input_string" | sed 's/[^[:alnum:]]//g')
# Iterate through the alphanumeric string
for ((i=0; i<${#alphanumeric_string}; i++)); do
local char="${alphanumeric_string:i:1}"
if [[ "$char" =~ [[:upper:]] ]]; then
((upper_count++))
elif [[ "$char" =~ [[:lower:]] ]]; then
((lower_count++))
fi
done
# Calculate the ratio, avoiding division by zero
if [[ "$lower_count" -gt 0 ]]; then
local ratio=$(echo "scale=2; $upper_count / $lower_count" | bc)
echo "$ratio"
else
# If no lowercase characters, return a special value (e.g., -1 or "infinity")
# Here, we'll return -1 to indicate no lowercase characters
echo "-1"
fi
}