OWASP A6 – Security Misconfiguration with PHP

This will be another non-development related post. I am going to cover security configuration of the operating system, web server, and PHP environment for your web applications. It doesn’t matter how secure your application is if the OS, web server, or PHP configuration is insecure. I am not going to cover full hardening of your servers, but rather some general guidelines along with some specific configuration settings for PHP and Apache.

General guidance on server deployment for your application environment:

  • Apply all security related patches to the operating system and services in use. Make sure that Apache and PHP are fully patched.
  • Apply a security best practice standard, deviating only when necessary. CIS is a good choice here because of their depth of configuration standards. Use security best practice standards for the OS as well as Apache.
  • Change default passwords for all accounts. Use a long and strong password for service and administrative accounts.
  • Disable or remove all unnecessary protocols, accounts, scripts, processes, and services.
  • Perform vulnerability scans, web application scans, and network and application level penetration tests against your systems on a regular basis.
  • Configure servers to log all security related events and to forward those events to a centralized security information management system.
  • Configure applications to only display generic error messages.
  • Perform administrative actions using unprivileged accounts. Use the “Run As” feature of Windows or the sudo feature of Linux to perform privileged operations on servers.

The above suggestions will help ensure that your system is patched and the OS is configured securely. Apache must be configured securely as well to limit the servers exposure to risk. General Apache recommendations:

  • Compile Apache with the minimum amount of modules and features required to run your application(s). I suggest the following directives be run as part of the configuration at a minimum: –enable-headers, –enable-expires, –enable-ssl, –enable-rewrite, –disable-status, –disable-asis, –disable-autoindex, –disable-userdir. The enable settings ensure that you can configure the server to timeout sessions and send other security related responses, support connections over SSL, and rewrite requests to prevent specific HTTP methods. The options for disabling features prevents information disclosure issues within the Apache web server.
  • Remove all default scripts from the /cgi-bin directory.
  • Create an apache user and group with minimal permissions. Run apache as this user and change ownership of all files served by Apache to this user and group with minimal permissions (in Linux: chown -R apache.apache /path/to/web/directory, chmod -R 644 /path/to/web/directory, then chmod 744 for all directories under the web directory).
  • Consider installing and configuring ModSecurity.

Specific Apache web server configuration suggestions follow. Configure httpd.conf so that the server doesn’t report full version and module information:

  ServerTokens Prod
  ServerSignature Off

 
Configure the server to use an unprivileged user account and group:

  User apache
  Group apache

 
Load the least amount of modules possible for your environment, our server is set to:

  LoadModule php5_module        /usr/modules/libphp5.so
  LoadModule security2_module   /usr/modules/mod_security2.so
  LoadModule unique_id_module   /usr/modules/mod_unique_id.so

 
Disable the use of unnecessary and potentially dangerous HTTP/WebDAV methods:

  <Directory />
    <Limit OPTIONS PUT CONNECT PATCH PROPFIND PROPPATCH MKCOL COPY MOVE LOCK UNLOCK DELETE TRACK>
      Order deny,allow
      Deny from all
    </Limit>

    Options None
    AllowOverride None
    Order deny,allow
    Deny from all
  </Directory>

  <Directory "/var/www/htdocs">
    <Limit OPTIONS PUT CONNECT PATCH PROPFIND PROPPATCH MKCOL COPY MOVE LOCK UNLOCK DELETE TRACK>
      Order deny,allow
      Deny from all
    </Limit>

    Options None
    AllowOverride None
    Order allow,deny
    Allow from all
  <Directory>

 
Disable support for all but specifically allowed file extensions:

  // Match all files and deny
  <FilesMatch "^.*\.[a-zA-Z0-9]+$">
    Order deny,allow
    Deny from all
  </FilesMatch>
  
  // Allow specific file extensions
  <FilesMatch "^.*\.(ico|css|tpl|wsdl|html|htm|JS|js|pdf|doc|xml|gif|jpg|jpe?g|png|php)$">
    Order deny,allow
    Allow from all
  </FilesMatch>

 
Log errors:

  ErrorLog "/var/log/apache/error_log"
  LogLevel notice
  LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
  LogFormat "%h %l %u %t \"%r\" %>s %b" combined
  CustomLog "/var/log/apache/access_log" combined

 
Disable access to the cgi-bin directory:

  <Directory "/usr/local/apache/cgi-bin">
    AllowOverride None
    Options None
    Order deny,allow
    Deny from all
  </Directory>

 
Block the TRACE and TRACK HTTP Methods (must be added to each virtual host):

  RewriteEngine On
  RewriteCond %{REQUEST_METHOD} ^(TRACE|TRACK)
  RewriteRule .* - [F]

 
Block anything other than HTTP 1.1 traffic:

  RewriteCond %{THE_REQUEST} !HTTP/1\.1$
  RewriteRule .* - [F]

 
Applications that require authentication should require SSL for the entire session. The following configuration directive will redirect requests to http://myapp.mysite.com to HTTPS:

  RewriteCond %{HTTPS} off
  RewriteRule (myapp.mysite.com.*) https://%{HTTP_HOST}%{REQUEST_URI}

 
In your ssl configuration file, require SSLv3 or TLS, and only strong encryption protocols:

  SSLProtocol -ALL +SSLv3 +TLSv1
  SSLCipherSuite HIGH:!ADH

 
If you cannot use the –disable-userdir and –disable-status options during Apache compilation, then add the following directives to your Apache configuration to prevent unnecessary information disclosure related to these modules:

  UserDir Disabled
  ExtendedStatus Off

 
If you cannot use the –disable-autoindex option during Apache compilation, then add the following directive to each <Directory> setting in your Apache configuration to prevent auto indexing of directories and leakage of directory contents:

  Options -Indexes

 
Finally, PHP must be configured securely to ensure the protection of your application and company/customer data. General PHP recommendations:

  • Compile PHP with the minimum amount of modules and features required to run your application(s). I suggest the following directives be run as part of the configuration at a minimum: –with-openssl and –with-mcrypt. This will ensure that you can leverage encryption routines within your application to protect data and passwords.
  • Protect the PHP session directory. Place session data in a temporary directory and then apply the most restrictive permissions possible to the folder. The folder can be owned by the root user and the apache group.
  • Place third-party PHP libraries used within your applications in a directory outside of the main web directory (/htdocs)
  • If possible, apply the PHP Suhosin patch to PHP to provide additional security to the scripting language core.

Specific PHP configuration suggestions follow. Configure php.ini to prevent Denial of Service (DoS) conditions (adjust these settings based on the needs of your application):

  // Maximum time a script can execute
  max_execution_time = 30

  // Maximum time a script can spend parsing request data
  max_input_time = 7200

  // Max memory a script can consume
  memory_limit = 128M

  // Limit the amount of data that can be POSTed to the 
  // server.  This affects file uploads as well.
  post_max_size = 4M

  // Limit the maximum size of a file uploaded to the server.
  upload_max_filesize = 4M

  // Limit the number of files that can be uploaded at a
  // single time.
  max_file_uploads = 10

 
Enable logging but disable displaying logs to application users:

  error_reporting = E_ALL & ~E_DEPRECATED
  display_errors = Off
  display_startup_errors = Off
  log_errors = On
  log_errors_max_len = 1024

  // Do not ignore errors, log them all
  ignore_repeated_errors = Off
  ignore_repeated_source = Off

 
Set specific mime types and content types to help prevent encoding, decoding, and other canonicalization issues that can result in successful XSS attacks:

  default_mimetype = "text/html"
  default_charset = "ISO-8859-1"

 
Place third-party PHP applications in a path outside of the /htdocs directory:

  include_path = ".:/usr/local/apache/phpincludes"

 
Implement strong protection of PHP sessions:

  // Save sessions as files in a specific directory
  session.save_handler = files
  session.save_path = "/tmp/phpsessions"

  // Require the use of cookies to prevent session
  // ID's from being included in URL's
  session.use_cookies = 1
  session.use_only_cookies = 1
  session.use_trans_sid = 0

  // Set the "secure" and "httponly" flags on the
  // cookie.  This will prevent the cookie from
  // being sent over an HTTP connection or being
  // accessed by JavaScript, helping prevent
  // session hijacking attacks via XSS.
  session.cookie_secure = true
  session.cookie_httponly = true

  // Set cookie path and domain information to 
  // limit where the cookie can be used, thus 
  // protecting session data.
  session.cookie_path = /codewatch/
  session.cookie_domain = www.codewatch.org

  // Set the cookie to delete once the browser
  // is closed.
  session.cookie_lifetime = 0

  // Perform garbage collection on session data
  // after 15 minutes of inactivity.
  session.gc_maxlifetime = 900

  // Use a secure source for generating random
  // session ID's (set to a non-zero value
  // on Windows systems.
  session.entropy_file = /dev/urandom

  // Use a strong hashing algorithm to create
  // the session ID and use as many characters
  // as possible to reduce the likeliness that
  // the session ID can be guessed or hijacked.
  session.hash_function = 'sha512'
  session.hash_bits_per_character = 6

  // Send the nocache directive in HTTP(S) 
  // responses to ensure the page can't be 
  // cached.  In addition, set the time-to-
  // live for the page to a low value.
  session.cache_limiter = nocache
  session.cache_expire = 15

 
Disable the ability for PHP to interpret a URL as a file to help prevent some types of remote file include attacks:

  allow_url_fopen = Off
  allow_url_include = Off

 
Disable registration of globals, long arrays, and the argc/argv variables (more information and the reason behind this suggestion can be found here, here, and here).:

  register_globals = Off
  register_long_arrays = Off
  register_argc_argv = Off

 
Following these guidelines and configuration settings should go a long way towards ensuring the security of your web and application servers, company and customer data, and the integrity of your systems.

One response to “OWASP A6 – Security Misconfiguration with PHP”

  1. Thanks for some other excellent article. Where else could anyone get that type of info in such an ideal method of writing? I’ve a presentation subsequent week, and I’m on the look for such info.

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: