Security Hints for PHP/MySQL Applications

General hardening recommendations for Apache servers running PHP/MySQL applications such as ConfTool, and useful for most productive PHP environments.

 


 

Always Use HTTPS / TLS

Any application that handles logins, personal data, or payment information must be served exclusively over an encrypted connection. Obtain a TLS certificate (for example a free certificate from Let’s Encrypt via certbot) and redirect all plain HTTP traffic to HTTPS.

# In your virtual host: force HTTPS
<VirtualHost *:80>
    ServerName conference.example.org
    Redirect permanent / https://conference.example.org/
</VirtualHost>

Once HTTPS is enforced, enable HTTP Strict Transport Security so browsers refuse to fall back to unencrypted connections (see Security Headers below).


 

Apache Server Security

Block Access to Backup Files

It is advisable to block access to all backup files. If these are, for instance, PHP files, they are usually not executed by the server and may reveal parameters such as the password for your MySQL database.

To block access to backup files with the extensions .bak, .BAK and ~, add the following to your httpd.conf (or the relevant virtual host):

<FilesMatch "(\.bak|\.BAK|~)$">
 Require all denied
</FilesMatch>

Example within a directory block:

<Directory "/home/conftool/">
  # Restrict directory options
  # -Indexes disables automatic directory listings
   Options -Indexes
   # -Includes disables Server-Side Includes (SSI)
   Options -Includes
   # -ExecCGI prevents Apache from executing CGI scripts in the directory.
   Options -ExecCGI

  # Controls who can access content from this directory.
  Require all granted

  # Prevent access to backup files!
  <FilesMatch "(\.bak|\.BAK|~)$">
      Require all denied
  </FilesMatch>
</Directory>

 

Disable the HTTP TRACE Method

The HTTP TRACE method echoes back the request it receives. It serves no purpose for a normal application and has historically been abused in Cross-Site Tracing (XST) attacks to read otherwise protected headers such as cookies. Turn it off globally in your server or virtual host configuration:

TraceEnable Off

Please note: TraceEnable is a server-level directive: place it in httpd.conf or within a <VirtualHost> block. It cannot be set inside a <Directory> block or an .htaccess file.

 

Security Headers

With mod_headers enabled, add response headers that reduce common attack surfaces. Set HSTS only after HTTPS works reliably.

Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains"
Header always set X-Content-Type-Options "nosniff"
Header always set Content-Security-Policy "frame-ancestors 'self'"
Header always set Referrer-Policy "no-referrer"

 


 

MySQL Database Security

Limit Network Access

If not required, block network access to the MySQL/MariaDB server from other hosts. One way is to add the following to your configuration file (my.cnf, usually in /etc/ or below the data directory):

skip-networking

Applications then have to use a socket file to reach the MySQL daemon. If disabling the network entirely causes problems, bind the server to localhost instead:

bind-address = 127.0.0.1

Set the Root Password

Connect as root and set the password:

mysql -u root

-- inside the client:
ALTER USER 'root'@'localhost' IDENTIFIED BY 'myNewStrongPassword';
FLUSH PRIVILEGES;

Alternatively, for a fresh installation, run the guided hardening script mysql_secure_installation, which sets the root password and removes anonymous users and the test database.

Use a Dedicated Application User

Never let the application connect as root. Create a dedicated user with only the privileges it actually needs on its own database (principle of least privilege):

CREATE USER 'conftool'@'localhost' IDENTIFIED BY 'aStrongPassword';
GRANT SELECT, INSERT, UPDATE, DELETE ON conftool_db.* TO 'conftool'@'localhost';
FLUSH PRIVILEGES;

Granting only data privileges (and, where required, schema privileges during installation/upgrades) keeps an attacker who obtains the application credentials away from administrative and file-level capabilities.

Disable LOAD_FILE() and Server-Side File Access

The MySQL function LOAD_FILE() can read files from the database server’s file system and return their contents to a query. Combined with an SQL-injection flaw, this can expose configuration files, password hashes, or other sensitive data. There are two complementary controls.

1. Withhold the FILE privilege. LOAD_FILE() (as well as LOAD DATA INFILE and SELECT … INTO OUTFILE) requires the global FILE privilege. Application users should never have it. If a user was granted it, revoke it:

REVOKE FILE ON *.* FROM 'conftool'@'localhost';
FLUSH PRIVILEGES;

You can verify which accounts hold it:

SELECT grantee FROM information_schema.user_privileges
WHERE privilege_type = 'FILE';

2. Restrict or disable file operations server-wide via the secure_file_priv system variable in the [mysqld] section of my.cnf. Setting it to NULL disables all server-side file import/export, so LOAD_FILE() returns NULL for everyone, regardless of privileges:

[mysqld]
# Disable LOAD_FILE / LOAD DATA INFILE / SELECT ... INTO OUTFILE entirely
secure_file_priv = NULL

If you do need file import/export for specific maintenance tasks, point it at a single, locked-down directory instead of disabling it completely:

secure_file_priv = "/var/lib/mysql-files/"

Please note: secure_file_priv is read-only at runtime, so the server must be restarted for changes to take effect. 
Check the current value with:

SHOW VARIABLES LIKE 'secure_file_priv';

 


 

PHP Security Settings

PHP is not an “unsafe” language, but a few settings reduce the exposure of most installations. They are set in php.ini; some can also be set in the Apache configuration or a local .htaccess file. Note that other PHP scripts on the same server might be affected by these settings.

disable_functions

Some PHP functions expose system resources, parameters, or files. The most sensitive are:

show_source, system, shell_exec, passthru, exec, phpinfo, popen, proc_open, proc_nice

ConfTool uses two of them:

exec is used on Windows systems to check whether the domain of an email address exists (all parameters are sanitized before the call; it is also used in some custom libraries to access credit-card gateways). popen is used by the PHPMailer library to send email (you may use PHP’s built-in mail function instead, but it is less capable).

If you use those features, disable the remaining functions only:

disable_functions = show_source, system, shell_exec, passthru, phpinfo, proc_open, proc_nice

allow_url_fopen / allow_url_include

allow_url_fopen = Off

This should be set on most servers. It prevents scripts from loading code or data from remote servers — a potential security issue. If some of your scripts genuinely need allow_url_fopen, you can at least block remote include/require separately:

allow_url_include = Off

display_errors / log_errors

display_errors = Off

This suppresses PHP error output to users (and potential attackers) and should always be off in production. Keep logging error details to the server log for analysis instead:

log_errors = On

open_basedir

Limits the directories from which PHP files may be executed; files outside the given path(s) are not run. It is always recommended to restrict PHP to the directories where known applications reside.

# Unix/Linux example
open_basedir = "/home/conftool/:/srv/www/"

# Windows example
open_basedir = "D:/www/conftool/;C:/Apache24/htdocs/"

expose_php / Session Cookies

Hide the PHP version from response headers, and make session cookies harder to steal or misuse. The secure flag requires the HTTPS setup described above.

expose_php = Off
session.cookie_secure   = On
session.cookie_httponly = On
session.cookie_samesite = "Lax"

 


 

Keep Software Up to Date

Run only versions of PHP and MySQL/MariaDB that still receive security support, and apply operating-system and application updates promptly. Consider basic brute-force protection for the login (for example fail2ban) and review file-system permissions so that configuration files containing credentials are not world-readable.

 


 

Conclusion

Security is not a state but a process. Because PHP and MySQL are very popular, keep track of recent developments and update your server settings accordingly. If you find any potential problems in ConfTool, please contact us immediately.