-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathnetscaler-content.sh
204 lines (186 loc) · 7.94 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
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
# Copyright 2020 FireEye, Inc. and Citrix Systems, Inc.
# FreeBSD/NetScaler bash doesn't support array declaration shortcut
# so we create the array by hand... I'm sorry.
declare -a ns_content_blacklist;
ns_content_blacklist[0]="template.new";
# don't match "execute" which is found in /netscaler/portal/templates/homepage.html
ns_content_blacklist[1]="exec[^u]";
ns_content_blacklist[2]="\`";
# /netscaler/portal/scripts/subscription.pl contains the line:
# eval(handle_subscriptions());
ns_content_blacklist[3]="eval([^h][^a][^n]";
ns_content_blacklist[4]="bash";
ns_content_blacklist[5]="ns.conf";
ns_content_blacklist[6]="curl";
ns_content_blacklist[7]="wget";
# seen in webshells
ns_content_blacklist[8]="Encode::decode(chr(";
ns_content_blacklist[9]="}exit";
# ref: https://github.com/projectzeroindia/CVE-2019-19781/blob/master/CVE-2019-19781.sh#L22
ns_content_blacklist[10]="pwnpzi1337";
ns_content_blacklist[11]="test1337";
# ref: https://github.com/trustedsec/cve-2019-19781/blob/master/citrixmash.py
ns_content_blacklist[12]="chr(";
# FireEye has seen actors copying the /flash/nsconfig/ns.conf file to a template so that it can be fetched remotely.
# Look for the header associated with the ns.conf file, like: `#NS12.1 Build 51.19`
ns_content_blacklist[13]="^\#NS";
# IP of host serving EternalBlue scanner/exploiter
ns_content_blacklist[14]="45.120.53.214";
ns_content_blacklist[15]="eternalblue.replay";
ns_content_blacklist[16]="scan.py";
ns_content_blacklist[17]="x64.dll";
ns_content_blacklist[18]="x86.dll";
ns_content_blacklist[19]="xp_eternalblue.replay";
# match filename `ld.sh` without matching `build.sh`
ns_content_blacklist[20]="[^i]ld.sh";
ns_content_blacklist[21]="piz.Lan";
# match filename `de.py` without matching `upgrade.py`
# see #9
ns_content_blacklist[22]="[^a]de.py";
ns_content_blacklist[23]=".new.zip";
ns_content_blacklist[24]="/tmp/rAgn";
# other activity
ns_content_blacklist[25]="198.44.227.126";
ns_content_blacklist[26]="/tmp/l.sh";
ns_content_blacklist[27]="Digest::MD5";
ns_content_blacklist[28]="Could not execute command";
# from subsequent NOTROBIN and/or APT41 blog posts from FEYE
ns_content_blacklist[29]="/tmp/bsd";
ns_content_blacklist[30]="/tmp/un";
ns_content_blacklist[31]="66.42.98.220";
ns_content_blacklist[32]="/var/nstmp/.nscache/prev.sh";
ns_content_blacklist[33]="/var/nstmp/.nscache/httpd-nscache_clean";
ns_content_blacklist[34]="/vpn/themes/imgs/tiny.php";
ns_content_blacklist[35]="/vpn/themes/imgs/debug.php";
ns_content_blacklist[36]="/vpn/themes/imgs/conn.php";
declare -a ns_exploit_dirs;
ns_exploit_dirs[0]="/netscaler/portal/templates/";
ns_exploit_dirs[1]="/netscaler/portal/scripts/";
# ref: https://github.com/x1sec/CVE-2019-19781/blob/master/CVE-2019-19781-DFIR.md
#
# note: this directory is synced between devices in an HA pair setup.
# this means that content dropped here by attackers onto a compromised device may
# be copied to the standby device.
# the standby device was not directly exploited, but does have attacker content.
# this should at least be cleaned, and possibly investigated.
ns_exploit_dirs[2]="/var/vpn/bookmark/";
ns_exploit_dirs[3]="/var/tmp/netscaler/portal/templates/";
ns_exploit_dirs[4]="/var/vpn/themes/";
ns_exploit_dirs[5]="/var/vpn/theme/";
# custom output formatting for matches.
# if the filename ends with .xml print the whole file,
# otherwise print the match as found
report_filename_or_cat_file_if_xml() {
local readonly fname="$1";
if [[ $fname = *2e786d6c ]]; then
# encoded name ends with .xml
report_encoded_file_name_and_contents "$fname";
else
report_encoded_file_name "$fname";
fi
}
report_ns_matches() {
entries="$1";
for entry in $entries; do
report_filename_or_cat_file_if_xml "$entry";
done
}
# Search the files in the given path for blacklisted terms.
# The blacklist is found above, at `ns_content_blacklist`.
#
# args:
# path - path to search, relative to root.
scan_ns_directory_content() {
local readonly path="$root_directory/$1";
if [ ! -d "$path" ]; then
debug "didn't find directory: $path";
return
fi
local found=false;
for re in "${ns_content_blacklist[@]}"; do
local findcmd="find -L $path -type f";
if [[ "$1" == "/var/vpn/bookmark/" ]]; then
# in bookmark directory, scan only non-xml files and xml files modified after 2019-12-15
findcmd="$findcmd -not -name "*.xml" -or -newermt "2019-12-15"";
fi
local entries=$($findcmd -exec grep -lI --null "$re" {} + | perl -0ne 'chomp; print(unpack("H*", $_), "\n")');
if [ -n "$entries" ]; then
found=true;
report_match "blacklisted content '$re'";
report "matches for '$re':";
report_ns_matches "$entries";
fi
done
if [ "$found" != true ]; then
debug "did not find blacklisted or suspicious content in $path";
fi
}
# Search the files in the given path for permissions like 'rw-r--r--' (644).
# It seems that files created during exploitation default to this mask.
#
# args:
# path - path to search, relative to root.
scan_ns_directory_perms() {
local readonly path="$root_directory/$1";
if [ ! -d "$path" ]; then
debug "didn't find directory: $path";
return
fi
# /var/vpn/bookmarks/ contains legit entries with prefix `bm_prefix_`
# on NetScaler versions after 13.0.47.24 (patch)
local entries=$(find "$path" -perm 644 -not -name "bm_prefix_*" -print0 | perl -0ne 'chomp; print(unpack("H*", $_), "\n")');
if [ -n "$entries" ]; then
report_match "incorrect file permissions";
report "files with permissions 644:";
report_ns_matches "$entries";
report "Please review the above paths for any unexpected files.";
report "Exploits commonly write to files with these permissions;"
report "however, customization of a Citrix NetScaler environment may cause false positives in the above list."
report "For example, '/var/vpn/bookmark/[legitimate-username].xml' may be valid in your environment."
else
debug "did not find incorrect permissions in $path";
fi
}
# Find files created in the templates directory that have been created since Jan 1, 2020.
# This seems to detect lots of activity; however, we're not sure how this interacts with patches and customizations.
# Disabled for now, with preference towards the permission scanner.
scan_ns_new_templates() {
if [ ! -d "$root_directory/netscaler/portal/templates" ]; then
debug "didn't find templates directory";
return;
fi
local readonly entries=$(find "$root_directory/netscaler/portal/templates/" -type f -newerct "2020-01-01" -print);
if [ -n "$entries" ]; then
report_match "recently created template";
report "recently created templates:";
report "$entries";
else
debug "did not find new files in /netscaler/portal/templates/.";
fi
}
# Find files created in the scripts directory that have been created since Jan 1, 2020.
# This seems to detect lots of activity; however, we're not sure how this interacts with patches and customizations.
# Disabled for now, with preference towards the permission scanner.
scan_ns_new_scripts() {
if [ ! -d "$root_directory/netscaler/portal/scripts" ]; then
debug "didn't find scripts directory";
return;
fi
local readonly entries=$(find "$root_directory/netscaler/portal/scripts/" -type f -newerct "2020-01-01" -print);
if [ -n "$entries" ]; then
report_match "recently created script";
report "recently created scripts:";
report "$entries";
else
debug "did not find new files in /netscaler/portal/scripts/.";
fi
}
scan_netscaler_content() {
for path in "${ns_exploit_dirs[@]}"; do
scan_ns_directory_content "$path";
scan_ns_directory_perms "$path";
done
# disabled, since we're not sure of the interaction with system updates and/or customizations.
#scan_ns_new_templates;
#scan_ns_new_scripts;
}