How to Harden a Shared Hosting Account Against Common Attacks
To harden a shared hosting account you have to accept a hard limit up front: you do not control the kernel, the web server build, or the other tenants on the machine. What you do control is your own document root, your file modes, your PHP configuration, your mail and FTP credentials, and the set of entry points the host lets you publish. Hardening a shared hosting account therefore means shrinking your own attack surface and making sure that when one of your scripts is compromised, it cannot easily be used to reach anything else. The goal is not perfect security, which does not exist on shared infrastructure, but containment.
Start With File Permissions and Ownership
Most shared hosting compromises that get reported as "the server was hacked" are really "one PHP file in one account was writable by the web user." The web server process runs as a shared or per-account user, and any file that user can write is a file an attacker can turn into a backdoor. The classic mistake is directory mode 0777 set by a script that needed to upload something. Directories need execute permission to be traversed, but they almost never need write permission for the web user.
Reasonable defaults are 0755 for directories and 0644 for files. Files that must be writable by the application should be owned by the account user and, where the host supports it, written through a group the web server belongs to rather than opened up to everyone. Configuration files holding database credentials should be 0600 or 0640, never world readable, because on shared storage another tenant may be able to read them even if they cannot execute them.
find ~/public_html -type d -exec chmod 755 {} \;
find ~/public_html -type f -exec chmod 644 {} \;
find ~/public_html -name "*.php" -perm -o+w -ls
The last line is the one that matters. It lists any PHP file that is world writable, which is exactly the set an attacker wants. Run it after every deployment, because a single careless upload script will reintroduce the problem. If your host offers per-account isolation, confirm it, but do not rely on it as your only layer.
Turn Off What You Do Not Use
Every enabled PHP function and every installed script is an entry point. On shared hosting you often cannot edit php.ini directly, but most hosts let you drop a per-directory configuration file that the PHP handler reads. The exact filename depends on the handler in use, so check your host's documentation for the correct name; the contents are the part you control.
; per-directory PHP configuration
disable_functions = exec,passthru,shell_exec,system,proc_open,popen
allow_url_fopen = Off
allow_url_include = Off
display_errors = Off
expose_php = Off
session.cookie_httponly = 1
session.cookie_secure = 1
Disabling allow_url_include blocks the oldest remote file inclusion trick outright, and turning off allow_url_fopen removes a common way for a compromised script to fetch a second stage. Disabling process execution functions stops a web shell from running system commands, though a determined attacker can often find another path, so treat this as friction rather than a wall. Turning off display_errors keeps stack traces and absolute paths out of responses. Setting the session cookie flags means a stolen cookie is harder to replay over plain HTTP.
Then remove what you are not using. An abandoned plugin, a demo script left from a tutorial, a phpinfo.php you created to debug something, a backup archive sitting inside the web root: all of these are readable by anyone who guesses the path. Backups in particular are a favorite target because they contain your configuration and often your database dump in plain form. Keep archives outside the document root.
Harden the Entry Points: Headers, TLS and Authentication
The browser-facing layer is where cheap wins are available. A few response headers reduce the damage a cross site scripting flaw can do, and they cost nothing to add. If you cannot set headers in the server configuration, you can usually emit them from PHP or from the per-directory configuration file.
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Strict-Transport-Security "max-age=31536000"
The Strict-Transport-Security header only takes effect over HTTPS and only after the browser has seen it once, so get a certificate working first. Redirect all plain HTTP to HTTPS, because a login form submitted over HTTP exposes the session cookie even with the Secure flag set on the cookie itself. If your host offers free certificate automation, enable it and let it renew; an expired certificate is a functional outage and a habit that trains users to click through warnings.
Authentication deserves the same treatment. Use SFTP or SSH rather than plain FTP, since FTP sends credentials in clear text. Where the host supports it, disable password login for SSH and use a key pair. For any administrative interface you run yourself, put HTTP basic authentication in front of it as a second gate, and restrict it by source address if you have a stable one. Two independent checks are much more work to bypass than one.
Account Practices That Actually Reduce Risk
Credential hygiene on shared hosting matters more than on a machine you own, because a single leaked password may expose mail, databases and files at once. Use a distinct password for the hosting control panel, for each database user, and for each application administrator account. Never reuse the panel password anywhere else. If your host offers two factor authentication on the control panel, turn it on; that panel can usually reset everything else.
Database users should have the narrowest privileges the application needs. A blog does not need DROP on the whole server, and it certainly does not need GRANT. Create a separate user per application and grant only on that application's schema. If the application's own installer asks for a root or superuser account, do not give it one; create the database and user yourself and supply those.
Keep a local copy of your files and database, and verify that you can restore from it. A backup you have never restored is a hope, not a backup. Store it somewhere other than the account it protects, because ransomware and account takeover both target the backups sitting next to the original.
Finally, watch for the quiet signals. Unexpected outbound connections, files with recent modification times you did not create, and mail queues filling with messages you did not send are all worth investigating. A quick check of recently changed PHP files under your document root will surface most injected shells.
find ~/public_html -name "*.php" -mtime -7 -ls
grep -rIl "eval(base64_decode" ~/public_html
Neither command is a scanner, and a careful attacker will avoid both patterns, but they catch the common case cheaply and they take seconds to run.
What to Do Next
Pick the two changes with the widest effect and do them today: fix your file and directory permissions, and disable the PHP functions and URL includes you do not need. Then add the security headers, then move to key based authentication and two factor on the control panel. Recheck permissions after every deployment rather than once, because hardening is a routine, not a one time task. If a setting you want is not exposed on your plan, ask the host whether it can be enabled at the account level; if the answer is no, that is useful information about whether the plan fits what you are running.
