Edit File by line
/home/barbar84/www/wp-conte.../plugins/sujqvwi/ShExBy/smshex_r.../opt/sharedra...
File: modsec_disable.py
#!/opt/imh-python/bin/python3
[0] Fix | Delete
[1] Fix | Delete
"""Written by Quentin H
[2] Fix | Delete
"""
[3] Fix | Delete
[4] Fix | Delete
[5] Fix | Delete
import subprocess
[6] Fix | Delete
import argparse
[7] Fix | Delete
from pathlib import Path
[8] Fix | Delete
import sys
[9] Fix | Delete
from rads.color import red, green
[10] Fix | Delete
[11] Fix | Delete
# Set the lock path to /tmp as a placeholder
[12] Fix | Delete
lock_file = Path("/tmp/modsec_disable.lock")
[13] Fix | Delete
platformI = Path("/etc/ansible/wordpress-ultrastack")
[14] Fix | Delete
[15] Fix | Delete
# Ensure that only one instance of the script runs at a time.
[16] Fix | Delete
def get_lock():
[17] Fix | Delete
if lock_file.exists():
[18] Fix | Delete
print(red("Another instance of the script is currently running. Exiting."))
[19] Fix | Delete
sys.exit(1)
[20] Fix | Delete
lock_file.touch() # Create a lock file to indicate the script is running
[21] Fix | Delete
[22] Fix | Delete
# Release the lock after the script has completed.
[23] Fix | Delete
def release_lock():
[24] Fix | Delete
lock_file.unlink(missing_ok=True)
[25] Fix | Delete
[26] Fix | Delete
# Check if Nginx exists
[27] Fix | Delete
def check_nginx():
[28] Fix | Delete
nginx_dir = Path("/var/log/nginx/")
[29] Fix | Delete
return nginx_dir.exists()
[30] Fix | Delete
[31] Fix | Delete
# Get Apache version
[32] Fix | Delete
def get_apache_version():
[33] Fix | Delete
try:
[34] Fix | Delete
result = subprocess.run(["apachectl", "-v"], capture_output=True, text=True, check=True)
[35] Fix | Delete
except FileNotFoundError:
[36] Fix | Delete
print(red("apachectl not found. Please ensure Apache is installed."))
[37] Fix | Delete
exit(1)
[38] Fix | Delete
except subprocess.CalledProcessError:
[39] Fix | Delete
print(red("Failed to get Apache version."))
[40] Fix | Delete
exit(1)
[41] Fix | Delete
if "Server version" in result.stdout:
[42] Fix | Delete
version_line = result.stdout.split('\n')[0]
[43] Fix | Delete
version = version_line.split()[2]
[44] Fix | Delete
return version.split('/')[1]
[45] Fix | Delete
print(red("Unable to parse Apache version."))
[46] Fix | Delete
exit(1)
[47] Fix | Delete
[48] Fix | Delete
# Update modsec.conf file based on provided arguments.
[49] Fix | Delete
def update_modsec_configuration(modsec_file, rule_ids=None, disable_all=False, reset=False, remove_rule_id=None):
[50] Fix | Delete
modsec_file.parent.mkdir(parents=True, exist_ok=True) # Ensure the directory exists
[51] Fix | Delete
# Ensure the modsec.conf file exists before modifying it
[52] Fix | Delete
if not modsec_file.exists() or reset:
[53] Fix | Delete
modsec_file.write_text("") # Create or reset the file if necessary
[54] Fix | Delete
[55] Fix | Delete
if disable_all:
[56] Fix | Delete
modsec_file.write_text("SecRuleEngine Off\n")
[57] Fix | Delete
elif rule_ids:
[58] Fix | Delete
for rule_id in rule_ids:
[59] Fix | Delete
disable_rule(modsec_file, rule_id)
[60] Fix | Delete
elif remove_rule_id:
[61] Fix | Delete
for rule_id in remove_rule_id:
[62] Fix | Delete
remove_rule(modsec_file, rule_id)
[63] Fix | Delete
[64] Fix | Delete
# Add rules to modsec.conf, checks if the rule exists and skips it if it does
[65] Fix | Delete
def disable_rule(modsec_file, rule_id):
[66] Fix | Delete
rule_text = f"SecRuleRemoveById {rule_id}"
[67] Fix | Delete
contents = ""
[68] Fix | Delete
if modsec_file.exists():
[69] Fix | Delete
with modsec_file.open("r+") as file:
[70] Fix | Delete
contents = file.read()
[71] Fix | Delete
if rule_text in contents:
[72] Fix | Delete
print(red(f"Rule {rule_id} already disabled, not adding."))
[73] Fix | Delete
return
[74] Fix | Delete
with modsec_file.open("a") as file:
[75] Fix | Delete
file.write(f"{rule_text}\n")
[76] Fix | Delete
print(green(f"Rule {rule_id} added to file: {modsec_file}"))
[77] Fix | Delete
[78] Fix | Delete
# Remove a rule from the modsec file.
[79] Fix | Delete
def remove_rule(modsec_file, rule_id):
[80] Fix | Delete
rule_text = f"SecRuleRemoveById {rule_id}"
[81] Fix | Delete
if modsec_file.exists():
[82] Fix | Delete
with modsec_file.open("r+") as file:
[83] Fix | Delete
contents = file.readlines()
[84] Fix | Delete
file.seek(0)
[85] Fix | Delete
file.truncate()
[86] Fix | Delete
for line in contents:
[87] Fix | Delete
if rule_text not in line:
[88] Fix | Delete
file.write(line)
[89] Fix | Delete
print(green(f"Rule {rule_id} removed from file: {modsec_file}"))
[90] Fix | Delete
[91] Fix | Delete
# Remove all SecRuleRemoveById and SecRuleEngine entries from the modsec file.
[92] Fix | Delete
def reset_modsec_configuration(modsec_file):
[93] Fix | Delete
if modsec_file.exists():
[94] Fix | Delete
with modsec_file.open("r+") as file:
[95] Fix | Delete
contents = file.readlines()
[96] Fix | Delete
file.seek(0)
[97] Fix | Delete
file.truncate()
[98] Fix | Delete
for line in contents:
[99] Fix | Delete
if not (line.startswith("SecRuleRemoveById") or line.startswith("SecRuleEngine Off")):
[100] Fix | Delete
file.write(line)
[101] Fix | Delete
print(green(f"All SecRuleRemoveById and SecRuleEngine entries removed from file: {modsec_file}"))
[102] Fix | Delete
[103] Fix | Delete
# Rebuild and restart Apache.
[104] Fix | Delete
def cpanel_restart_apache():
[105] Fix | Delete
subprocess.run(["/scripts/rebuildhttpdconf"])
[106] Fix | Delete
subprocess.run(["/sbin/apachectl", "graceful"])
[107] Fix | Delete
print(green("Apache configuration rebuilt and service restarted gracefully."))
[108] Fix | Delete
[109] Fix | Delete
def platformI_restart_apache():
[110] Fix | Delete
try:
[111] Fix | Delete
subprocess.run(["apachectl", "-t"])
[112] Fix | Delete
except subprocess.CalledProcessError:
[113] Fix | Delete
print(red("Syntax failed apache check"))
[114] Fix | Delete
exit(1)
[115] Fix | Delete
try:
[116] Fix | Delete
subprocess.run(["systemctl", "restart", "httpd"])
[117] Fix | Delete
print(green("Apache restarted correctly."))
[118] Fix | Delete
except subprocess.CalledProcessError:
[119] Fix | Delete
print(red("Apache failed to restart"))
[120] Fix | Delete
exit(1)
[121] Fix | Delete
[122] Fix | Delete
# Run ngxconf if Nginx exists
[123] Fix | Delete
def cpanel_run_ngxconf(user):
[124] Fix | Delete
subprocess.run(["ngxconf", "-u", user, "-rd"])
[125] Fix | Delete
[126] Fix | Delete
# Function to handle platformI check and set the modsec file path
[127] Fix | Delete
def platformI_modsec(args):
[128] Fix | Delete
modsec_file_path = Path("/etc/httpd/modsecurity.d/activated_rules/z-mycustom.conf")
[129] Fix | Delete
update_modsec_configuration(
[130] Fix | Delete
modsec_file=modsec_file_path,
[131] Fix | Delete
rule_ids=args.rule if args.rule else None,
[132] Fix | Delete
disable_all=args.off,
[133] Fix | Delete
reset=args.reset,
[134] Fix | Delete
remove_rule_id=args.drop
[135] Fix | Delete
)
[136] Fix | Delete
if args.reset:
[137] Fix | Delete
reset_modsec_configuration(modsec_file_path)
[138] Fix | Delete
platformI_restart_apache()
[139] Fix | Delete
[140] Fix | Delete
# Cpanel function that sets the modsec.conf file based on the flags/args passed to the script
[141] Fix | Delete
def cpanel_modsec(args):
[142] Fix | Delete
if not args.user:
[143] Fix | Delete
print(red("The --user (-u) flag is required for CPanel operations."))
[144] Fix | Delete
sys.exit(1)
[145] Fix | Delete
[146] Fix | Delete
try:
[147] Fix | Delete
apache_version = get_apache_version()
[148] Fix | Delete
if apache_version.startswith("2.4"):
[149] Fix | Delete
std_apache_dir = Path("/usr/local/apache/conf/userdata/std/2_4")
[150] Fix | Delete
ssl_apache_dir = Path("/usr/local/apache/conf/userdata/ssl/2_4")
[151] Fix | Delete
elif apache_version.startswith("2."):
[152] Fix | Delete
std_apache_dir = Path("/usr/local/apache/conf/userdata/std/2")
[153] Fix | Delete
ssl_apache_dir = Path("/usr/local/apache/conf/userdata/ssl/2")
[154] Fix | Delete
else:
[155] Fix | Delete
print(red(f"Unsupported Apache version {apache_version}."))
[156] Fix | Delete
exit(1)
[157] Fix | Delete
[158] Fix | Delete
# Determine the correct modsec_file path based on the presence of the domain flag
[159] Fix | Delete
if args.domain:
[160] Fix | Delete
modsec_file_std = std_apache_dir / args.user / args.domain / "modsec.conf"
[161] Fix | Delete
modsec_file_ssl = ssl_apache_dir / args.user / args.domain / "modsec.conf"
[162] Fix | Delete
else:
[163] Fix | Delete
modsec_file_std = std_apache_dir / args.user / "modsec.conf"
[164] Fix | Delete
modsec_file_ssl = ssl_apache_dir / args.user / "modsec.conf"
[165] Fix | Delete
[166] Fix | Delete
# Ensure the directory and files exist
[167] Fix | Delete
modsec_file_std.parent.mkdir(parents=True, exist_ok=True)
[168] Fix | Delete
modsec_file_ssl.parent.mkdir(parents=True, exist_ok=True)
[169] Fix | Delete
modsec_file_std.touch(exist_ok=True)
[170] Fix | Delete
modsec_file_ssl.touch(exist_ok=True)
[171] Fix | Delete
[172] Fix | Delete
if args.rule:
[173] Fix | Delete
for rule_id in args.rule:
[174] Fix | Delete
disable_rule(modsec_file_std, rule_id)
[175] Fix | Delete
disable_rule(modsec_file_ssl, rule_id)
[176] Fix | Delete
[177] Fix | Delete
if args.drop:
[178] Fix | Delete
for rule_id in args.drop:
[179] Fix | Delete
remove_rule(modsec_file_std, rule_id)
[180] Fix | Delete
remove_rule(modsec_file_ssl, rule_id)
[181] Fix | Delete
[182] Fix | Delete
if args.reset:
[183] Fix | Delete
if args.domain:
[184] Fix | Delete
reset_modsec_configuration(modsec_file_std)
[185] Fix | Delete
reset_modsec_configuration(modsec_file_ssl)
[186] Fix | Delete
else:
[187] Fix | Delete
reset_modsec_configuration(std_apache_dir / args.user / "modsec.conf")
[188] Fix | Delete
reset_modsec_configuration(ssl_apache_dir / args.user / "modsec.conf")
[189] Fix | Delete
[190] Fix | Delete
if args.off:
[191] Fix | Delete
disable_all_rules(modsec_file_std)
[192] Fix | Delete
disable_all_rules(modsec_file_ssl)
[193] Fix | Delete
[194] Fix | Delete
finally:
[195] Fix | Delete
if check_nginx():
[196] Fix | Delete
print(green("Nginx detected."))
[197] Fix | Delete
cpanel_run_ngxconf(args.user)
[198] Fix | Delete
cpanel_restart_apache()
[199] Fix | Delete
[200] Fix | Delete
# Function to disable all rules in modsec.conf
[201] Fix | Delete
def disable_all_rules(modsec_file):
[202] Fix | Delete
if modsec_file.exists():
[203] Fix | Delete
with modsec_file.open("a") as file:
[204] Fix | Delete
file.write("SecRuleEngine Off\n")
[205] Fix | Delete
print(green(f"All rules disabled in file: {modsec_file}"))
[206] Fix | Delete
[207] Fix | Delete
# Main function to parse arguments and run needed functions based on server type
[208] Fix | Delete
def main():
[209] Fix | Delete
get_lock() # Get the lock before proceeding
[210] Fix | Delete
try:
[211] Fix | Delete
parser = argparse.ArgumentParser(description="Disable modsec rules for Cpanel or PlatformI users and domains.")
[212] Fix | Delete
[213] Fix | Delete
if platformI.exists():
[214] Fix | Delete
parser.add_argument("-r", "--rule", type=int, nargs='+', help="Specific rule IDs to disable")
[215] Fix | Delete
parser.add_argument("-o", "--off", action="store_true", help="Disable all rules")
[216] Fix | Delete
parser.add_argument("-R", "--reset", action="store_true", help="Reset the modsec configuration")
[217] Fix | Delete
parser.add_argument("-D", "--drop", nargs='+', type=int, help="Drop/Remove a specific rule ID from the modsec configuration")
[218] Fix | Delete
else:
[219] Fix | Delete
parser.add_argument("-u", "--user", type=str, required=True, help="CPanel user this is for")
[220] Fix | Delete
parser.add_argument("-d", "--domain", type=str, help="The domain to modify rules for")
[221] Fix | Delete
parser.add_argument("-r", "--rule", type=int, nargs='+', help="Specific rule IDs to disable")
[222] Fix | Delete
parser.add_argument("-o", "--off", action="store_true", help="Disable all rules for the domain")
[223] Fix | Delete
parser.add_argument("-R", "--reset", action="store_true", help="Reset the modsec configuration")
[224] Fix | Delete
parser.add_argument("-a", "--all", action="store_true", help="Apply changes to all domains for the user")
[225] Fix | Delete
parser.add_argument("-D", "--drop", nargs='+', type=int, help="Drop/Remove a specific rule ID from the modsec configuration")
[226] Fix | Delete
[227] Fix | Delete
args = parser.parse_args()
[228] Fix | Delete
[229] Fix | Delete
if platformI.exists():
[230] Fix | Delete
platformI_modsec(args)
[231] Fix | Delete
else:
[232] Fix | Delete
cpanel_modsec(args)
[233] Fix | Delete
[234] Fix | Delete
finally:
[235] Fix | Delete
release_lock() # Release the lock after the script completes
[236] Fix | Delete
[237] Fix | Delete
if __name__ == "__main__":
[238] Fix | Delete
main()
[239] Fix | Delete
[240] Fix | Delete
It is recommended that you Edit text format, this type of Fix handles quite a lot in one request
Function