/
opt
/
dedrads
/
/opt/dedrads
mkdir
upload
Name
Size
Mode
Actions
account_review/
-
0555
rm
check_software_mods/
-
0555
rm
cms_tools/
-
0555
rm
etc/
-
0555
rm
extras/
-
0555
rm
mailparse/
-
0555
rm
mysql/
-
0555
rm
nlp_scripts/
-
0555
rm
oldrads/
-
0555
rm
perl/
-
0555
rm
provision/
-
0555
rm
python/
-
0555
rm
suspended/
-
0555
rm
__pycache__/
-
0555
rm
account-review
799
0555
edit
dl
rm
allfw
6259
0555
edit
dl
rm
alp.py
16553
0555
edit
dl
rm
autossl_sync
6267
0555
edit
dl
rm
check_apache
9205
0555
edit
dl
rm
check_bandwidth
4546
0555
edit
dl
rm
check_boxtrapper
1684
0555
edit
dl
rm
check_cpu
12212
0555
edit
dl
rm
check_crons
1827
0555
edit
dl
rm
check_dcpumon
1973
0555
edit
dl
rm
check_dns
1827
0555
edit
dl
rm
check_domlogs
61
0555
edit
dl
rm
check_exim
3731
0555
edit
dl
rm
check_hacks
22604
0555
edit
dl
rm
check_imap
5249
0555
edit
dl
rm
check_io
6635
0555
edit
dl
rm
check_max_children
16341
0555
edit
dl
rm
check_mem
1660
0555
edit
dl
rm
check_misc
1510
0555
edit
dl
rm
check_pacct
5201
0555
edit
dl
rm
check_php
4344
0555
edit
dl
rm
check_pop3
2295
0555
edit
dl
rm
check_prov.py
4714
0555
edit
dl
rm
check_server
696
0555
edit
dl
rm
check_size
490
0555
edit
dl
rm
check_software
9849
0555
edit
dl
rm
check_spamd
2426
0555
edit
dl
rm
check_traffic
1933
0555
edit
dl
rm
check_user
1887
0555
edit
dl
rm
clean_exim.py
6390
0555
edit
dl
rm
clusterfix
5343
0555
edit
dl
rm
cmspass.py
3970
0555
edit
dl
rm
cms_check.py
9825
0555
edit
dl
rm
cms_counter.py
36734
0555
edit
dl
rm
cms_creds
713
0555
edit
dl
rm
cms_dumpdb
4485
0555
edit
dl
rm
cms_pw
1416
0555
edit
dl
rm
cpanel-api
7040
0555
edit
dl
rm
cpanel_postgres_manager.py
29004
0555
edit
dl
rm
cpmerge
4631
0555
edit
dl
rm
cpumon
2195
0555
edit
dl
rm
dcpumon.pl
1239
0555
edit
dl
rm
dedcheck
18127
0555
edit
dl
rm
dns-sync
14386
0555
edit
dl
rm
docroot.py
4425
0555
edit
dl
rm
du-tree
7450
0555
edit
dl
rm
envinfo.py
6633
0555
edit
dl
rm
exclude_rbl.py
5249
0555
edit
dl
rm
extract-vhost
2691
0555
edit
dl
rm
filescan
3566
0555
edit
dl
rm
find_warez
1460
0555
edit
dl
rm
first_setup.py
19120
0555
edit
dl
rm
fixwpcron.py
4822
0555
edit
dl
rm
fix_dns_cluster
353
0555
edit
dl
rm
goaccess
1217720
0555
edit
dl
rm
hostsfilemods
4467
0555
edit
dl
rm
imap_io
2323
0555
edit
dl
rm
innodb_converter.py
9343
0555
edit
dl
rm
killall911
530
0555
edit
dl
rm
killdns
941
0555
edit
dl
rm
lastcommcache.sh
1374
0555
edit
dl
rm
legal_lock_down.sh
7450
0555
edit
dl
rm
lil-cpanel
52002
0555
edit
dl
rm
listacct
4575
0555
edit
dl
rm
mailscan
4544
0555
edit
dl
rm
mail_sources.py
7407
0555
edit
dl
rm
megaclisas-status
38664
0555
edit
dl
rm
migrate2central.sh
14418
0555
edit
dl
rm
modify-account
40631
0555
edit
dl
rm
modsec_disable.py
11461
0555
edit
dl
rm
monarxctl
8912
0555
edit
dl
rm
msp.pl
27714
0555
edit
dl
rm
mysql_dstat
474
0555
edit
dl
rm
mysql_selector.py
73102
0555
edit
dl
rm
nlp
4582
0555
edit
dl
rm
procscrape
1863
0555
edit
dl
rm
quarantine
11083
0555
edit
dl
rm
radsfunctions.sh
863
0555
edit
dl
rm
recent-cp
16148
0555
edit
dl
rm
remote_dump
18347
0555
edit
dl
rm
reset_cpanel
3205
0555
edit
dl
rm
server-load
2192
0555
edit
dl
rm
show-conns
20105
0555
edit
dl
rm
show-conns-adv.py
54667
0555
edit
dl
rm
sparta.py
382498
0555
edit
dl
rm
sqltop
27129
0555
edit
dl
rm
telcheck
2411
0555
edit
dl
rm
temprootreset
186
0555
edit
dl
rm
unsuspend_user
1307
0555
edit
dl
rm
unsusprunner.sh
1840
0555
edit
dl
rm
updatednsadmin
526
0555
edit
dl
rm
update_spf
14972
0555
edit
dl
rm
upgrade-check
9216
0555
edit
dl
rm
vhost_data.py
6221
0555
edit
dl
rm
wp-xray.sh
85816
0555
edit
dl
rm
Edit:
/opt/dedrads/cms_check.py
(9825B)
#!/usr/lib/rads/venv/bin/python3 from pathlib import Path import argparse import json import subprocess import os import time import re import yaml from rads.color import green, yellow, bold, blue, red class Fingerprint: """Fingerprint to find a CMS installation.""" def __init__(self, cms, fp_data): self.cms = cms self.fp_data = fp_data self.filename = fp_data.get("file") self.signature = fp_data.get("signature") self.excludes = {2: ["softaculous"], 3: ["quarantine"]} self.paths_found = [] def search(self): """Uses mlocate to search for the file signature.""" cmd = [ "/bin/locate", "-d", "/var/lib/mlocate/mlocate.db", self.filename, ] with subprocess.Popen( cmd, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, encoding='utf-8', ) as proc: for out_line in proc.stdout: line = out_line.strip() if not os.path.exists(line) or self.should_exclude(line): continue if self.signature: with open(line, encoding="utf-8") as stream: match = re.search(self.signature, stream.read()) if match: self.paths_found.append(line) else: self.cms.main.print_debug( red(f"{self.signature} not found within {line}") ) else: self.paths_found.append(line) def should_exclude(self, path): """Determines whether or not the path should be excluded. Args: path (str): found path Returns: bool: True if should be excluded, else False """ self.cms.main.print_debug(f"Checking excludes on {path}") pos_path = Path(path) if "/" in self.filename: if self.filename not in path: self.cms.main.print_debug( red( f"excluded: {pos_path.name} does not match " f"{self.filename}." ) ) return True else: if pos_path.name != self.filename: self.cms.main.print_debug( red( f"excluded: {pos_path.name} does not " f"match {self.filename}." ) ) return True for index, part in enumerate(pos_path.parts): if index in self.excludes: if part in self.excludes[index]: self.cms.main.print_debug( red( f"excluded: excluded part, {part} " f"in {pos_path.parts}" ) ) return True if not self.cms.main.args.include_all: for docroot_path in self.cms.main.document_roots: if docroot_path in pos_path.parents: return False else: return False self.cms.main.print_debug( red(f"excluded: didn't determine if we shouldn't exclude: {path}") ) return True class CMS: def __init__(self, cms_search: 'CMSSearch', name, data): self.main = cms_search self.name = name self.data = data self.actual_name = name self.fingerprints = [] self.versions = [] def load(self): """Loads the actual name and the fingerprints from the CMS Signature data. """ self.actual_name = self.data.get("name") for fingerprint in self.data.get("fingerprints", []): fp = Fingerprint(self, fingerprint) fp.search() self.fingerprints.append(fp) def found_installations(self): """Returns all installation paths found for the first fingerprint that found an installation. Returns: dict: key, value dictionary of path and docroot domain. """ all_paths = {} for fp in self.fingerprints: if len(fp.paths_found) > 0: for path in fp.paths_found: all_paths[path] = self.main.find_docroot_domain(path) return all_paths return all_paths class CMSSearch: def __init__(self, args): self.document_roots = {} self.args = args self.installs = {} def run(self): """Primary run entry to begin CMS search.""" self.collect_docroots() self.load_cms_data() self.display_results() def print_debug(self, message): """Prints a debug message if verbose is enabled. Args: message (str): the message to print """ if self.args.verbose: print(blue(message)) def display_results(self): """Lists all found installations in a specific format based on given flags. """ out_json = {"cms": {}} for cms_name, cms_obj in self.installs.items(): cms_obj: 'CMS' installs = cms_obj.found_installations() actual_name = cms_obj.actual_name if len(installs) > 0: if self.args.output == "simple": print(cms_name, installs) elif self.args.output == "normal": print(bold(yellow(actual_name))) for install in installs: domain = green(installs[install]) print(f"{domain}: {install}") print() elif self.args.output == "json": for install in installs: domain = installs[install] if actual_name not in out_json["cms"]: out_json["cms"][actual_name] = {} if domain not in out_json["cms"][actual_name]: out_json["cms"][actual_name][domain] = [] out_json["cms"][actual_name][domain].append(domain) if self.args.output == "json": print(json.dumps(out_json)) def load_cms_data(self): """Safely loads the CMS signatures from a yaml file.""" with open( "/opt/dedrads/extras/cms_signatures.yaml", encoding="utf-8" ) as infile: try: cms_yaml = yaml.load(infile, Loader=yaml.SafeLoader) for cms_name in cms_yaml: cms = CMS(self, cms_name, cms_yaml[cms_name]) cms.load() self.installs[cms_name] = cms except yaml.YAMLError as err: print(err) def find_docroot_domain(self, path): """Returns a domain for the document root that the provided path belongs to. Args: path (str): path of the installation Returns: str: domain of the document root """ for docroot_path, domain in self.document_roots.items(): if docroot_path in Path(path).parents: return domain return "no-domain" def collect_docroots(self): """Collects all document roots from cPanel.""" for user_folder in Path("/var/cpanel/userdata/").glob("*"): for user_item in Path(user_folder).glob("*"): with open(user_item, encoding="utf-8") as stream: docroot = "" servername = "" for line in stream.readlines(): if line.startswith("documentroot:"): docroot = Path(line.split()[1].strip()) if line.startswith("servername:"): servername = line.split()[1].strip() if docroot and servername: self.document_roots[docroot] = servername def check_db_age(self): """ Checks the mlocate database modification age and runs update if older than 24 hours. """ mtime = os.path.getmtime("/var/lib/mlocate/mlocate.db") diff = time.time() - mtime if diff > 86400: if self.args.output != "json": print(yellow("Locate DB is too old, running update.")) self.update_db() def update_db(self): """Updates the mlocate database.""" ret_code = subprocess.call(["/bin/updatedb"]) if self.args.output == "json": return if ret_code: print(red("Failed to update mlocate database.")) else: print(green("Updated mlocate database.")) def parse_args(): args = argparse.ArgumentParser( description=( "Uses signatures to determine what CMS installations are " "installed on the server." ) ) output_choices = ["json", "simple", "normal"] args.add_argument( "--output", nargs="?", help="type of output", choices=output_choices, default="normal", ) args.add_argument( "--include-all", action="store_true", help=( "Includes all installations, including those not in a " "document root." ), ) args.add_argument("--verbose", action="store_true", help="Verbose output.") return args.parse_args() def main(): args = parse_args() cms_searcher = CMSSearch(args) cms_searcher.check_db_age() cms_searcher.run() if __name__ == "__main__": main()
Save
cmd:
run