Edit File by line
/home/barbar84/public_h.../wp-conte.../plugins/sujqvwi/ExeBy/smexe_ro.../opt/maint/bin
File: secureperms.py
#!/opt/imh-python/bin/python3
[0] Fix | Delete
"""Script to fix common security issues on shared servers"""
[1] Fix | Delete
from pathlib import Path
[2] Fix | Delete
import platform
[3] Fix | Delete
from os import chown
[4] Fix | Delete
import pwd
[5] Fix | Delete
import grp
[6] Fix | Delete
from stat import S_IWGRP, S_IWOTH, S_IMODE
[7] Fix | Delete
from subprocess import run, DEVNULL
[8] Fix | Delete
import distro
[9] Fix | Delete
import rads
[10] Fix | Delete
[11] Fix | Delete
[12] Fix | Delete
def main():
[13] Fix | Delete
users = rads.all_cpusers(owners=False)
[14] Fix | Delete
print("Checking /home...")
[15] Fix | Delete
set_perms(Path('/home'), 0o711, (0, 0), 'root:root')
[16] Fix | Delete
print("Removing shell access for unauthorized users...")
[17] Fix | Delete
check_shells(users)
[18] Fix | Delete
if not IS_SUPHP:
[19] Fix | Delete
return
[20] Fix | Delete
print("Checking user home folder permissions...")
[21] Fix | Delete
nobody_gid = grp.getgrnam('nobody').gr_gid
[22] Fix | Delete
for user in users:
[23] Fix | Delete
fix_user_perms(user, nobody_gid)
[24] Fix | Delete
[25] Fix | Delete
[26] Fix | Delete
def check_shells(users: list[str]):
[27] Fix | Delete
"""Remove shell access for users that shouldn't have it"""
[28] Fix | Delete
if distro.id() == 'cloudlinux':
[29] Fix | Delete
print("CloudLinux server detected. Allowing /bin/bash shells")
[30] Fix | Delete
main_shell = '/bin/bash'
[31] Fix | Delete
else:
[32] Fix | Delete
main_shell = '/usr/local/cpanel/bin/jailshell'
[33] Fix | Delete
allowed_shells = (main_shell, '/usr/local/cpanel/bin/noshell')
[34] Fix | Delete
reload_crond = False
[35] Fix | Delete
for user in users:
[36] Fix | Delete
if user in rads.SYS_USERS:
[37] Fix | Delete
continue
[38] Fix | Delete
try:
[39] Fix | Delete
user_shell = pwd.getpwnam(user).pw_shell
[40] Fix | Delete
except KeyError:
[41] Fix | Delete
continue
[42] Fix | Delete
if user_shell in allowed_shells:
[43] Fix | Delete
continue
[44] Fix | Delete
reload_crond = True
[45] Fix | Delete
LOGGER.info(
[46] Fix | Delete
'Changing shell of %s from %s to %s',
[47] Fix | Delete
user,
[48] Fix | Delete
user_shell,
[49] Fix | Delete
main_shell,
[50] Fix | Delete
)
[51] Fix | Delete
chsh = ['chsh', '-s', main_shell, user]
[52] Fix | Delete
run(chsh, stdout=DEVNULL, check=False)
[53] Fix | Delete
# fmt: off
[54] Fix | Delete
sed = [
[55] Fix | Delete
'sed', '-i', f"s@{user_shell}@{main_shell}@g",
[56] Fix | Delete
f'/var/spool/cron/{user}',
[57] Fix | Delete
]
[58] Fix | Delete
# fmt: on
[59] Fix | Delete
run(sed, stdout=DEVNULL, check=False)
[60] Fix | Delete
if reload_crond:
[61] Fix | Delete
run(['service', 'crond', 'reload'], stdout=DEVNULL, check=False)
[62] Fix | Delete
[63] Fix | Delete
[64] Fix | Delete
def set_perms(
[65] Fix | Delete
path: Path, new_mode: int, uid_gid: tuple[int, int], usr_grp: str
[66] Fix | Delete
):
[67] Fix | Delete
try:
[68] Fix | Delete
stat = path.stat()
[69] Fix | Delete
except OSError:
[70] Fix | Delete
return
[71] Fix | Delete
cur_mode = S_IMODE(stat.st_mode)
[72] Fix | Delete
if cur_mode != new_mode:
[73] Fix | Delete
path.chmod(new_mode)
[74] Fix | Delete
LOGGER.info(
[75] Fix | Delete
'%s --> Changed mode from %s to %s',
[76] Fix | Delete
path,
[77] Fix | Delete
oct(cur_mode)[2:],
[78] Fix | Delete
oct(new_mode)[2:],
[79] Fix | Delete
)
[80] Fix | Delete
if uid_gid != (stat.st_uid, stat.st_gid):
[81] Fix | Delete
chown(path, uid_gid[0], uid_gid[1])
[82] Fix | Delete
LOGGER.info('%s --> Changed owner:group to %s', path, usr_grp)
[83] Fix | Delete
[84] Fix | Delete
[85] Fix | Delete
def fix_user_perms(user: str, nobody_gid: int):
[86] Fix | Delete
try:
[87] Fix | Delete
info = pwd.getpwnam(user)
[88] Fix | Delete
except rads.CpuserError as exc:
[89] Fix | Delete
LOGGER.error(exc)
[90] Fix | Delete
return
[91] Fix | Delete
homedir = Path(info.pw_dir)
[92] Fix | Delete
if (
[93] Fix | Delete
info.pw_dir == '/home'
[94] Fix | Delete
or not info.pw_dir.startswith('/home')
[95] Fix | Delete
or not homedir.is_dir()
[96] Fix | Delete
):
[97] Fix | Delete
return
[98] Fix | Delete
if info.pw_uid == 0: # malicious cpmove restores can do this
[99] Fix | Delete
rads.send_email(
[100] Fix | Delete
'steam@imhadmin.net',
[101] Fix | Delete
subject='SECURITY: cPanel user with UID of 0',
[102] Fix | Delete
body=f"secureperms found {user}@{platform.node()} has a UID of 0",
[103] Fix | Delete
)
[104] Fix | Delete
return
[105] Fix | Delete
set_perms(
[106] Fix | Delete
homedir,
[107] Fix | Delete
0o711,
[108] Fix | Delete
(info.pw_uid, info.pw_gid),
[109] Fix | Delete
f'{user}:{user}',
[110] Fix | Delete
)
[111] Fix | Delete
set_perms(
[112] Fix | Delete
homedir / 'public_html',
[113] Fix | Delete
0o750,
[114] Fix | Delete
(info.pw_uid, nobody_gid),
[115] Fix | Delete
f'{user}:nobody',
[116] Fix | Delete
)
[117] Fix | Delete
set_perms(
[118] Fix | Delete
homedir / '.my.cnf',
[119] Fix | Delete
0o600,
[120] Fix | Delete
(info.pw_uid, info.pw_gid),
[121] Fix | Delete
f'{user}:{user}',
[122] Fix | Delete
)
[123] Fix | Delete
# check if homedir/logs is writable by group or world
[124] Fix | Delete
try:
[125] Fix | Delete
logs_mode = (homedir / 'logs').stat().st_mode
[126] Fix | Delete
except OSError:
[127] Fix | Delete
logs_mode = 0
[128] Fix | Delete
if logs_mode & S_IWOTH or logs_mode & S_IWGRP:
[129] Fix | Delete
set_perms(
[130] Fix | Delete
homedir / 'logs',
[131] Fix | Delete
0o700,
[132] Fix | Delete
(info.pw_uid, info.pw_gid),
[133] Fix | Delete
f'{user}:{user}',
[134] Fix | Delete
)
[135] Fix | Delete
# fix docroot perms
[136] Fix | Delete
try:
[137] Fix | Delete
userdata = rads.UserData(user)
[138] Fix | Delete
except rads.CpuserError:
[139] Fix | Delete
LOGGER.error(exc)
[140] Fix | Delete
return
[141] Fix | Delete
for docroot in map(Path, userdata.all_roots):
[142] Fix | Delete
set_perms(
[143] Fix | Delete
docroot,
[144] Fix | Delete
0o750,
[145] Fix | Delete
(info.pw_uid, nobody_gid),
[146] Fix | Delete
f'{user}:nobody',
[147] Fix | Delete
)
[148] Fix | Delete
[149] Fix | Delete
[150] Fix | Delete
if __name__ == '__main__':
[151] Fix | Delete
# cron config appends stdout/err to /var/log/maint/secureperms.log
[152] Fix | Delete
LOGGER = rads.setup_logging(
[153] Fix | Delete
path=None, name='secureperms', print_out='stdout', loglevel='INFO'
[154] Fix | Delete
)
[155] Fix | Delete
IS_SUPHP = Path('/etc/apache2/conf.modules.d/90-suphp.conf').is_file()
[156] Fix | Delete
main()
[157] Fix | Delete
[158] Fix | Delete
It is recommended that you Edit text format, this type of Fix handles quite a lot in one request
Function