web analytics

Archive for the ‘MySQL’ Category

Best Practices for Deploying New Environments in the Cloud for the First Time

When organizations take their first steps to use public cloud services, they tend to look at a specific target.

My recommendation – think scale!

Plan a couple of steps ahead instead of looking at single server that serves just a few customers. Think about a large environment comprised of hundreds or thousands of servers, serving 10,000 customers concurrently.

Planning will allow you to manage the environment (infrastructure, information security and budget) when you do reach a scale of thousands of concurrent customers. The more we plan the deployment of new environments in advance, according to their business purposes and required resources required for each environment, it will be easier to plan to scale up, while maintaining high level security, budget and change management control and more.

In this three-part blog series, we will review some of the most important topics that will help avoid mistakes while building new cloud environments for the first time.

Resource allocation planning

The first step in resources allocation planning is to decide how to divide resources based on an organizational structure (sales, HR, infrastructure, etc.) or based on environments (production, Dev, testing, etc.)

In-order to avoid mixing resources (or access rights) between various environments, the best practice is to separate the environments as follows:

  • Share resource account (security products, auditing, billing management, etc.)
  • Development environment account (consider creating separate account for test environment purposes)
  • Production environment account

Separating different accounts or environments can be done using:

Tagging resources

Even when deploying a single server inside a network environment (AWS VPC, Azure Resource Group, GCP VPC), it is important to tag resources. This allows identifying which resources belong to which projects / departments / environments, for billing purposes.

Common tagging examples:

  • Project
  • Department
  • Environment (Prod, Dev, Test)

Beyond tagging, it is recommended to add a description to resources that support this kind of meta-data, in-order to locate resources by their target use.

Authentication, Authorization and Password Policy

In-order to ease the management of working with accounts in the cloud (and in the future, multiple accounts according to the various environments), the best practice is to follow the rules below:

  • Central authentication – In case the organization isn’t using Active Directory for central account management and access rights, the alternative is to use managed services such as AWS IAM, Google Cloud IAM, Azure AD, Oracle Cloud IAM, etc.

If managed IAM service is chosen, it is critical to set password policy according to the organization’s password policy (minimum password length, password complexity, password history, etc.)

  • If the central directory service is used by the organization, it is recommended to connect and sync the managed IAM service in the cloud to the organizational center directory service on premise (federated authentication).
  • It is crucial to protect privileged accounts in the cloud environment (such as AWS Root Account, Azure Global Admin, Azure Subscription Owner, GCP Project Owner, Oracle Cloud Service Administrator, etc.), among others, by limiting the use of privileged accounts to the minimum required, enforcing complex passwords, and password rotation every few months. This enables multi-factor authentication and auditing on privileged accounts, etc.
  • Access to resources should be defined according to the least privilege principle.
  • Access to resources should be set to groups instead of specific users.
  • Access to resources should be based on roles in AWS, Azure, GCP, Oracle Cloud, etc.

Audit Trail

It is important to enable auditing in all cloud environments, in-order to gain insights on access to resources, actions performed in the cloud environment and by whom. This is both security and change management reasons.

Common managed audit trail services:

  • AWS CloudTrail – It is recommended to enable auditing on all regions and forward the audit logs to a central S3 bucket in a central AWS account (which will be accessible only for a limited amount of user accounts).
  • Working with Azure, it is recommended to enable the use of Azure Monitor for the first phase, in-order to audit all access to resources and actions done inside the subscription. Later on, when the environment expands, you may consider using services such as Azure Security Center and Azure Sentinel for auditing purposes.
  • Google Cloud Logging – It is recommended to enable auditing on all GCP projects and forward the audit logs to the central GCP project (which will be accessible only for a limited amount of user accounts).
  • Oracle Cloud Infrastructure Audit service – It is recommended to enable auditing on all compartments and forward the audit logs to the Root compartment account (which will be accessible only for a limited amount of user accounts).

Budget Control

It is crucial to set a budget and budget alerts for any account in the cloud at in the early stages of working with in cloud environment. This is important in order to avoid scenarios in which high resource consumption happens due to human error, such as purchasing or consuming expensive resources, or of Denial of Wallet scenarios, where external attackers breach an organization’s cloud account and deploys servers for Bitcoin mining.

Common examples of budget control management for various cloud providers:

  • AWS Consolidated Billing – Configure central account among all the AWS account in the organization, in-order to forward billing data (which will be accessible only for a limited amount of user accounts).
  • GCP Cloud Billing Account – Central repository for storing all billing data from all GCP projects.
  • Azure Cost Management – An interface for configuring budget and budget alerts for all Azure subscriptions in the organization. It is possible to consolidate multiple Azure subscriptions to Management Groups in-order to centrally control budgets for all subscriptions.
  • Budget on Oracle Cloud Infrastructure – An interface for configuring budget and budget alerts for all compartments.

Secure access to cloud environments

In order to avoid inbound access from the Internet to resources in cloud environments (virtual servers, databases, storage, etc.), it is highly recommended to deploy a bastion host, which will be accessible from the Internet (SSH or RDP traffic) and will allow access and management of resources inside the cloud environment.

Common guidelines for deploying Bastion Host:

The more we expand the usage of cloud environments, we can consider deploying a VPN tunnel from the corporate network (Site-to-site VPN) or allow client VPN access from the Internet to the cloud environment (such as AWS Client VPN endpoint, Azure Point-to-Site VPN, Oracle Cloud SSL VPN).

Managing compute resources (Virtual Machines and Containers)

When selecting to deploy virtual machines in cloud environment, it is highly recommended to follow the following guidelines:

  • Choose an existing image from a pre-defined list in the cloud providers’ marketplace (operating system flavor, operating system build, and sometimes an image that includes additional software inside the base image).
  • Configure the image according to organizational or application demands.
  • Update all software versions inside the image.
  • Store an up-to-date version of the image (“Golden Image”) inside the central image repository in the cloud environment (for reuse).
  • In case the information inside the virtual machines is critical, consider using managed backup services (such as AWS Backup or Azure Backup).
  • When deploying Windows servers, it is crucial to set complex passwords for the local Administrator’s account, and when possible, join the Windows machine to the corporate domain.
  • When deploying Linux servers, it is crucial to use SSH Key authentication and store the private key(s) in a secure location.
  • Whenever possible, encrypt data at rest for all block volumes (the server’s hard drives / volumes).
  • It is highly recommended to connect the servers to a managed vulnerability assessment service, in order to detect software vulnerabilities (services such as Amazon Inspector or Azure Security Center).
  • It is highly recommended to connect the servers to a managed patch management service in-order to ease the work of patch management (services such as AWS Systems Manager Patch Manager, Azure Automation Update Management or Google OS Patch Management).

When selecting to deploy containers in the cloud environment, it is highly recommended to follow the following guidelines:

Storing sensitive information

It is highly recommended to avoid storing sensitive information, such as credentials, encryption keys, secrets, API keys, etc., in clear text inside virtual machines, containers, text files or on the local desktop.

Sensitive information should be stored inside managed vault services such as:

Object Storage

When using Object Storage, it is recommended to follow the following guidelines:

  • Avoid allowing public access to services such as Amazon S3, Azure Blob Storage, Google Cloud Storage, Oracle Cloud Object Storage, etc.
  • Enable audit access on Object Storage and store the access logs in a central account in the cloud environment (which will be accessible only for a limited amount of user accounts).
  • It is highly recommended to encrypt data at rest on all data inside Object Storage and when there is a business or regulatory requirement, and encrypt data using customer managed keys.
  • It is highly recommended to enforce HTTPS/TLS for access to object storage (users, computers and applications).
  • Avoid creating object storage bucket names with sensitive information, since object storage bucket names are unique and saved inside the DNS servers worldwide.

Networking

Advanced use of cloud environments

It allows consumption of services, rather than maintaining servers, operating systems, updates/patches, backup and availability, assuming managed services in cluster or replica mode is chosen.

  • Use Infrastructure as a Code (IoC) in-order to ease environment deployments, lower human errors and standardize deployment on multiple environments (Prod, Dev, Test).

Common Infrastructure as a Code alternatives:

Summary

To sum up:

Plan. Know what you need. Think scale.

If you use the best practices outlined here, taking off to the cloud for the first time will be an easier, safer and smoother ride then you might expect.

Additional references

The Basics of Secure Web Development

The internet has contributed a great deal to commerce around the world in the last decade, and of course with a whole new generation of people breaking into the online world we’re starting to see just what computers are capable of accomplishing. Particularly when there is malicious intent on the other side of that keyboard.

Hackers and crackers are one of the biggest threats the world has ever experienced; they can take your money, your products or even destroy your business from the inside out – and you’ll never see them do it, they might not leave a trace at all. That is the terrifying truth about the internet; in most cases those with the skills to take what they want have the skills to hide themselves from detection – so what can you do to stop them.

The easiest way of protecting your website is to ensure that your business have a securely developed website. Secure web development is a complex area, and most likely something that you will need the help of a professional in order to fully implement, but it is worth noting that there are three different levels of security to take into consideration for your website and thus three different levels that need to be securely developed in order to ensure the protection of your business.

Consider these levels almost like doors. If your website was a business property you would have three ways in to the top secret bits; a front door, a side door and a back door.

The front door is the user interface; the bit of the website that you yourself work with. Now; the web developer might have made you a big magnificent door, lovely and secure – the sort of user interface that lets you manage your stock, orders, customers and all of the individual aspects of your business effortlessly without giving anything up. However; if your passwords aren’t secure it’s the equivalent of putting a rubbish, rusty old lock on that lovely secure door – completely pointless and insecure. Easy access. This is the first place a hacker is going to look – why would they waste their time hunting down and trying to exploit tiny weaknesses in the back door if they could open the front door with one little shove?

Change your passwords regularly, select passwords that use upper case, lower case, numbers and punctuation. Do not use the same password for everything.

The side door is the programming. The code used to construct your website puts everything in place and says who can do what and when; everything is controlled with the code, so an opening here can cause big problems if a hacker finds it. There are a number of different potential security risks when it comes to the code; there are bugs, which are just general, little faults with the website that occur when something didn’t go quite as planned or something was missed in the development stage. They always happen and there isn’t a single piece of software that doesn’t have bugs, the secure ones are just those that resolve the bugs as soon as they’re found, which stops them from being exploited.

Another risk to that side door is an injection; sort of like a fake key. This is something some of the smarter hackers can accomplish by injecting their own instructions into your system when it sends off a command or query – they can intercept your command or query. For example; let’s say you perform a simple PHP query that will fetch the products from the database when your user selects a product category. Normally this sort of script would be accessed through the URL with a category id.

For example;

Let’s say you did a regular sql database select query looking for the category ID, your category information and URL command might look something like;

c.category_id = ‘ . $_GET[‘cat’] . ‘LIMIT 10’;

Now; obviously this example suggests that the clever programmer has included a limit to prevent what is going to happen next – but this won’t protect him. Poor clever programmer is about to be outsmarted.

First of all; the only thing the thing the hacker needs to do is find your product list page and look for everything, example;

Yourwebsite.com/productlist.php?cat=1 or 1=1-

Doesn’t look like anything special right? Well, with this alone the hacker can now see every single one of your products. Depending on how secure your website is this might let them find faults in the products, but it’s probably still not that dangerous right? Well, what if they did this;

/productlist.php?cat=1 or error!;#$

Yep – bet you’re horrified now, because this will typically reveal the DBMS version of the query, and sometimes expose your table and column names. Not dangerous enough for you? With the tables and columns are revealed the hacker can move on to attacking the user table, all thanks to exploiting a weakness in the products table.

/productlist.php?cat=1 and (select count(*) from users) > 0

Creating a new query inside the existing one means that they don’t need to verify the database connection; they’re using yours. They have access to your database not and their using it to find your user table, which can progress to finding how many users you have, and even finding the information within the user table. I’m quite sure I don’t need to specify why having access to your user database is such a bad thing.

So – if you want to avoid the injections you need to ensure that every bit of input data gets validated, reduce the amount of information shown when an error displays, really limit the database permissions to prevent php queries from being able to pull any more information than they absolutely need to and use parameters in your queries.

Finally – the back door. This is the server. You need to ensure that the server you use to host your information and website is secure. There have been a number of cases where highly secure websites were eventually hacked by first hacking a much lower security website that shared the host server. If you want to avoid this you can consider a dedicated server for your website, you should also consider keeping to companies hosting companies that offer support and security as part of the hosting package. Ask them what software their servers are running; this will give you an idea of how regularly they are updated – up to date servers are the most secure. Older software has had longer to be exploited and thus more of the weaknesses in these are already known to hackers.

 

 

Kate Critchlow is a young and enthusiastic writer with a particular interest for technology, covering everything from secure development to the latest gadget releases.

Hardening guide for Drupal 7.7

Pre-installation notes
The guide bellow is based on CentOS 5.5 (i386), Apache 2.2.19, MySQL 5.5.15

The guide bellow is based on the previous guides:

PHP installation phase

  1. Login to the server using Root account.
  2. Before compiling the PHP environment, install the following RPM from the CentOS 5.5 DVD source folder:
    rpm -ivh kernel-headers-2.6.18-194.el5.i386.rpm
    rpm -ivh glibc-headers-2.5-49.i386.rpm
    rpm -ivh glibc-devel-2.5-49.i386.rpm
    rpm -ivh gmp-4.1.4-10.el5.i386.rpm
    rpm -ivh libgomp-4.4.0-6.el5.i386.rpm
    rpm -ivh gcc-4.1.2-48.el5.i386.rpm
    rpm -ivh libxml2-2.6.26-2.1.2.8.i386.rpm
    rpm -ivh zlib-devel-1.2.3-3.i386.rpm
    rpm -ivh libxml2-devel-2.6.26-2.1.2.8.i386.rpm
    rpm -ivh pkgconfig-0.21-2.el5.i386.rpm
    rpm -ivh libpng-devel-1.2.10-7.1.el5_3.2.i386.rpm
    rpm -ivh libjpeg-devel-6b-37.i386.rpm
  3. Download MySQL development RPM from:
    http://download.softagency.net/MySQL/Downloads/MySQL-5.5/
  4. Download PHP 5.3.8 source files from:
    http://php.net/downloads.php
  5. Download the latest libxml2 for PHP from:
    http://xmlsoft.org/sources/
  6. Copy the MySQL development RPM using PSCP (or SCP) into /tmp
  7. Copy the PHP 5.3.8 source files using PSCP (or SCP) into /tmp
  8. Move to /tmp
    cd /tmp
  9. Install the MySQL development RPM:
    rpm -ivh MySQL-devel-5.5.15-1.rhel5.i386.rpm
  10. Remove MySQL development RPM:
    rm -f MySQL-devel-5.5.15-1.rhel5.i386.rpm
  11. Extract the php-5.3.8.tar.gz file:
    tar -zxvf php-5.3.8.tar.gz
  12. Extract the libxml2 source file:
    tar -zxvf libxml2-2.7.7.tar.gz
  13. Move the libxml2-2.7.7 folder:
    cd /tmp/libxml2-2.7.7
  14. Run the commands bellow to compile the libxml2:
    ./configuremakemake install
  15. Move to the PHP source folder:
    cd /tmp/php-5.3.8
  16. Run the commands bellow to compile the PHP environment:
    ./configure --with-mysql=mysqlnd --with-libdir=lib --prefix=/usr/local/apache2 --with-apxs2=/usr/local/apache2/bin/apxs --with-openssl --with-zlib --with-gd --with-jpeg-dir=/usr/lib --with-png-dir=/usr/lib --enable-pdo --with-pdo-mysql=mysqlnd --enable-ftpmakemake install
  17. Edit using VI, the file /usr/local/apache2/conf/httpd.conf
    Add the following string, to the end of the AddType section:
    AddType application/x-httpd-php .php
    Replace the line from:
    DirectoryIndex index.htmlTo:
    DirectoryIndex index.php index.html index.htm
    Replace the value of the string, from:
    LimitRequestBody 10000To:
    LimitRequestBody 600000
  18. Copy the PHP.ini file
    cp /tmp/php-5.3.8/php.ini-development /etc/php.ini
  19. Change the permissions on the php.ini file:
    chmod 640 /etc/php.ini
  20. Edit using VI, the file /etc/php.ini
    Replace the value of the string, from:
    mysql.default_host =To:
    mysql.default_host = 127.0.0.1:3306Replace the value of the string, from:
    pdo_mysql.default_socket=To:
    pdo_mysql.default_socket=127.0.0.1Replace the value of the string, from:
    allow_url_fopen = OnTo:
    allow_url_fopen = OffReplace the value of the string, from:
    expose_php = OnTo:
    expose_php = OffReplace the value of the string, from:
    memory_limit = 128MTo:
    memory_limit = 64MReplace the value of the string, from:
    ;open_basedir =To:
    open_basedir = "/www"Replace the value of the string, from:
    post_max_size = 8MTo:
    post_max_size = 2MReplace the value of the string, from:
    disable_functions =To:
    disable_functions = fpassthru,crack_check,crack_closedict,crack_getlastmessage,crack_opendict, psockopen,php_ini_scanned_files,shell_exec,chown,hell-exec,dl,ctrl_dir,phpini,tmp,safe_mode,systemroot,server_software, get_current_user,HTTP_HOST,ini_restore,popen,pclose,exec,suExec,passthru,proc_open,proc_nice,proc_terminate, proc_get_status,proc_close,pfsockopen,leak,apache_child_terminate,posix_kill,posix_mkfifo,posix_setpgid, posix_setsid,posix_setuid,escapeshellcmd,escapeshellarg,posix_ctermid,posix_getcwd,posix_getegid,posix_geteuid,posix_getgid,posix_getgrgid, posix_getgrnam,posix_getgroups,posix_getlogin,posix_getpgid,posix_getpgrp,posix_getpid, posix_getppid,posix_getpwnam,posix_getpwuid,posix_getrlimit,system,posix_getsid,posix_getuid,posix_isatty, posix_setegid,posix_seteuid,posix_setgid,posix_times,posix_ttyname,posix_uname,posix_access,posix_get_last_error,posix_mknod, posix_strerror,posix_initgroups,posix_setsidposix_setuidReplace the value of the string, from:
    ;include_path = ".:/php/includes"To:
    include_path = "/usr/local/lib/php;/usr/local/apache2/include/php"Replace the value of the string, from:
    display_errors = OnTo:
    display_errors = OffReplace the value of the string, from:
    display_startup_errors = OnTo:
    display_startup_errors = Off

    Replace the value of the string, from:
    ;gd.jpeg_ignore_warning = 0To:
    gd.jpeg_ignore_warning = 1

  21. Run the commands bellow to restart the Apache service:
    /usr/local/apache2/bin/apachectl stop/usr/local/apache2/bin/apachectl start
  22. Remove the PHP source and test files:
    rm -f /tmp/php-5.3.8.tar.gz
    rm -f /tmp/libxml2-2.7.7.tar.gz
    rm -rf /tmp/php-5.3.8
    rm -rf /tmp/libxml2-2.7.7
    rm -rf /tmp/pear
    rm -rf /usr/local/apache2/lib/php/test
    rm -rf /usr/local/lib/php/test

Drupal installation phase

  1. Login to the server using Root account.
  2. Run the command bellow to login to the MySQL:
    /usr/bin/mysql -uroot -pnew-passwordNote: Replace the string “new-password” with the actual password for the root account.
  3. Run the following commands from the MySQL prompt:
    CREATE USER 'blgusr'@'localhost' IDENTIFIED BY 'password2';
    SET PASSWORD FOR 'blgusr'@'localhost' = OLD_PASSWORD('password2');
    CREATE DATABASE Z5J6Dw1;
    GRANT ALL PRIVILEGES ON Z5J6Dw1.* TO "blgusr"@"localhost" IDENTIFIED BY "password2";
    FLUSH PRIVILEGES;
    quit
    Note 1: Replace “blgusr” with your own MySQL account to access the database.
    Note 2: Replace “password2” with complex password (at least 14 characters).
    Note 3: Replace “Z5J6Dw1” with your own Drupal database name.
  4. Download Drupal 7.7 from:
    http://drupal.org/project/drupal
  5. Copy the Drupal 7.7 source files using PSCP (or SCP) into /www
  6. Move to /www
    cd /www
  7. Extract the file bellow:
    tar -zxvf drupal-7.7.tar.gz
  8. Remove Drupal source file:
    rm -f /www/drupal-7.7.tar.gz
  9. Rename the Drupal folder:
    mv /www/drupal-7.7 /www/drupal
  10. Remove default content:
    rm -f /www/drupal/CHANGELOG.txt
    rm -f /www/drupal/COPYRIGHT.txt
    rm -f /www/drupal/INSTALL.pgsql.txt
    rm -f /www/drupal/LICENSE.txt
    rm -f /www/drupal/UPGRADE.txt
    rm -f /www/drupal/INSTALL.mysql.txt
    rm -f /www/drupal/INSTALL.sqlite.txt
    rm -f /www/drupal/INSTALL.txt
    rm -f /www/drupal/MAINTAINERS.txt
    rm -f /www/drupal/sites/example.sites.php
  11. Edit using VI, the file /usr/local/apache2/conf/httpd.conf
    Replace the line from:
    DocumentRoot "/www"To:
    DocumentRoot "/www/drupal"
  12. Run the commands bellow to restart the Apache service:
    /usr/local/apache2/bin/apachectl stop/usr/local/apache2/bin/apachectl start
  13. Create the following folders:
    mkdir /www/drupal/sites/default/filesmkdir /www/private
  14. Copy the settings.php file:
    cp /www/drupal/sites/default/default.settings.php /www/drupal/sites/default/settings.php
  15. Change permissions on the settings.php file:
    chmod a+w /www/drupal/sites/default/settings.phpchmod -R 777 /www/drupal/sites/default/fileschmod -R 777 /www/private
  16. Open a web browser from a client machine, and enter the URL bellow:
    http://Server_FQDN/install.php
  17. Select “Standard” installation and click “Save and continue”.
  18. Choose the default “English” and click “Save and continue”.
  19. Specify the following details:
    • Database type: MySQL
    • Database name: Z5J6Dw1
    • Database username: blgusr
    • Database password: password2
    • Click on Advanced Options
    • Database host: 127.0.0.1
    • Table prefix: Z5J6Dw1_

    Note 1: Replace “Z5J6Dw1” with your own Drupal database name.
    Note 2: Replace “blgusr” with your own MySQL account to access the database.
    Note 3: Replace “password2” with complex password (at least 14 characters).

  20. Click “Save and Continue”.
  21. Specify the following information:
    • Site name
    • Site e-mail address (for automated e-mails, such as registration information)
    • Username (for the default administrator account)
    • E-mail address
    • Password
  22. Select “Default country” and “Default time zone”.
  23. Unselect the “Update Notifications” checkboxes.
  24. Click “Save and Continue”.
  25. Close the web browser.
  26. Create using VI the file /www/config.php with the following content:
    <?php
    $databases = array (
    'default' =>
    array (
    'default' =>
    array (
    'driver' => 'mysql',
    'database' => 'Z5J6Dw1',
    'username' => 'blgusr',
    'password' => 'password2',
    'host' => '127.0.0.1',
    'port' => '',
    'prefix' => 'Z5J6Dw1_',
    ),
    ),
    );
    ?>
    Note 1: Make sure there are no spaces, newlines, or other strings before an opening ‘< ?php’ tag or after a closing ‘?>’ tag.
    Note 2: Replace “blgusr” with your own MySQL account to access the database.
    Note 3: Replace “password2” with complex password (at least 14 characters).
    Note 4: Replace “Z5J6Dw1” with your own Drupal database name.
  27. Edit using VI, the file /www/drupal/sites/default/settings.php
    Add the following line:
    include('/www/config.php');Remove the following section:
    $databases = array (
    'default' =>
    array (
    'default' =>
    array (
    'driver' => 'mysql',
    'database' => 'Z5J6Dw1',
    'username' => 'blgusr',
    'password' => 'password2',
    'host' => '127.0.0.1',
    'port' => '',
    'prefix' => 'Z5J6Dw1_',
    ),
    ),
    );
    Replace the string from:
    ini_set('session.cookie_lifetime', 2000000);To:
    ini_set('session.cookie_lifetime', 0);
  28. Change permissions on the settings.php file:
    chmod a-w /www/drupal/sites/default/settings.php
  29. Add the following lines to the /www/drupal/.htaccess file:
    # Block any file that starts with "."
    <FilesMatch "^\..*$">
    Order allow,deny
    </FilesMatch>
    <FilesMatch "^.*\..*$">
    Order allow,deny
    </FilesMatch>
    # Allow "." files with safe content types
    <FilesMatch "^.*\.(css|html?|txt|js|xml|xsl|gif|ico|jpe?g|png)$">
    Order deny,allow
    </FilesMatch>
  30. Run the command bellow to change permissions on the /www/drupal/.htaccess file:
    chmod 444 /www/drupal/.htaccess
  31. Download into /www/drupal/sites/all/modulesthe latest build of the modules bellow:
  32. From SSH session, move to the folder /www/drupal/sites/all/modules.
  33. Extract the downloaded above modules:
    tar zxvf dfw-7.x-1.1.tar.gztar zxvf spamspan-7.x-1.1-beta1.tar.gztar zxvf content_security_policy-7.x-1.x-dev.tar.gztar zxvf goaway-7.x-1.2.tar.gztar zxvf ip_anon-7.x-1.0.tar.gztar zxvf flood_control-7.x-1.0.tar.gztar zxvf password_policy-7.x-1.0-beta1.tar.gztar zxvf persistent_login-7.x-1.x-dev.tar.gztar zxvf secure_permissions-7.x-1.5.tar.gztar zxvf security_review-7.x-1.x-dev.tar.gztar zxvf system_perm-7.x-1.x-dev.tar.gztar zxvf blockanonymouslinks-7.x-1.1.tar.gz
  34. Remove the modules source files:
    rm -f /www/drupal/sites/all/modules/dfw-7.x-1.1.tar.gzrm -f /www/drupal/sites/all/modules/spamspan-7.x-1.1-beta1.tar.gzrm -f /www/drupal/sites/all/modules/content_security_policy-7.x-1.x-dev.tar.gzrm -f /www/drupal/sites/all/modules/goaway-7.x-1.2.tar.gzrm -f /www/drupal/sites/all/modules/ip_anon-7.x-1.0.tar.gzrm -f /www/drupal/sites/all/modules/flood_control-7.x-1.0.tar.gzrm -f /www/drupal/sites/all/modules/password_policy-7.x-1.0-beta1.tar.gzrm -f /www/drupal/sites/all/modules/persistent_login-7.x-1.x-dev.tar.gzrm -f /www/drupal/sites/all/modules/secure_permissions-7.x-1.5.tar.gzrm -f /www/drupal/sites/all/modules/security_review-7.x-1.x-dev.tar.gzrm -f /www/drupal/sites/all/modules/system_perm-7.x-1.x-dev.tar.gz

    rm -f /www/drupal/sites/all/modules/blockanonymouslinks-7.x-1.1.tar.gz

  35. Open a web browser from a client machine, and enter the URL bellow:
    http://Server_FQDN/?q=user/login
  36. From the upper menu, click on Configuration -> People -> Account Settings -> “Who can register accounts”: select Administrators only -> click on “Save configuration”.
  37. From the upper menu, click on Configuration -> Media -> File system -> “Private file system path”: specify /www/private -> click on “Save configuration”.
  38. From the upper menu, click on Configuration -> Development -> Logging and errors -> “Error messages to display”: select None -> click on “Save configuration”.
  39. From the upper menu, click on Modules -> from the list of modules, select “Update manager” -> click on “Save configuration”.
  40. From the upper menu, click on Modules -> from the main page, select the following modules:
    • Drupal firewall
    • SpamSpan
    • Content Security Policy
    • Content Security Policy Reporting
    • GoAway
    • IP anonymize
    • Flood control
    • Password change tab
    • Password policy
    • Persistent Login
    • Secure Permissions
    • Security Review
    • System Perms
    • BlockAnonymousLinks
  41. Click on Save configuration.

Drupal SSL configuration phase

  1. Add the following line to the /www/drupal/sites/default/settings.php file:
    $conf['https'] = TRUE;
  2. Download into /www/drupal/sites/all/modulesthe latest build of the modules bellow:
  3. From SSH session, move to the folder /www/drupal/sites/all/modules.
  4. Extract the downloaded above modules:
    tar zxvf securepages-7.x-1.x-dev.tar.gztar zxvf securelogin-7.x-1.2.tar.gz
  5. Remove the modules source files:
    rm -f /www/drupal/sites/all/modules/securepages-7.x-1.x-dev.tar.gzrm -f /www/drupal/sites/all/modules/securelogin-7.x-1.2.tar.gz
  6. Open a web browser from a client machine, and enter the URL bellow:
    https://Server_FQDN/?q=user/login
  7. From the upper menu, click on Modules -> from the main page, select the following modules:
    • Secure Login
    • Secure Pages
  8. Click on Save configuration.
  9. From the upper menu, click on Configuration -> from the main page, click on the link Secure Pages -> under Enable Secure Pages -> choose Enabled -> click on Save configuration.

Hardening guide for WordPress 3.0 for hosted web sites

Important note: Make sure your hosting provider is using the most up-to-date build of WordPress.

  1. Request from your hosting provider access through SSH.
  2. Login to the hosted server using SSH.
  3. Edit using VI the file ~/html/wp-config.php and write down the data of the following values:
    • DB_NAME
    • DB_USER
    • DB_PASSWORD
  4. Create using VI the file ~/config.php with the following content:
    <?php
    define('DB_NAME', 'm6gf42s');
    define('DB_USER', 'blgusr');
    define('DB_PASSWORD', 'password2');
    define('AUTH_KEY', 'put your unique phrase here');
    define('SECURE_AUTH_KEY', 'put your unique phrase here');
    define('LOGGED_IN_KEY', 'put your unique phrase here');
    define('NONCE_KEY', 'put your unique phrase here');
    define('AUTH_SALT', 'put your unique phrase here');
    define('SECURE_AUTH_SALT', 'put your unique phrase here');
    define('LOGGED_IN_SALT', 'put your unique phrase here');
    define('NONCE_SALT', 'put your unique phrase here');
    ?>
    Note 1: Make sure there are no spaces, newlines, or other strings before an opening ‘< ?php‘ tag or after a closing ‘?>‘ tag.
    Note 2: Replace “blgusr” with the MySQL account to access the database.
    Note 3: Replace “password2” with the MySQL account password.
    Note 4: Replace “m6gf42s” with the WordPress database name.
    Note 5: In-order to generate random values for the AUTH_KEY, SECURE_AUTH_KEY, LOGGED_IN_KEY and NONCE_KEY, use the web site bellow:
    http://api.wordpress.org/secret-key/1.1/
  5. Edit using VI, the file ~/html/wp-config.php
    Add the following line:
    include('/path/config.php');Note: Replace /path/ with the full path to the config.php file.

    Remove the following sections:
    define('DB_NAME', 'putyourdbnamehere');
    define('DB_USER', 'usernamehere');
    define('DB_PASSWORD', 'yourpasswordhere');
    define('AUTH_KEY', 'put your unique phrase here');
    define('SECURE_AUTH_KEY', 'put your unique phrase here');
    define('LOGGED_IN_KEY', 'put your unique phrase here');
    define('NONCE_KEY', 'put your unique phrase here');
    define('AUTH_SALT', 'put your unique phrase here');
    define('SECURE_AUTH_SALT', 'put your unique phrase here');
    define('LOGGED_IN_SALT', 'put your unique phrase here');
    define('NONCE_SALT', 'put your unique phrase here');

  6. Remove default content:
    rm -f ~/html/license.txt
    rm -f ~/html/readme.html
    rm -f ~/html/wp-config-sample.php
    rm -f ~/html/wp-content/plugins/hello.php
  7. Create using VI the file ~/html/.htaccess with the following content:
    <files wp-config.php>
    Order deny,allow
    deny from all
    </files>
    <Files wp-login.php>
    AuthUserFile /dev/null
    AuthGroupFile /dev/null
    AuthName "Access Control"
    AuthType Basic
    </Files>
  8. Create using VI the file ~/html/wp-content/plugins/.htaccess with the following content:
    AuthUserFile /dev/null
    AuthGroupFile /dev/null
    AuthName "Access Control"
    AuthType Basic
  9. Create the following folders:
    mkdir -p ~/html/wp-content/cache
    mkdir -p ~/html/wp-content/uploads
    mkdir -p ~/html/wp-content/upgrade
  10. Change the file permissions:
    chmod -R 777 ~/html/wp-content/cache
    chmod -R 777 ~/html/wp-content/uploads
    chmod -R 777 ~/html/wp-content/upgrade
  11. Download “Login Lockdown” plugin from:
    http://www.bad-neighborhood.com/login-lockdown.html
  12. Download “Limit Login” plugin from:
    http://wordpress.org/extend/plugins/limit-login-attempts/
  13. Download “WP-Secure Remove WordPress Version” plugin from:
    http://wordpress.org/extend/plugins/wp-secure-remove-wordpress-version/
  14. Download “WP Security Scan” plugin from:
    http://wordpress.org/extend/plugins/wp-security-scan/
  15. Download “KB Robots.txt” plugin from:
    http://wordpress.org/extend/plugins/kb-robotstxt/
  16. Download “WordPress Firewall” plugin from:
    http://www.seoegghead.com/software/wordpress-firewall.seo
  17. Copy the “WordPress Firewall” plugin file “wordpress-firewall.php” using PSCP (or SCP) into /html/wp-content/plugins
  18. Open a web browser from a client machine, and enter the URL bellow:
    http://Server_FQDN/wp-login.php
  19. From WordPress dashboard, click on “settings” -> make sure that “Anyone can register” is left unchecked -> put a new value inside the “Tagline” field -> click on “Save changes”.
  20. Click on “Save changes”.
  21. From WordPress dashboard, click on “Plugins” -> Add New -> choose “Upload” -> click Browse to locate the plugin -> click “Install Now” -> click “Proceed” -> click on “Activate Plugin”.
    Note: Install and activate all the above downloaded plugins.
  22. From WordPress dashboard, click on “settings” -> click on “KB Robots.txt” -> add the following content into the Robots.txt editor field:
    Disallow: /wp-*
    Disallow: /wp-admin
    Disallow: /wp-includes
    Disallow: /wp-content/plugins
    Disallow: /wp-content/cache
    Disallow: /wp-content/themes
    Disallow: /wp-login.php
    Disallow: /wp-register.php
  23. Click “Submit”.
  24. From the upper pane, click on “Log Out”.
  25. Delete the file /wp-admin/install.php
  26. In-case the server was configured with SSL certificate, add the following line to the config.php file:
    define('FORCE_SSL_LOGIN', true);

Hardening guide for WordPress 3.0

Pre-installation notes
The guide bellow is based on the previous guides:

Installation and configuration phase

  1. Login to the server using Root account.
  2. Create a new account for uploading files using SSH:
    groupadd sshaccount
    useradd -g sshaccount -d /home/sshaccount -m sshaccount
  3. Run the commands bellow to switch to the SSH account:
    su sshaccount
  4. Run the command bellow to generate SSH keys:
    ssh-keygen
    Note: Leave deafult values for the ssh-keygen.
  5. Copy the SSH keys:
    cp /home/sshaccount/.ssh/id_rsa.pub /home/sshaccount/.ssh/authorized_keys
  6. Change permissions for the SSH keys:
    chmod 755 /home/sshaccount/.ssh
    chmod 644 /home/sshaccount/.ssh/*
  7. Exit the SSH account shell and return to the Root account:
    exit
  8. Run the command bellow to login to the MySQL:
    /usr/bin/mysql -uroot -pnew-password
    Note: Replace the string “new-password” with the actual password for the root account.
  9. Run the following commands from the MySQL prompt:
    CREATE USER 'blgusr'@'localhost' IDENTIFIED BY 'password2';
    SET PASSWORD FOR 'blgusr'@'localhost' = OLD_PASSWORD('password2');
    CREATE DATABASE m6gf42s;
    GRANT ALL PRIVILEGES ON m6gf42s.* TO "blgusr"@"localhost" IDENTIFIED BY "password2";
    FLUSH PRIVILEGES;
    quit
    Note 1: Replace “blgusr” with your own MySQL account to access the database.
    Note 2: Replace “password2” with complex password (at least 14 characters).
    Note 3: Replace “m6gf42s” with your own WordPress database name.
  10. Download WordPress 3.0 from:
    http://wordpress.org/download
  11. Copy the WordPress 3.0 source files using PSCP (or SCP) into /www
  12. Move to /www
    cd /www
  13. Extract the wordpress-3.0.zip file:
    unzip wordpress-3.0.zip
  14. Remove WordPress source file:
    rm -f /www/wordpress-3.0.zip
  15. Create using VI the file /www/config.php with the following content:
    <?php
    define('DB_NAME', 'm6gf42s');
    define('DB_USER', 'blgusr');
    define('DB_PASSWORD', 'password2');
    define('DB_HOST', '127.0.0.1');
    $table_prefix = 'm6gf42s_';
    define('AUTH_KEY', 'put your unique phrase here');
    define('SECURE_AUTH_KEY', 'put your unique phrase here');
    define('LOGGED_IN_KEY', 'put your unique phrase here');
    define('NONCE_KEY', 'put your unique phrase here');
    define('AUTH_SALT', 'put your unique phrase here');
    define('SECURE_AUTH_SALT', 'put your unique phrase here');
    define('LOGGED_IN_SALT', 'put your unique phrase here');
    define('NONCE_SALT', 'put your unique phrase here');
    define('FS_METHOD', 'direct');
    define('FS_CHMOD_DIR', 0777);
    define('FS_CHMOD_FILE', 0777);
    define('FTP_BASE', '/www/wordpress/');
    define('FTP_CONTENT_DIR', '/www/wordpress/wp-content/');
    define('FTP_PLUGIN_DIR ', '/www/wordpress/wp-content/plugins/');
    define('FTP_PUBKEY', '/home/sshaccount/.ssh/id_rsa.pub');
    define('FTP_PRIKEY', '/home/sshaccount/.ssh/id_rsa');
    define('FTP_USER', 'sshaccount');
    define('FTP_HOST', '127.0.0.1:22');
    ?>
    Note 1: Make sure there are no spaces, newlines, or other strings before an opening ‘< ?php‘ tag or after a closing ‘?>‘ tag.
    Note 2: Replace “blgusr” with your own MySQL account to access the database.
    Note 3: Replace “password2” with complex password (at least 14 characters).
    Note 4: Replace “m6gf42s” with your own WordPress database name.
    Note 5: In-order to generate random values for the AUTH_KEY, SECURE_AUTH_KEY, LOGGED_IN_KEY and NONCE_KEY, use the web site bellow:
    http://api.wordpress.org/secret-key/1.1/
  16. Copy the wp-config.php file:
    cp /www/wordpress/wp-config-sample.php /www/wordpress/wp-config.php
  17. Edit using VI, the file /www/wordpress/wp-config.php
    Add the following line:
    include('/www/config.php');

    Remove the following sections:
    define('DB_NAME', 'putyourdbnamehere');
    define('DB_USER', 'usernamehere');
    define('DB_PASSWORD', 'yourpasswordhere');
    define('DB_HOST', 'localhost');
    $table_prefix = 'wp_';
    define('AUTH_KEY', 'put your unique phrase here');
    define('SECURE_AUTH_KEY', 'put your unique phrase here');
    define('LOGGED_IN_KEY', 'put your unique phrase here');
    define('NONCE_KEY', 'put your unique phrase here');
    define('AUTH_SALT', 'put your unique phrase here');
    define('SECURE_AUTH_SALT', 'put your unique phrase here');
    define('LOGGED_IN_SALT', 'put your unique phrase here');
    define('NONCE_SALT', 'put your unique phrase here');

  18. Remove default content:
    rm -f /www/wordpress/license.txt
    rm -f /www/wordpress/readme.html
    rm -f /www/wordpress/wp-config-sample.php
    rm -f /www/wordpress/wp-content/plugins/hello.php
  19. Edit using VI the file /usr/local/apache2/conf/httpd.conf
    Replace the value of the string, from:
    DocumentRoot "/www"To:
    DocumentRoot "/www/wordpress"

    Replace the value of the string, from:
    LimitRequestBody 10000To:
    LimitRequestBody 200000

  20. Restart the Apache service.
  21. Open a web browser from a client machine, and enter the URL bellow:
    http://Server_FQDN/wp-admin/install.php
  22. Specify the following information:
    • Site Title
    • Username – replace the default “admin
    • Password
    • E-mail
  23. Click on “Install WordPress” button, and close the web browser.
  24. Create using VI the file /www/wordpress/.htaccess with the following content:
    <files wp-config.php>
    Order deny,allow
    deny from all
    </files>
    <Files wp-login.php>
    AuthUserFile /dev/null
    AuthGroupFile /dev/null
    AuthName "Access Control"
    AuthType Basic
    Order deny,allow
    Deny from All
    Allow from 1.1.1.0
    </Files>
    RewriteEngine On
    RewriteCond %{REQUEST_METHOD} POST
    RewriteCond %{REQUEST_URI} .wp-comments-post\.php*
    RewriteCond %{HTTP_REFERER} !.*Server_FQDN.* [OR]
    RewriteCond %{HTTP_USER_AGENT} ^$
    RewriteRule (.*) ^http://%{REMOTE_ADDR}/$ [R=301,L]
    Note 1: Replace 1.1.1.0 with the internal network IP address.
    Note 2: Replace Server_FQDN with the server FQDN (DNS name).
  25. Create using VI the file /www/wordpress/wp-admin/.htaccess with the following content:
    AuthUserFile /dev/null
    AuthGroupFile /dev/null
    AuthName “Access Control”
    AuthType Basic
    <LIMIT GET POST>
    order deny,allow
    deny from all
    Allow from 1.1.1.0
    </LIMIT>
    <IfModule mod_security.c>
    SecFilterInheritance Off
    </IfModule>
    Note: Replace 1.1.1.0 with the internal network IP address.
  26. Create using VI the file /www/wordpress/wp-content/plugins/.htaccess with the following content:
    AuthUserFile /dev/null
    AuthGroupFile /dev/null
    AuthName "Access Control"
    AuthType Basic
    Order deny,allow
    Deny from All
    Allow from 1.1.1.0
    Note: Replace 1.1.1.0 with the internal network IP address.
  27. Create the following folders:
    mkdir -p /www/wordpress/wp-content/cache
    mkdir -p /www/wordpress/wp-content/uploads
    mkdir -p /www/wordpress/wp-content/upgrade
  28. Change the file permissions:
    chown -R root:root /www/wordpress
    chown daemon:root /www/wordpress/wp-content/plugins
    chmod 644 /www/config.php
    chmod 644 /www/wordpress/wp-config.php
    chmod 644 /www/wordpress/.htaccess
    chmod 644 /www/wordpress/wp-admin/.htaccess
    chmod 644 /www/wordpress/wp-content/plugins/.htaccess
    chmod -R 777 /www/wordpress/wp-content/cache
    chmod -R 777 /www/wordpress/wp-content/uploads
    chmod -R 777 /www/wordpress/wp-content/upgrade
  29. Download “Login Lockdown” plugin from:
    http://www.bad-neighborhood.com/login-lockdown.html
  30. Download “Limit Login” plugin from:
    http://wordpress.org/extend/plugins/limit-login-attempts/
  31. Download “WP-Secure Remove WordPress Version” plugin from:
    http://wordpress.org/extend/plugins/wp-secure-remove-wordpress-version/
  32. Download “WP Security Scan” plugin from:
    http://wordpress.org/extend/plugins/wp-security-scan/
  33. Download “KB Robots.txt” plugin from:
    http://wordpress.org/extend/plugins/kb-robotstxt/
  34. Download “WordPress Database Backup” plugin from:
    http://austinmatzko.com/wordpress-plugins/wp-db-backup/
  35. Download “WordPress Firewall” plugin from:
    http://www.seoegghead.com/software/wordpress-firewall.seo
  36. Copy the “WordPress Firewall” plugin file “wordpress-firewall.php” using PSCP (or SCP) into /www/wordpress/wp-content/plugins
  37. Create a folder for the “WordPress Database Backup” plugin:
    mkdir -p /www/wordpress/wp-content/backup-ed602
  38. Set permissions for the “WordPress Database Backup” plugin:
    chmod 777 /www/wordpress/wp-content/backup-ed602
  39. Open a web browser from a client machine, and enter the URL bellow:
    http://Server_FQDN/wp-login.php
  40. From WordPress dashboard, click on “settings” -> make sure that “Anyone can register” is left unchecked -> put a new value inside the “Tagline” field -> click on “Save changes”.
  41. From WordPress dashboard, click on “settings” -> click on “Media” -> “Store uploads in this folder” -> specify:
    wp-content/uploads
  42. Click on “Save changes”.
  43. From WordPress dashboard, click on “Plugins” -> Add New -> choose “Upload” -> click Browse to locate the plugin -> click “Install Now” -> click “Proceed” -> click on “Activate Plugin”.
    Note: Install and activate all the above downloaded plugins.
  44. From WordPress dashboard, click on “settings” -> click on “KB Robots.txt” -> add the following content into the Robots.txt editor field:
    Disallow: /wp-*
    Disallow: /wp-admin
    Disallow: /wp-includes
    Disallow: /wp-content/plugins
    Disallow: /wp-content/cache
    Disallow: /wp-content/themes
    Disallow: /wp-login.php
    Disallow: /wp-register.php
  45. Click “Submit”.
  46. From the upper pane, click on “Log Out”.
  47. Delete the file /wp-admin/install.php
  48. In-case the server was configured with SSL certificate, add the following line to the /www/config.php file:
    define('FORCE_SSL_LOGIN', true);

Hardening guide for WordPress 2.9.2


Pre-installation notes
The guide bellow is based on the previous guides:

Installation and configuration phase

  1. Login to the server using Root account.
  2. Create a new account for uploading files using SSH:
    groupadd sshaccount
    useradd -g sshaccount -d /home/sshaccount -m sshaccount
  3. Run the commands bellow to switch to the SSH account:
    su sshaccount
  4. Run the command bellow to generate SSH keys:
    ssh-keygen
    Note: Leave deafult values for the ssh-keygen.
  5. Copy the SSH keys:
    cp /home/sshaccount/.ssh/id_rsa.pub /home/sshaccount/.ssh/authorized_keys
  6. Change permissions for the SSH keys:
    chmod 755 /home/sshaccount/.ssh
    chmod 644 /home/sshaccount/.ssh/*
  7. Exit the SSH account shell and return to the Root account:
    exit
  8. Run the command bellow to login to the MySQL:
    /usr/bin/mysql -uroot -pnew-password
    Note: Replace the string “new-password” with the actual password for the root account.
  9. Run the following commands from the MySQL prompt:
    CREATE USER 'blgusr'@'localhost' IDENTIFIED BY 'password2';
    SET PASSWORD FOR 'blgusr'@'localhost' = OLD_PASSWORD('password2');
    CREATE DATABASE m6gf42s;
    GRANT ALL PRIVILEGES ON m6gf42s.* TO "blgusr"@"localhost" IDENTIFIED BY "password2";
    FLUSH PRIVILEGES;
    quit

    Note 1: Replace “blgusr” with your own MySQL account to access the database.
    Note 2: Replace “password2” with complex password (at least 14 characters).
    Note 3: Replace “m6gf42s” with your own WordPress database name.
  10. Download WordPress 2.9.2 from:
    http://wordpress.org/download
  11. Copy the WordPress 2.9.2 source files using PSCP (or SCP) into /www
  12. Move to /www
    cd /www
  13. Extract the wordpress-2.9.2.tar.gz file:
    tar -zxvf wordpress-2.9.2.tar.gz
  14. Remove WordPress source file:
    rm -f /www/wordpress-2.9.2.tar.gz
  15. Create using VI the file /www/config.php with the following content:
    <?php
    define('DB_NAME', 'm6gf42s');
    define('DB_USER', 'blgusr');
    define('DB_PASSWORD', 'password2');
    define('DB_HOST', '127.0.0.1');
    $table_prefix = 'm6gf42s_';
    define('AUTH_KEY', 'put your unique phrase here');
    define('SECURE_AUTH_KEY', 'put your unique phrase here');
    define('LOGGED_IN_KEY', 'put your unique phrase here');
    define('NONCE_KEY', 'put your unique phrase here');
    define('FS_METHOD', 'direct');
    define('FS_CHMOD_DIR', 0777);
    define('FS_CHMOD_FILE', 0777);
    define('FTP_BASE', '/www/wordpress/');
    define('FTP_CONTENT_DIR', '/www/wordpress/wp-content/');
    define('FTP_PLUGIN_DIR ', '/www/wordpress/wp-content/plugins/');
    define('FTP_PUBKEY', '/home/sshaccount/.ssh/id_rsa.pub');
    define('FTP_PRIKEY', '/home/sshaccount/.ssh/id_rsa');
    define('FTP_USER', 'sshaccount');
    define('FTP_HOST', '127.0.0.1:22');
    ?>
    Note 1: Make sure there are no spaces, newlines, or other strings before an opening ‘< ?php‘ tag or after a closing ‘?>‘ tag.
    Note 2: Replace “blgusr” with your own MySQL account to access the database.
    Note 3: Replace “password2” with complex password (at least 14 characters).
    Note 4: Replace “m6gf42s” with your own WordPress database name.
    Note 5: In-order to generate random values for the AUTH_KEY, SECURE_AUTH_KEY, LOGGED_IN_KEY and NONCE_KEY, use the web site bellow:
    http://api.wordpress.org/secret-key/1.1/
  16. Copy the wp-config.php file:
    cp /www/wordpress/wp-config-sample.php /www/wordpress/wp-config.php
  17. Edit using VI, the file /www/wordpress/wp-config.php
    Add the following line:
    include('/www/config.php');Remove the following sections:
    define('DB_NAME', 'putyourdbnamehere');
    define('DB_USER', 'usernamehere');
    define('DB_PASSWORD', 'yourpasswordhere');
    define('DB_HOST', 'localhost');
    $table_prefix = 'wp_';
    define('AUTH_KEY', 'put your unique phrase here');
    define('SECURE_AUTH_KEY', 'put your unique phrase here');
    define('LOGGED_IN_KEY', 'put your unique phrase here');
    define('NONCE_KEY', 'put your unique phrase here');
  18. Remove default content:
    rm -f /www/wordpress/license.txt
    rm -f /www/wordpress/readme.html
    rm -f /www/wordpress/wp-config-sample.php
    rm -f /www/wordpress/wp-content/plugins/hello.php
  19. Edit using VI the file /usr/local/apache2/conf/httpd.conf
    Replace the value of the string, from:
    DocumentRoot "/www"
    To:
    DocumentRoot "/www/wordpress"
    Replace the value of the string, from:
    LimitRequestBody 10000
    To:
    LimitRequestBody 200000
  20. Restart the Apache service.
  21. Open a web browser from a client machine, and enter the URL bellow:
    http://Server_FQDN/wp-admin/install.php
  22. Specify the following information:
    • Blog Title
    • E-Mail
  23. Click on “Install WordPress” button, and close the web browser.
  24. Run the command bellow to login to the MySQL:
    /usr/bin/mysql -uroot -pnew-password
    Note: Replace the string “new-password” with the actual password for the root account.
  25. Run the following commands from the MySQL prompt:
    use m6gf42s;
    UPDATE m6gf42s_users SET user_login='johnd' WHERE user_login='admin';
    UPDATE m6gf42s_users SET user_pass=MD5('password3') WHERE user_login='johnd';
    FLUSH PRIVILEGES;
    quit
    Note 1: Replace “m6gf42s” with your own WordPress database name.
    Note 1: Replace “johnd” with your own new WordPress admin.
    Note 2: Replace “password3” with complex password (at least 14 characters).
  26. Edit using VI, the file /www/wordpress/wp-includes/http.php and replace the following line from:
    'timeout' => apply_filters( 'http_request_timeout', 5),
    To:
    'timeout' => apply_filters( 'http_request_timeout', 30),
  27. Create using VI the file /www/wordpress/.htaccess with the following content:
    <files wp-config.php>
    Order deny,allow
    deny from all
    </files>
    <Files wp-login.php>
    AuthUserFile /dev/null
    AuthGroupFile /dev/null
    AuthName "Access Control"
    AuthType Basic
    Order deny,allow
    Deny from All
    Allow from 1.1.1.0
    </Files>
    RewriteEngine On
    RewriteCond %{REQUEST_METHOD} POST
    RewriteCond %{REQUEST_URI} .wp-comments-post\.php*
    RewriteCond %{HTTP_REFERER} !.*Server_FQDN.* [OR]
    RewriteCond %{HTTP_USER_AGENT} ^$
    RewriteRule (.*) ^http://%{REMOTE_ADDR}/$ [R=301,L]
    Note 1: Replace 1.1.1.0 with the internal network IP address.
    Note 2: Replace Server_FQDN with the server FQDN (DNS name).
  28. Create using VI the file /www/wordpress/wp-admin/.htaccess with the following content:
    AuthUserFile /dev/null
    AuthGroupFile /dev/null
    AuthName “Access Control”
    AuthType Basic
    <LIMIT GET POST>
    order deny,allow
    deny from all
    Allow from 1.1.1.0
    </LIMIT>
    <IfModule mod_security.c>
    SecFilterInheritance Off
    </IfModule>
    Note: Replace 1.1.1.0 with the internal network IP address.
  29. Create using VI the file /www/wordpress/wp-content/plugins/.htaccess with the following content:
    AuthUserFile /dev/null
    AuthGroupFile /dev/null
    AuthName "Access Control"
    AuthType Basic
    Order deny,allow
    Deny from All
    Allow from 1.1.1.0
    Note: Replace 1.1.1.0 with the internal network IP address.
  30. Create the following folders:
    mkdir -p /www/wordpress/wp-content/cache
    mkdir -p /www/wordpress/wp-content/uploads
    mkdir -p /www/wordpress/wp-content/upgrade
  31. Change the file permissions:
    chown -R root:root /www/wordpress
    chown daemon:root /www/wordpress/wp-content/plugins
    chmod 644 /www/config.php
    chmod 644 /www/wordpress/wp-config.php
    chmod 644 /www/wordpress/.htaccess
    chmod 644 /www/wordpress/wp-admin/.htaccess
    chmod 644 /www/wordpress/wp-content/plugins/.htaccess
    chmod -R 777 /www/wordpress/wp-content/cache
    chmod -R 777 /www/wordpress/wp-content/uploads
    chmod -R 777 /www/wordpress/wp-content/upgrade
  32. Download “Login Lockdown” plugin from:
    http://www.bad-neighborhood.com/login-lockdown.html
  33. Download “WP-Secure Remove WordPress Version” plugin from:
    http://wordpress.org/extend/plugins/wp-secure-remove-wordpress-version/
  34. Download “WP Security Scan” plugin from:
    http://wordpress.org/extend/plugins/wp-security-scan/
  35. Download “KB Robots.txt” plugin from:
    http://wordpress.org/extend/plugins/kb-robotstxt/
  36. Download “WordPress Database Backup” plugin from:
    http://austinmatzko.com/wordpress-plugins/wp-db-backup/
  37. Download “WordPress Firewall” plugin from:
    http://www.seoegghead.com/software/wordpress-firewall.seo
  38. Copy the “WordPress Firewall” plugin file “wordpress-firewall.php” using PSCP (or SCP) into /www/wordpress/wp-content/plugins
  39. Create a folder for the “WordPress Database Backup” plugin:
    mkdir -p /www/wordpress/wp-content/backup-ed602
  40. Set permissions for the “WordPress Database Backup” plugin:
    chmod 777 /www/wordpress/wp-content/backup-ed602
  41. Open a web browser from a client machine, and enter the URL bellow:
    http://Server_FQDN/wp-login.php
  42. From WordPress dashboard, click on “settings” -> make sure that “Anyone can register” is left unchecked -> click on “Save changes”.
  43. From WordPress dashboard, click on “settings” -> click on “Miscellaneous” -> “Store uploads in this folder” -> specify:
    wp-content/uploads
  44. Click on “Save changes”.
  45. From WordPress dashboard, click on “Plugins” -> Add New -> choose “Upload” -> click Browse to locate the plugin -> click “Install Now” -> click “Proceed” -> click on “Activate Plugin”.
    Note: Install and activate all the above downloaded plugins.
  46. From WordPress dashboard, click on “settings” -> click on “KB Robots.txt” -> add the following content into the Robots.txt editor field:
    Disallow: /wp-*
    Disallow: /wp-admin
    Disallow: /wp-includes
    Disallow: /wp-content/plugins
    Disallow: /wp-content/cache
    Disallow: /wp-content/themes
    Disallow: /wp-login.php
    Disallow: /wp-register.php
  47. Click “Submit”.
  48. From the upper pane, click on “Log Out”.
  49. In-case the server was configured with SSL certificate, add the following line to the /www/config.php file:
    define('FORCE_SSL_LOGIN', true);

Hardening guide for PHP 5.3.2 on Apache 2.2.15 / MySQL 5.1.47 (RHEL 5.4)

Pre-installation notes
The guide bellow is based on the previous guides:

Installation and configuration phase

  1. Login to the server using Root account.
  2. Before compiling the PHP environment, install the following RPM from the RHEL 5.4 (64bit) DVD source folder:
    rpm -ivh kernel-headers-2.6.18-164.el5.x86_64.rpm
    rpm -ivh glibc-headers-2.5-42.x86_64.rpm
    rpm -ivh glibc-devel-2.5-42.x86_64.rpm
    rpm -ivh gmp-4.1.4-10.el5.x86_64.rpm
    rpm -ivh libgomp-4.4.0-6.el5.x86_64.rpm
    rpm -ivh gcc-4.1.2-46.el5.x86_64.rpm
    rpm -ivh libxml2-2.6.26-2.1.2.8.x86_64.rpm
    rpm -ivh zlib-devel-1.2.3-3.x86_64.rpm
    rpm -ivh libxml2-devel-2.6.26-2.1.2.8.x86_64.rpm
  3. Download MySQL development RPM from:
    http://download.softagency.net/MySQL/Downloads/MySQL-5.1/
  4. Download PHP 5.3.2 source files from:
    http://php.net/downloads.php
  5. Copy the MySQL development RPM using PSCP (or SCP) into /tmp
  6. Copy the PHP 5.3.2 source files using PSCP (or SCP) into /tmp
  7. Move to /tmp
    cd /tmp
  8. Install the MySQL development RPM:
    rpm -ivh MySQL-devel-community-5.1.47-1.rhel5.x86_64.rpm
  9. Remove MySQL development RPM:
    rm -f MySQL-devel-community-5.1.47-1.rhel5.x86_64.rpm
  10. Extract the php-5.3.2.tar.gz file:
    tar -zxvf php-5.3.2.tar.gz
  11. Move to the PHP source folder:
    cd /tmp/php-5.3.2
  12. Run the commands bellow to compile the PHP environment:
    ./configure --with-mysql=/var/lib/mysql --with-libdir=lib64 --prefix=/usr/local/apache2 --with-apxs2=/usr/local/apache2/bin/apxs --with-openssl --with-zlib

    make

    make install

  13. Edit using VI, the file /usr/local/apache2/conf/httpd.conf
    Make sure the following string exists at the end of the LoadModule section:
    LoadModule php5_module modules/libphp5.so
    Add the following string, to the end of the AddType section:
    AddType application/x-httpd-php .php
    Replace the line from:
    DirectoryIndex index.htmlTo:
    DirectoryIndex index.php index.html index.htm
  14. Copy the PHP.ini file
    cp /tmp/php-5.3.2/php.ini-development /etc/php.ini
  15. Change the permissions on the php.ini file:
    chmod 640 /etc/php.ini
  16. Edit using VI, the file /etc/php.ini and replace the following values:
    From:
    mysql.default_host =To:
    mysql.default_host = 127.0.0.1:3306

    From:
    allow_url_fopen = OnTo:
    allow_url_fopen = Off

    From:
    expose_php = OnTo:
    expose_php = Off

    From:
    memory_limit = 128MTo:
    memory_limit = 8M

    From:
    ;open_basedir =To:
    open_basedir = "/www"

    From:
    post_max_size = 8MTo:
    post_max_size = 2M

    From:
    upload_max_filesize = 2MTo:
    upload_max_filesize = 1M

    From:
    disable_functions =To:
    disable_functions = fpassthru,crack_check,crack_closedict,crack_getlastmessage,crack_opendict, psockopen,php_ini_scanned_files,shell_exec,chown,hell-exec,dl,ctrl_dir,phpini,tmp,safe_mode,systemroot,server_software, get_current_user,HTTP_HOST,ini_restore,popen,pclose,exec,suExec,passthru,proc_open,proc_nice,proc_terminate, proc_get_status,proc_close,pfsockopen,leak,apache_child_terminate,posix_kill,posix_mkfifo,posix_setpgid, posix_setsid,posix_setuid,escapeshellcmd,escapeshellarg,posix_ctermid,posix_getcwd,posix_getegid,posix_geteuid,posix_getgid,posix_getgrgid, posix_getgrnam,posix_getgroups,posix_getlogin,posix_getpgid,posix_getpgrp,posix_getpid, posix_getppid,posix_getpwnam,posix_getpwuid,posix_getrlimit,system,posix_getsid,posix_getuid,posix_isatty, posix_setegid,posix_seteuid,posix_setgid,posix_times,posix_ttyname,posix_uname,posix_access,posix_get_last_error,posix_mknod, posix_strerror,posix_initgroups,posix_setsidposix_setuid

    From:
    ;include_path = ".:/php/includes"To:
    include_path = "/usr/local/lib/php;/usr/local/apache2/include/php"

    From:
    display_errors = OnTo:
    display_errors = Off

    From:
    display_startup_errors = OnTo:
    display_startup_errors = Off

  17. Run the commands bellow to restart the Apache service:
    /usr/local/apache2/bin/apachectl stop
    /usr/local/apache2/bin/apachectl start
  18. Remove the PHP source and test files:
    rm -rf /tmp/php-5.3.2
    rm -f /tmp/php-5.3.2.tar.gz
    rm -rf /usr/local/apache2/lib/php/test
    rm -rf /usr/local/lib/php/test
  19. Uninstall the following RPM:
    rpm -e libxml2-devel-2.6.26-2.1.2.8
    rpm -e gcc-4.1.2-46.el5
    rpm -e libgomp-4.4.0-6.el5
    rpm -e gmp-4.1.4-10.el5
    rpm -e glibc-devel-2.5-42
    rpm -e glibc-headers-2.5-42
    rpm -e kernel-headers-2.6.18-164.el5

Hardening guide for MySQL 5.1.47 on RedHat 5.4 (64bit edition)

  1. Login to the server using Root account.
  2. Create a new account:
    groupadd mysql
    useradd -d /dev/null -g mysql -s /bin/false mysql
  3. Download MySQL server and client RPM from:
    http://download.softagency.net/MySQL/Downloads/MySQL-5.1/
  4. Copy the MySQL 5.1.47 source files using PSCP (or SCP) into /tmp
  5. Move to /tmp
    cd /tmp
  6. Install the MySQL packages:
    rpm -ivh MySQL-server-community-5.1.47-1.rhel5.x86_64.rpm
    rpm -ivh MySQL-client-community-5.1.47-1.rhel5.x86_64.rpm
  7. Delete the MySQL source files:
    rm -f /tmp/MySQL-server-community-5.1.47-1.rhel5.x86_64.rpm
    rm -f /tmp/MySQL-client-community-5.1.47-1.rhel5.x86_64.rpm
  8. Run the commands bellow to set ownership and permissions:
    chown -R root /usr/bin/mysql*
    chown -R mysql:root /var/lib/mysql
    chmod -R go-rwx /var/lib/mysql
    mkdir -p /var/log/mysql
    chown -R mysql:root /var/log/mysql
  9. Run the command bellow to copy the main configuration file:
    cp /usr/share/mysql/my-medium.cnf /etc/my.cnf
  10. Run the commands bellow to remove default folder:
    rm -rf /var/lib/mysql/test
    rm -f /usr/share/mysql/*.cnf
  11. Run the command bellow to set ownership and permissions for my.cnf file:
    chown root /etc/my.cnf
    chmod 644 /etc/my.cnf
  12. Edit using VI, the file /etc/my.cnf
    Add the strings bellow under the [mysqld] section
    pid-file = /var/lib/mysql/mysqld.pid
    log = /var/log/mysql/mysql.log
    bind-address = 127.0.0.1
    Add the section bellow:
    [safe_mysqld]
    err-log = /var/log/mysql/mysql.err
  13. Run the command bellow to restart the target server:
    reboot
  14. Login to the server using Root account.
  15. Run the commands bellow to set password for the MySQL root user:
    /usr/bin/mysqladmin -u root password 'new-password'
    /usr/bin/mysqladmin -u root -h hostname password 'new-password'
    Note 1: Specify complex password (at least 14 characters) and document it.
    Note 2: Replace “hostname” with the server FQDN (DNS name)
  16. Run the command bellow to login to the MySQL:
    /usr/bin/mysql -uroot -pnew-password
    Note: Replace the string “new-password” with the actual password for the root account.
  17. Run the following commands from the MySQL prompt:
    use mysql;
    DELETE FROM mysql.user WHERE user = '';
    DELETE FROM mysql.user WHERE user = 'root' AND host = '%';
    DELETE FROM mysql.user WHERE User='root' AND Host!='localhost';
    DROP DATABASE test;
    DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%';
    FLUSH PRIVILEGES;
    quit
  18. Run the command bellow to stop the MySQL service:
    /etc/init.d/mysql stop
  19. Run the command bellow to start the MySQL service:
    /etc/init.d/mysql start