forked from mandiant/citrix-ioc-scanner-cve-2023-3519
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnetscaler-content.sh
150 lines (126 loc) · 5.35 KB
/
netscaler-content.sh
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
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# FreeBSD/NetScaler bash doesn't support array declaration shortcut
# so we create the array by hand... I'm sorry.
declare -a ns_content_denylist;
# look for strings found in most of the eval shells
ns_content_denylist[0]="http_response_code([0-9]\{3\})";
ns_content_denylist[1]="str_rot13(";
ns_content_denylist[2]="base64_decode(\$_POST";
ns_content_denylist[3]="@\\\$_POST".
ns_content_denylist[4]="eval(\$_POST";
ns_content_denylist[4]="eval(\$_GET";
ns_content_denylist[5]="Expires: Wed, 11 Jan 1984 05:00:00";
ns_content_denylist[6]="@eval(";
# REGEORG.NEO tunneler
ns_content_denylist[7]="blv_encode";
ns_content_denylist[8]="sayhello";
# SECRETSAUCE webshell
ns_content_denylist[9]="get('openssl_public_decrypt')";
# misc bad seen in webshells
ns_content_denylist[10]="#nssecret#";
ns_content_denylist[11]="uRemote";
# bishopfox https://github.com/BishopFox/CVE-2023-3519/
ns_content_denylist[12]="<?=\`curl";
# mass scanning
ns_content_denylist[13]="168\.100\.11\.89:8000";
# port scanner
ns_content_denylist[14]="github\.com/lcvvv/kscan";
# tunnelers
# look for printable strings left from the build process
declare -a ns_binary_content_denylist;
ns_binary_content_denylist[0]="ligolo-ng";
ns_binary_content_denylist[1]="sshd/server\.go";
ns_binary_content_denylist[2]="test/httpdemo/main\.go";
ns_binary_content_denylist[3]="ehang\.io/nps";
ns_binary_content_denylist[4]="\[library-to-inject\]";
ns_binary_content_denylist[5]="UPX executable";
report_ns_matches() {
entries="$1";
for entry in $entries; do
report_encoded_file_name "$entry";
done
}
# Search the files in the given path for denylisted terms.
# The denylist is found above, at `ns_content_denylist`.
scan_ns_directory_content() {
local readonly path="$root_directory";
if [ ! -d "$path" ]; then
debug "didn't find directory: $path";
return
fi
local found=false;
for re in "${ns_content_denylist[@]}"; do
local findcmd="find -EL $path -type f";
local entries=$($findcmd \( -not -path "/proc/*" -and -not -regex "/tmp/[0-9]{10}/.*" -and -not -regex "/var(/crash)?/nsproflog/newproflog.*" -and -not -regex "/var(/crash)?/log/notice.log" \) -exec grep -lI --null -e "$re" {} + | perl -0ne 'chomp; print(unpack("H*", $_), "\n")');
if [ -n "$entries" ]; then
found=true;
report_match "denylisted content '$re'";
report "matches for '$re':";
report_ns_matches "$entries";
fi
done
if [ "$found" != true ]; then
debug "did not find denylisted or suspicious content in $path";
fi
}
# scan binary files under 10mb for denylisted items. We do this separately so that we can
# look for webshells without scanning binary files unnecessarily
# The binary deny list is above at `ns_binary_content_denylist`
scan_ns_directory_binary_content() {
local readonly path="$root_directory";
if [ ! -d "$path" ]; then
debug "didn't find directory: $path";
return
fi
local found=false;
for re in "${ns_binary_content_denylist[@]}"; do
local findcmd="find -EL $path -type f -size -10M";
local entries=$($findcmd \( -not -path "/proc/*" -and -not -regex "/tmp/[0-9]{10}/.*" -and -not -regex "/var(/crash)?/nsproflog/newproflog.*" -and -not -regex "/var(/crash)?/log/notice.log" \) -exec grep -l --null -e "$re" {} + | perl -0ne 'chomp; print(unpack("H*", $_), "\n")');
if [ -n "$entries" ]; then
found=true;
report_match "denylisted content '$re' in binary file";
report "matches for '$re':";
report_ns_matches "$entries";
fi
done
if [ "$found" != true ]; then
debug "did not find denylisted or suspicious binary content in $path";
fi
}
# Search the files in the given path for nobody:root ownership
# This is relatively rare and a good indication of post-exploitation
# files being dropped
scan_ns_file_ownership() {
local readonly path="$root_directory";
if [ ! -d "$path" ]; then
debug "didn't find directory: $path";
return
fi
local entries=$(find -L "$path" -type f -user nobody -gid 0 -not -path "/proc/*" -exec file {} \; | egrep -i "script|html|executable|compressed|archive" | awk -F":" '{print $1}' | perl -0ne 'chomp; print(unpack("H*", $_), "\n")');
if [ -n "$entries" ]; then
report_permission_match "suspicious file ownership";
report "files with ownership nobody:root:";
report_ns_matches "$entries";
report "Please review the above paths for suspicious content.";
report "Exploits commonly write to files with these permissions;"
else
debug "did not find incorrect permissions in $path";
fi
}
scan_netscaler_content() {
scan_ns_directory_content;
scan_ns_directory_binary_content;
scan_ns_file_ownership;
}