WordPress Security

Add extra security to stop brute force attacks (logins).

These measures can reduce login attempts dramatically from 400 a day to none. 

Password Protect wp-login.php

Add this to htaccess

# Stop Apache from serving .ht* files
<Files ~ "^\.ht">
  Order allow,deny
  Deny from all
</Files>
# Protect wp-login.php
<Files wp-login.php>
	AuthUserFile /filelocation/.htpasswd
	AuthName "Private access"
	AuthType Basic
	Require valid-user
</Files>

Deny Access to No Referrer Requests

When your readers comment, the wp-comments-post.php file is accessed, does its thing, and creates the post. The user’s browser will send a “referral” line about this.

When a spam-bot comes in, it hits the file directly and usually does not leave a referrer. This allows for some nifty detection and action direct from the server. If you are not familiar with Apache directives, then write the following in your root directory .htaccess file:

# Stop spam attack logins and comments
<IfModule mod_rewrite.c>
	RewriteEngine On
	RewriteCond %{REQUEST_METHOD} POST
	RewriteCond %{REQUEST_URI} .(wp-comments-post|wp-login)\.php*
	RewriteCond %{HTTP_REFERER} !.*domain.com.* [OR]
	RewriteCond %{HTTP_USER_AGENT} ^$
	RewriteRule (.*) http://%{REMOTE_ADDR}/$1 [R=301,L]
</ifModule>

This will:

  1. Detect when a POST is being made
  2. Check to see if the post is on wp-comments-post.php
  3. Check if the referrer is in your domain or if no referrer
  4. Send the spam-bot BACK to its originating server’s IP address.

Disabling Xmlrpc.php

The biggest issues with XML-RPC are the security concerns that arise. The issues aren’t with XML-RPC directly, but instead how the file can be used to enable a brute force attack on your site.

The first is using brute force attacks to gain entry to your site. An attacker will try to access your site using xmlrpc.php by using various username and password combinations. They can effectively use a single command to test hundreds of different passwords. This allows them to bypass security tools that typically detect and block brute force attacks.

The second was taking sites offline through a DDoS attack. Hackers would use the pingback feature in WordPress to send pingbacks to thousands of sites instantaneously. This feature in xmlrpc.php gives hackers a nearly endless supply of IP addresses to distribute a DDoS attack over.

# Block WordPress xmlrpc.php requests
<Files xmlrpc.php>
order deny,allow
deny from all
</Files>

Update domain of WordPress site

If you need a new url to be the primary one for your WordPress site, read on.

Edit the DNS Record of New Domain

Point the new domain by editing the A record for the domain to point to the IP of the server.

Create a New Virtual Host

Copy the original virtual host to create the new one and then edit it:

cp /etc/apache2/sites-available/original.com.conf /etc/apache2/sites-available/new.com.conf
nano /etc/apache2/sites-available/new.com.conf

Just update the domain information part, not the directory it points to.

Enable the new virtual host:

a2ensite new.com.conf

Restart apache2 to see the new domain in effect:

service apache2 restart

When you visit the website now, you’ll be able to visit with both domains. The original domain will show all files and images correctly, while the new domain the site will look a little broken.

Update the Database

You need to update the database to use the new domain for the wp_siteurl, wp_home and all links to files and images. There are two ways to do this.

  1. WP Migrate plugin
    The quickest way to do this is to use the WP Migrate plugin to export the database. The plugin adds a Find and Replace already loaded with the current domain. Add the new domain in the Replace field beside it. You can remove the absolute path to the directory as that’s not changing. Export the database.
  2. Edit SQL file with EditPad Lite
    If you do not have WP Migrate installed, you can download the database and open the sql file with EditPad Lite which is good for opening large files. Do a find and replace with the new domain.

Drop all tables from the live website and then upload your new sql file from WP Migrate or your edited one from EditPad Lite into the database.

Now if you visit the new domain, the images will load correctly. You will also be able to see the original domain which we’ll need to change as only one should be primary.

Redirect to the Primary Domain

Update your htaccess file at the top to redirect all domains to the new domain:

RewriteEngine on
RewriteCond %{HTTP_HOST} !^new\.com$ [NC]
RewriteRule ^(.*)$ https://new.com/$1 [R=301,L]

Now the domain is updated for your WordPress site!

Get WordPress posts from another WordPress website

<?php
$response = wp_remote_get( add_query_arg( array(
		'per_page' => 3
	), 'https://domain.com/wp-json/wp/v2/posts' ) );
	if( !is_wp_error( $response ) && $response['response']['code'] == 200 ) {
		$posts = json_decode( $response['body'] ); // our posts are here
		
		foreach( $posts as $post ) {
			$date = date('F j, Y', strtotime($post->date));
			echo '<div class="blog-post-date">' . $date . '</div>';
			echo '<h3 class="blog-post-title">'. $post->title->rendered . '</h3>';
			echo $post->content->rendered;
			//$output .= print_r( $post );
		}
	}

Add Google Analytics only for customers

<?php
function site_inline_scripts() {
	global $current_user;
	$property_ga4 = "CONTAINER";
	$staging = false;
	if($_SERVER['HTTP_HOST']!="domain.com"){
		$property_ga4 = "CONTAINER2";
		$staging = true;
	}
	if ( !isset( $current_user->roles[0] ) || $current_user->roles[0] == 'customer' || $staging == true) {
		<!-- Google Tag Manager -->
		<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
	new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
	j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
	'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
	})(window,document,'script','dataLayer','<?php echo $property_ga4; ?>');</script>
		<!-- End Google Tag Manager -->
	}
}
add_action('wp_footer', 'site_inline_scripts', 17);

Create Shortcode in WordPress

Create shortcode that can be used in posts or pages like this:

[newshortcode]

Add to functions.php

<?php 
function newshortcode_shortcode() { 
	if(is_admin()) return;
	$post_title = get_the_title();
	ob_start();
	?>
	<?php echo $post_title; ?>
	<div>Some text</div>
	<?php
	$output = ob_get_contents();
	ob_end_clean();
	return $output;
} 
add_shortcode('newshortcode', 'newshortcode_shortcode');
?>

Get attachment image from media library

wp_get_attachment_image function can accept four values as you can see:

wp_get_attachment_image( int $attachment_id, string|array $size = 'thumbnail', bool $icon = false, string|array $attr = '' )

Examples

<?php echo wp_get_attachment_image( get_the_ID(), array('700', '600'), false, array( "class" => "img-fluid" ) ); ?>
<?php echo wp_get_attachment_image( 5151, 'medium', false, array( "class" => "img-fluid" ) ); ?>