How to Secure Your WordPress Website Using HTTP Headers (Block CGI, SQL Injection, and Clickjacking)

Kodepen- Wordpress Security

WordPress is the most popular CMS in the world, but its popularity also makes it a frequent target for hackers. Attacks like SQL injection, CGI exploits, and clickjacking can compromise your site and put user data at risk.

The good news? You can significantly harden your WordPress website by configuring the right security headers at the server level. This blog post walks you through how to use HTTP response headers and server rules to reduce your exposure to these types of threats.

What Are HTTP Security Headers?

HTTP headers are additional pieces of information sent from your web server to a browser. While often used for things like caching and content type, some headers instruct the browser to behave in a way that improves security — such as blocking malicious scripts or preventing a site from being embedded in an iframe.

🔒 Essential Security Headers for WordPress

1. X-Frame-Options

Protects against clickjacking by preventing your site from being loaded in an iframe.

Recommended Value:

httpCopyEditX-Frame-Options: DENY

2. Content-Security-Policy (CSP)

Helps block cross-site scripting (XSS), data injection, and even clickjacking by specifying what content browsers are allowed to load.

Basic Example:

httpCopyEditContent-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self';

You can customize this to allow certain CDNs or APIs, but keep it as tight as possible.

3. X-Content-Type-Options

Prevents browsers from MIME-sniffing a response away from the declared content-type.

Value:

httpCopyEditX-Content-Type-Options: nosniff

4. Strict-Transport-Security (HSTS)

Forces browsers to use HTTPS, even if the user types “http://” in their browser.

Value:

httpCopyEditStrict-Transport-Security: max-age=31536000; includeSubDomains; preload

Use only after HTTPS is fully working on your domain.

5. Permissions-Policy (Feature-Policy)

Restricts access to browser features like camera, microphone, etc.

Example:

hCopyEditPermissions-Policy: geolocation=(), microphone=()

6. Referrer-Policy

Controls how much referrer data the browser should include with requests.

Recommended Setting:

httpCopyEditReferrer-Policy: no-referrer-when-downgrade

🔐 Block CGI and Other Dangerous File Access

Many older attacks target .cgi, .pl, or similar scripts. These are rarely used in WordPress and can be disabled at the server level.

Apache .htaccess:

<FilesMatch "\.(cgi|pl|py|sh)$">
Order allow,deny
Deny from all
</FilesMatch>

Nginx:

nginxCopyEditlocation ~* \.(cgi|pl|py|sh)$ {
    deny all;
}

🛡️ SQL Injection Protection (Beyond Headers)

While HTTP headers can’t directly prevent SQL injection, you can significantly reduce the risk with the following:

  • Keep WordPress, themes, and plugins updated
  • Avoid nulled or untrusted plugins/themes
  • Use a Web Application Firewall (WAF)
    Tools like Cloudflare, Wordfence, or Sucuri detect and block SQLi attempts.
  • Sanitize input & escape output in any custom development.

🧩 How to Apply These Headers in WordPress

🔧 Apache: Add to .htaccess

<IfModule mod_headers.c>
Header always set X-Frame-Options "DENY"
Header always set X-Content-Type-Options "nosniff"
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
Header always set Referrer-Policy "no-referrer-when-downgrade"
Header always set Permissions-Policy "geolocation=(), microphone=()"
Header always set Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self'"
</IfModule>

🔧 Nginx: Add to nginx.conf or site config

nginxCopyEditadd_header X-Frame-Options "DENY" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Permissions-Policy "geolocation=(), microphone=()" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self'" always;

⚙️ Bonus Hardening Tips

  • ✅ Disable XML-RPC if you don’t use it.
  • ✅ Limit login attempts and use 2FA with Wordfence or iThemes Security.
  • ✅ Hide the WordPress version from source code.
  • ✅ Disable file editing in the dashboard: phpCopyEditdefine('DISALLOW_FILE_EDIT', true);

HTTP security headers are not just optional extras — they are an essential layer of defense for any WordPress website. Combined with server-level restrictions and good plugin hygiene, you can block many common threats including CGI access, clickjacking, and SQL injection vectors.

Take a few minutes today to apply these changes. It’s one of the easiest ways to keep your WordPress site safer.

✅ Hardened .htaccess for WordPress Security

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]

# Protect against common exploits
RewriteCond %{REQUEST_METHOD} ^(TRACE|DELETE|TRACK) [NC]
RewriteRule ^.*$ - [F,L]

# Protect from SQL Injection and XSS via URL
RewriteCond %{QUERY_STRING} (\.\.\/|\.\.\\) [NC,OR]
RewriteCond %{QUERY_STRING} (\<|%3C).*script.*(\>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} union.*select [NC,OR]
RewriteCond %{QUERY_STRING} concat.*\( [NC]
RewriteRule ^.*$ - [F]

# Block access to .git, .env, .htaccess, config files etc.
RedirectMatch 403 /\.(git|env|htaccess|htpasswd|ini|log|conf|bak|swp|sql)$
</IfModule>
# END WordPress

# Disable script execution in uploads directory
<Directory "/wp-content/uploads/">
  <FilesMatch "\.(php|php5|php7|phps|phtml|pl|py|cgi|sh)$">
    Order allow,deny
    Deny from all
  </FilesMatch>
</Directory>

# Block access to CGI and shell script files site-wide
<FilesMatch "\.(cgi|pl|py|sh)$">
  Order allow,deny
  Deny from all
</FilesMatch>

# Protect wp-config.php
<files wp-config.php>
  order allow,deny
  deny from all
</files>

# Disable directory browsing
Options -Indexes

# Disable file editing from WordPress dashboard
<IfModule mod_php.c>
  php_flag engine on
</IfModule>

# Set Security Headers
<IfModule mod_headers.c>
  Header always set X-Frame-Options "DENY"
  Header always set X-Content-Type-Options "nosniff"
  Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
  Header always set Referrer-Policy "no-referrer-when-downgrade"
  Header always set Permissions-Policy "geolocation=(), microphone=()"
  Header always set Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self'"
</IfModule>

# Leverage browser caching (basic version)
<IfModule mod_expires.c>
  ExpiresActive On
  ExpiresByType image/jpg "access plus 1 year"
  ExpiresByType image/jpeg "access plus 1 year"
  ExpiresByType image/gif "access plus 1 year"
  ExpiresByType image/png "access plus 1 year"
  ExpiresByType text/css "access plus 1 month"
  ExpiresByType text/javascript "access plus 1 month"
  ExpiresByType application/javascript "access plus 1 month"
  ExpiresByType application/pdf "access plus 1 month"
</IfModule>
Categories: