Listen up, fellow web admins: if you’ve ever had your site hammered by SQL injections, XSS sneak attacks, or some script kiddie trying to RCE their way in, you know the pain. OpenLiteSpeed (OLS) is a speed demon, but without a solid Web Application Firewall (WAF), it’s like leaving your front door wide open. This guide is your no-BS blueprint to manually install OWASP Core Rule Set (CRS), toss in some custom rules, and turn your server into Fort Knox. Whether you’re ditching CyberPanel or rocking pure OLS on Ubuntu 20.04, I’ve got your back with step-by-step instructions that even a sleep-deprived sysadmin can follow. Let’s dive in and make those hackers cry!
Why Bother with OWASP CRS and Custom Rules?
OWASP CRS is like the Swiss Army knife of WAF rules—straight from the OWASP GitHub repo, it blocks 90% of common web attacks like SQL injection, XSS, and RCE right out of the gate. But sometimes your site needs a little extra love, like stopping brute-force logins or blocking shady file uploads. That’s where custom rules come in. Sure, it’s a bit of a hassle to set up manually, but you’ll save a fortune compared to those overpriced commercial WAFs. Plus, you get to flex your tech chops!
Before You Start: Gear Up
Before we get our hands dirty, let’s make sure your setup isn’t a hot mess:
- OpenLiteSpeed Installed: Run
lswsctrl status. If it’s running, you’re golden. If not, install it first. - ModSecurity Module: Check with
ls /usr/local/lsws/modules/mod_security.so. Missing? Install it:sudo apt-get install ols-modsecurity -y. - Permissions: You’ll need
sudoaccess, and make sure/usr/local/lsws/logs/is writable for logs.
Step 1: Install OWASP CRS Like a Boss
OWASP CRS isn’t bundled with OLS, so we’re grabbing it straight from GitHub. As of September 2025, version 4.4.0 is the latest hotness. Here’s how to nail it:
- Create a Rules Directory:
sudo mkdir -p /usr/local/lsws/conf/owasp/ cd /usr/local/lsws/conf/owasp/ - Download CRS:
sudo wget https://github.com/coreruleset/coreruleset/archive/refs/tags/v4.4.0.zipGitHub can be a diva sometimes. If the download stalls, try again or hunt for a mirror.
- Unzip and Rename:
sudo unzip v4.4.0.zip sudo mv coreruleset-4.4.0 owasp-modsecurity-crs cd owasp-modsecurity-crsKeep the folder as
/usr/local/lsws/conf/owasp/owasp-modsecurity-crs/to avoid breaking rule paths. - Rename Example Files:
sudo mv crs-setup.conf.example crs-setup.conf cd rules sudo mv REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf sudo mv RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf.example RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.confThese “.example” files are templates. Rename them to activate, and don’t mess with their guts unless you know what you’re doing.
- Create the Rules Include File:In
/usr/local/lsws/conf/owasp/, createmodsec_includes.conf:# ModSecurity core configuration include modsecurity.conf # OWASP CRS setup and rules include owasp-modsecurity-crs/crs-setup.conf include owasp-modsecurity-crs/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf include owasp-modsecurity-crs/rules/REQUEST-901-INITIALIZATION.conf include owasp-modsecurity-crs/rules/REQUEST-905-COMMON-EXCEPTIONS.conf include owasp-modsecurity-crs/rules/REQUEST-911-METHOD-ENFORCEMENT.conf include owasp-modsecurity-crs/rules/REQUEST-913-SCANNER-DETECTION.conf include owasp-modsecurity-crs/rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf include owasp-modsecurity-crs/rules/REQUEST-921-PROTOCOL-ATTACK.conf include owasp-modsecurity-crs/rules/REQUEST-930-APPLICATION-ATTACK-LFI.conf include owasp-modsecurity-crs/rules/REQUEST-931-APPLICATION-ATTACK-RFI.conf include owasp-modsecurity-crs/rules/REQUEST-932-APPLICATION-ATTACK-RCE.conf include owasp-modsecurity-crs/rules/REQUEST-933-APPLICATION-ATTACK-PHP.conf include owasp-modsecurity-crs/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf include owasp-modsecurity-crs/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf include owasp-modsecurity-crs/rules/REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION.conf include owasp-modsecurity-crs/rules/REQUEST-944-APPLICATION-ATTACK-JAVA.conf include owasp-modsecurity-crs/rules/REQUEST-949-BLOCKING-EVALUATION.conf include owasp-modsecurity-crs/rules/RESPONSE-950-DATA-LEAKAGES.conf include owasp-modsecurity-crs/rules/RESPONSE-951-DATA-LEAKAGES-SQL.conf include owasp-modsecurity-crs/rules/RESPONSE-952-DATA-LEAKAGES-JAVA.conf include owasp-modsecurity-crs/rules/RESPONSE-953-DATA-LEAKAGES-PHP.conf include owasp-modsecurity-crs/rules/RESPONSE-954-DATA-LEAKAGES-IIS.conf include owasp-modsecurity-crs/rules/RESPONSE-959-BLOCKING-EVALUATION.conf include owasp-modsecurity-crs/rules/RESPONSE-980-CORRELATION.conf include owasp-modsecurity-crs/rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.confThis file is the master orchestrator, loading rules in the right order to avoid chaos.
Step 2: Add Custom Rules to Beef Up Security
OWASP CRS is a beast, but it’s not perfect for every site. Custom rules let you tackle specific threats like brute-force logins or sneaky file uploads. We’ll keep them separate for easy management.
- Create Custom Rules File:In
/usr/local/lsws/conf/owasp/, createcustom_rules.conf:# Custom ModSecurity Rules for OpenLiteSpeed # Enhanced protection for specific threats # --- 1. Core Settings --- SecRuleEngine On SecRequestBodyAccess On SecResponseBodyAccess On SecResponseBodyMimeType text/plain text/html text/xml application/json SecDefaultAction "phase:2,log,auditlog,deny,status:403" SecDefaultAction "phase:1,log,auditlog,deny,status:403" # --- 2. General Attack Protection --- # 2.1 SQL Injection (SQLi) SecRule ARGS|REQUEST_HEADERS|!REQUEST_HEADERS:User-Agent "@rx (?i)(?:\\b(?:union|select|insert|update|delete|drop|alter|create|rename|truncate|load_file|outfile|sleep|benchmark)\\b|\\d\\s*\\'|\\'\\s*\\d|\\b(?:or|xor|and)\\b\\s*[\\d\\'\\\"])" \ "id:1000,phase:2,block,t:none,t:lowercase,msg:'SQL Injection Attack Detected',logdata:'Matched Data: %{MATCHED_VAR}',severity:'CRITICAL',tag:'application-multi',tag:'language-multi',tag:'platform-multi',tag:'attack-sqli'" # 2.2 Cross-Site Scripting (XSS) SecRule ARGS|REQUEST_HEADERS|REQUEST_BODY "@rx (?i)(?:<script|javascript:|onload\\s*=|onerror\\s*=|onmouseover\\s*=|eval\\(|alert\\(|document\\.cookie)" \ "id:1001,phase:2,block,t:none,t:lowercase,msg:'XSS Attack Attempt Detected',logdata:'Matched Data: %{MATCHED_VAR}',severity:'CRITICAL',tag:'application-multi',tag:'language-multi',tag:'platform-multi',tag:'attack-xss'" # 2.3 Remote Command Execution (RCE) SecRule ARGS|REQUEST_HEADERS|REQUEST_BODY "@rx (?i)(?:\\b(?:bash|sh|cmd|powershell|python|perl|php)\\s*-c|\\b(?:whoami|id|ifconfig|ipconfig|ls|dir|cat|echo|curl|wget|ftp)\\b|\\|\\s*\\||&\\s*&|;\\s*;|`|\\$(?:\\(|\\{))" \ "id:1002,phase:2,block,t:none,t:lowercase,msg:'Remote Command Execution Attempt',logdata:'Matched Data: %{MATCHED_VAR}',severity:'CRITICAL',tag:'attack-rce'" # 2.4 File Inclusion (LFI/RFI) SecRule ARGS|REQUEST_HEADERS "@rx (?i)(?:\.\./|\.\\.\\|file:\\/\\/|php:\\/\\/input|php:\\/\\/filter|expect:\\/\\/|http:\\/\\/|https:\\/\\/|ftp:\\/\\/|\\b(?:etc|proc|usr|home|root|windows|winnt)\\b)" \ "id:1003,phase:2,block,t:none,t:lowercase,msg:'File Inclusion Attack Attempt',logdata:'Matched Data: %{MATCHED_VAR}',severity:'CRITICAL',tag:'attack-lfi',tag:'attack-rfi'" # 2.5 Session Fixation SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/ "!@streq %{SESSION.ID}" \ "id:1004,phase:2,block,msg:'Session Fixation Attack Attempt',tag:'attack-session-fixation'" # --- 3. Scanner and Bot Protection --- # 3.1 Block Scanner User-Agents SecRule REQUEST_HEADERS:User-Agent "@pmf /usr/local/lsws/conf/modsec/scanner-user-agents.list" \ "id:2000,phase:1,deny,msg:'Scanner Detected via User-Agent',logdata:'Scanner User-Agent: %{MATCHED_VAR}',severity:'WARNING',tag:'hostile-scanner'" # --- 4. File Upload Restrictions --- SecRule FILES_TMPNAMES "@rx \\.(?:php|pl|py|jsp|asp|sh|exe|dll|bat|cmd)$" \ "id:3000,phase:2,deny,msg:'Potentially Malicious File Upload Attempt',logdata:'File Name: %{MATCHED_VAR}',severity:'CRITICAL',tag:'attack-malicious-file'" # --- 5. Information Leakage Protection --- # 5.1 Prevent PHP Source Leak SecRule RESPONSE_BODY "@rx (?i:\\<\\?php.*\\?\\>)" \ "id:4000,phase:4,deny,msg:'PHP Source Code Leakage Detected',severity:'ERROR'" # 5.2 Prevent Sensitive File Access SecRule REQUEST_FILENAME "@rx /(\\.git|\\.env|\\.DS_Store)(/|$)|\\/\\.env$" \ "id:4001,phase:1,deny,msg:'Access to Sensitive Hidden File or Directory',logdata:'Matched File: %{MATCHED_VAR}',severity:'CRITICAL'" # --- 6. Rate Limiting (Anti-Brute Force) --- SecRule REQUEST_FILENAME "@streq /wp-login.php" \ "id:5000,phase:1,setvar:'ip.brute_force_counter=+1',expirevar:'ip.brute_force_counter=60',nolog,pass" SecRule VARIABLE:brute_force_counter "@gt 5" \ "id:5001,phase:1,deny,msg:'Brute Force Attack Attempt from IP: %{REMOTE_ADDR}',logdata:'Requests in last 60 seconds: %{brute_force_counter}',severity:'WARNING'" # --- 7. Path Traversal Protection --- SecRule ARGS "\.\./" "t:normalisePathWin,id:99999,severity:4,msg:'Drive Access',log,auditlog,deny" - Create Helper File:For rule ID 2000, create
scanner-user-agents.list:sudo mkdir -p /usr/local/lsws/conf/modsec/ sudo nano /usr/local/lsws/conf/modsec/scanner-user-agents.listAdd entries like
sqlmap,nikto,burp. - Update Include File:Edit
modsec_includes.confto add:include custom_rules.confPlace it after CRS rules to let custom rules supplement or override.
Step 3: Configure ModSecurity Module
Edit /usr/local/lsws/conf/httpd_config.conf to ensure ModSecurity is ready to rumble:
module mod_security {
modsecurity on
modsecurity_rules `
SecDebugLogLevel 0
SecDebugLog /usr/local/lsws/logs/modsec.log
SecAuditEngine on
SecAuditLogRelevantStatus "^(?:5|4(?!04))"
SecAuditLogParts AFH
SecAuditLogType Serial
SecAuditLog /usr/local/lsws/logs/auditmodsec.log
SecRuleEngine On
`
modsecurity_rules_file /usr/local/lsws/conf/owasp/modsec_includes.conf
ls_enabled 1
}
Check log directory permissions:
sudo mkdir -p /usr/local/lsws/logs/
sudo chown lsadm:lsadm /usr/local/lsws/logs/
sudo chmod 750 /usr/local/lsws/logs/
Step 4: Test and Validate Like a Paranoid Admin
Don’t pop the champagne yet—let’s make sure this WAF actually works.
- Enable Debugging: Set
SecDebugLogLevel 9inhttpd_config.conf, then restart:sudo systemctl restart lsws. - Simulate Attacks:
- XSS:
curl "http://your-domain/?param=<script>alert(1)</script>"– Expect a 403, triggering ID 1001 or CRS 941100. - SQLi:
curl "http://your-domain/?id=1' OR '1'='1"– Should hit ID 1000 or 942100. - Path Traversal:
curl "http://your-domain/?file=../etc/passwd"– Triggers ID 99999 or 930100.
- XSS:
- Check Logs: Dig into
/usr/local/lsws/logs/modsec.logand/usr/local/lsws/logs/auditmodsec.logfor rule IDs and 403 errors. - Handle False Positives: If your WordPress admin page gets blocked, edit
custom_rules.confor CRS rules, comment out problem rules (e.g.,#SecRule ...), or addSecRuleRemoveById 1000. - Go Live: Once tested, set
SecDebugLogLevel 0,SecRuleEngine On, and restart.
Pitfalls to Dodge
- False Positives: WordPress might choke on rules like ID 1000 (SQLi) for legit inputs like “union” in comments. Fix: Add exclusions for specific URLs or tweak regex.
- Path Mismatches: The
/wp-login.phpin ID 5000-5001 won’t work if your login is, say,/admin/login. Update it. - Missing Files: No
scanner-user-agents.list? Rule ID 2000 is useless. Create it! - Log Bloat: Audit logs grow fast. Rotate them or tweak
SecAuditLogRelevantStatusto cut noise. - CyberPanel Hangovers: Migrated from CyberPanel? Nuke any old rules in
/usr/local/lsws/conf/modsec/to avoid conflicts.
Wrap-Up
Boom! Your OpenLiteSpeed server is now a fortress with OWASP CRS and custom rules blocking SQL injections, XSS, and brute-force nonsense. Keep an eye on the CRS GitHub for updates, and check your logs regularly to stay ahead of the bad guys. Manual setup takes some elbow grease, but it’s way cheaper than a commercial WAF, and you’ll feel like a cybersecurity rockstar.

Comments NOTHING