This Week in SEO w/ Rick Cable for Week Ending 10/25/2019

There is a lot going in SEO this week.

Barry Schwartz over at Searh Engine Roundtable is discussing a Google search engine algorithm update on Wednesday, October 24th

On my Free Classifieds website, FinditClassifieds.com, I did see a slight increase in organic traffic from Google after the 10/24/2019 update initially. I had new JSON-LD code I’ll be discussing later in the article that was generating a HTTP 500 sever errors which caused Google to pause displaying pages from the domain for both organic search results as well Google Ads (CPC) at the exact same time. Hopefully, this is only temporary and our organic search results momentum can be picked up where we left off.

This suggests that both the Organic Search Results side and Paid Advertising CPC Google Ads seem to use the Googlebot HTTP 500 server error results as a flag for a domain and or sub-domains and reduce traffic to them.

I looked around and found this information packed article that includes information on how Google Search uses Googlebot 500 error results to remove problem pages or domains as soon as issues are detected.

MY FIRST JSON-LD IMPLEMENTATION W/ LESSONS LEARNED

A Background Video on JSON-LD

You would implement JSON-LD to make sure Googlebot in this case can pick up on product details such as the product name, description and price. JSON-LD helps provides context to information Googlebot spiders on your site.

My implementation of JSON-LD was done on the local classifieds page. This JSON-LD example was a list of items for sale in a classified ads page for the Modesto, California metro area.

JSON-LD Code Example / Server Side Code Generates the Script Block

The system I’m patching to add the JSON-LD is running on Classic ASP which is probably closer to PHP or C# Razor Syntax. The language and or framework matter not that much, its the idea / solution.

This example is mix of front end JavaScript and ASP VBScript taking care of the looping thru the recordset to get the values needed to fill in the JSON-LD values.

To me, JSON is a fairly simple concept of transporting data in a simple key/value pair format.

The trickiest part I found about constructing a well structured and acceptable JSON-LD message is the nesting syntax when outputting multiple records at a time and and making sure that we don’t have duplicate values in the key/value pairs.

In my case, I had to construct the JSON-LD block inside a server side code block where we are looping through a recordset and outputting the fields related to the JSON-LD from the local classifieds ad table.

Notice how I’ve got @context and @type outside the loop as these fields and values will be the same for each record. 

So output all your values that are the same for every record then nest the rest of the output in a block inside it using [ ] and { } as seen in the example below. Feel free to checkout the output from the live site anytime. :-).

http://modesto.finditclassifieds.com/misc-classifieds/local-search.asp

<script type="application/ld+json">
	"@context" : "http://schema.org",
	"@type" : "Product" [
<% While NOT Recordset1.eof	%>
<% if InStr(Recordset1("Category"),"service") = 0 then %>
		{
	"@name" : "<%=Replace(Mid(Recordset1("ItemDescription"),1,40),vbCrLf,"") & " in " & Recordset1("City") & ", " & Recordset1("State")%>",
	"decription" : "<%=Replace(Replace(Mid(Recordset1("AdText"),1,120), vbCrLf, ""),vbTab,"")%>",
	"offers" : {
		"@type": Offer,
		"url": "<%=SiteURL%>/misc-classifieds/listings-detail/adid/<%=Recordset1("ID")%>/description/<%=Server.URLEncode(Replace(Mid(Recordset1("ItemDescription"),1,25),vbCrLf,""))%>",
		"priceCurrency": "USD"
		}
	}
		
	],
	<% 
	end if
	Recordset1.MoveNext
	Wend
	Recordset1.MoveFirst 
	%>
</script>

SEO Videos & Articles of Note for Week Ending 10/25/2019.

Here are the best SEO related videos and articles I could find to share with you this week!

Marie Haynes Search News Podcast – Oct 23rd 2019

Video: SEO This Week Episode 139 – Coding, Links, Mapping

Video: SEO Fight Club Episode 38 – Rank Tracking Problems

Video: Barry Schwartz Interview w/ Eric Enge of Stone Temple Consulting in Boston

3 Low Cost Ideas to Address RDP Brute Force Attacks on Your Windows Web Server

Its late at night, I’m remoted in to my Windows web server. I’m reviewing the event logs and see something suspicious. Audit failures in the Security event logs.

The next 7 hours had me consumed in learning everything I can about “Brute Force RDP Attacks” and try to apply it to my server ASAP.

Before I go any further, I want to reiterate that this a hobby server I run. This is not a server I work on for my day job in a large enterprise environment. Hence the focus on low cost solutions.

First, Remote Desktop Protocol (RDP), is probably one of the most commonly unsecured items on Windows web servers which is also why your server is going to be relentlessly pounded by scanning tools and hackers trying to access your server via RDP, usually via port 3389.

Video: Brute Force Attack with Hydra Hacking Tool

I could just block port 3389 and move on with my life but I personally prefer to access this particular server via RDP to handle administrative tasks. Everything else is done via FTP or telnet.

I run all my hobby servers on a super tight budget. This article will discuss what I learned and how I applied that knowledge to mitigate some of the risk associated with managing Windows servers exposed to the Wild Wild West (WWW) with RDP connections using techniques that are no cost except for your time to implement.

Low Cost Ideas for Mitigating RDP Brute Force Attacks on Your Windows Servers

  1. Use Strong Passwords
    • Strong passwords are your first and best defense for any RDP brute force attack.
      • Use a password with a length or 12 character or more.
      • Don’t use words that can be found in a dictionary
      • Use a combination of UPPER CASE, lower case, numbers and special characters
      • Be Social Media aware! Don’t use friends, family, pets or info that could be derived from Social Media posts.
  2. Clean Up Old User Accounts
    • Make sure only the accounts you need are on your server.
    • Fewer accounts reduces possible attack vectors.
    • Also validate the level of access of the accounts on your server.
  3. Update Windows Firewall Rules
    • Exclude IP Ranges for Countries with highest amount of hacking.
    • See steps below for updating your Windows Firewall configuration to block IP ranges for China, Russia and North Korea.

Before You Mess with Your Firewall

The PowerShell script I cover below worked great but then decided to build a firewall rule manually for South American IP addresses and re-learned a very important lesson about working with Firewalls.

A word of caution: Don’t build your Firewall IP restrictions manually.

Always script them out in PowerShell. If you’re not 100% awake and paying attention, you will find yourself blocked out of your server and kicking yourself in the ass like I did.

Thankfully, I have a great hosting company, AccuWebHosting, who has been able to un-do all my screw ups so far. I’ve used them happily for many years and highly recommend them. I pay about $500 a year for a decent Windows server VPS with great support.

Use Windows Firewall to Block IP Ranges for China, Russia and North Korea and many others.

The steps to block IP ranges using Windows Firewall are pretty simple.

  1. Create a directory for working with PowerShell and PowerShell Scripts.
    • Example: C:\ip-security
  2. Go to this page click on Step 2 link to download your PowerShell scripts zip file.
  3. Extract contents of the the ip-security-package.zip file to your “C:\ip-security” folder.
    • You folder should look like this:
  4. Open PowerShell from the Command Line as an Administrator so you’ll have the correct rights to make changes to the Windows Firewall
  5. Run this command to make sure PowerShell is in the right mode
    • “Set-ExecutionPolicy Bypass”
    • Type “Y” when prompted to access the change
  6. Type the following commands to import the IP Range Exclusions in to Windows Firewall.
    • Import-Firewall-Blocklist.ps1 -inputfile china.zone.txt
    • Import-Firewall-Blocklist.ps1 -inputfile russia.zone.txt
    • Import-Firewall-Blocklist.ps1 -inputfile northkorea.txt
  7. You should now have IP blocks in your firewall.

If you’ve done these three things, your web server is better prepared than most.

Some Closing Thoughts on Web Server Security

Security on the internet is hard and ever changing. Running your own server for your hobby or side hustle can be done but can be very frustrating and overwhelming at times. Do as much of what I covered as you can.

We covered a few options above, but if you get nothing else from this article, make sure your passwords are long and hard to guess as this is the last defense before a bad guy gets access to your system.

From meetings I’ve been in with Enterprise engineers, passwords of 12 characters or more are best. Rainbow hash attacks can typically get most common passwords less than 12 characters. Scary, right?

Don’t use passwords made from words that can be found in a dictionary and now with the new world of social media, avoid using your kids, significant other or pet’s name or other references that can be guessed from online posts.

In one of the attacks that prompted me to write this article, one attacker used my youngest Son’s full name. I don’t use Facebook anymore so there only a few places you could go to figure that out.

I hope this story helps someone else on their IT Journey.

Regards,
Rick Cable
Lost in the Cyber Abyss

References:

https://www.gregsitservices.com/blog/2016/02/blocking-unwanted-countries-with-windows-firewall/

http://www.ipdeny.com/ipblocks/

https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.security/set-executionpolicy?view=powershell-6

C# Generics: Digesting Tim Corey’s C# Generics Video

C# Generics: Digesting Tim Corey’s C# Generics Video

Tonight, I’m completing a learning session on C# Generics. I’m using Tim Corey’s YouTube video on C# Generics as my tutorial.

You can get all the files to go along with Tim Corey’s C# Generics video at Time’s web site for the cost of providing Tim with your email address for his email list. You can unsubscribe anytime.

Below is Corey’s Video. Watch it, then if you’re still interested. My personal training notes will be shared below. It might help you if you’re feeling stuck or want to cement an idea in your own mind.

Tim Corey’s C# Generics Video

How to Get Started Programming in Python / Python Crash Course

Crash Course in to Python Programming

I had really been wanting to find a couple of hours to do a crash course on python and finally found an opportunity to do it last night.

Having been a programmer for a while, I’m finding many of the Python videos quite boring as they are for absolute beginners which has you plodding through the basics of programming which makes learning a new programming language painfully slow.

Luckily, I had found this great Python primer video by Derek Banas on YouTube.

I followed along and completed all the code in the video and had working examples of most of the important code snippets for much of how stuff gets done in Python.  Success was not without some pain, see problems and  resolutions below.

Video: Learn Python in One Video

I will save you some pain by telling you there is a very frustrating code issue at the end of this long video.

See code fix below.

When you are in the Dog class referencing the Animal super class from which it inherits the name, weight, height and sound, properties or values you have to use the setter and getter class methods instead of the object “self” reference like we could in the Animal object.  Once you change that, the code works.

For the Dog class, the toString() method only worked for me the example below:

def toString(self):
        return "{} is {} cm tall and {} kilograms, says {} and owner is {}".format(
                                                                    self.get_name(),
                                                                    self.get_height(),
                                                                    self.get_weight(),
                                                                    self.get_sound(),
                                                                    self.__owner)
...instead of:
(this doesn't)
def toString(self):
        return "{} is {} cm tall and {} kilograms, says {} and owner is {}".format(
                                                                    self.__name,
                                                                    self.__height,
                                                                    self.__weight,
                                                                    self.__sound,
                                                                    self.__owner)

As a bonus I would add watching this video to help solidify the idea of polymorphism if you’re having difficulty getting a grasp of it.

Hope this helps someone!

Video: What is Polymorphism?

Rick’s Picks: Top 5 Software Developer Podcasts

About 3 years ago I took on a challenging role as a developer at a start-up that had me doing a 3-4 hour daily commute, 5 days a week.

I’m working from home a lot more now but I did this grueling commute for at least 2 years. I still commute now, just less frequently. I learned to fill my time with lots of technical information mainly podcasts.

It took a while to nail it down, but felt I got the most out of filling my drive time with software development podcasts when I made my self research virtually every unfamiliar term or concept I would hear on the podcasts. Initially, it was exhausting but slowly over time, I was looking things up less and less and impostor syndrome visited less and less. 🙂

Here is a list of the top 5 software development podcasts that I found helpful in my journey as a web / software developer.

Have a favorite developer podcast you didn’t see on my list? Drop me a line or leave a comment with your favorite.

Callback Functions in Javascript – Explained!

I’m working on a project and the topic of Javascript callback functions came up. I’m sure I’ve come upon this before in the past but never spent a lot of time on thinking deeply about it.

I’ve seen a lot of video and blogs about Javascript callback functions but most say it is hard to explain.

I’ve just spent 2 hours digging in and here is the easiest way I can explain them to anyone.

A Javascript callback function is just a placeholder that we can use when we want to be able to pass a function in to another function, then it acts as the function itself once we inject it in to the other function where we can substitute callback “in our minds” with the name of the function we passed in the code logic.

I will be back soon to elaborate and provide you with examples.

-Regards Rick

Here are some good references I’m looking at now.
http://recurial.com/programming/understanding-callback-functions-in-javascript/

Video:

Google reCAPTCHA Privacy and Terms of Service links not Working in Internet Explorer 11 (Explained)

I’m sharing this story as it is something you might encounter when using Internet Explorer 11 with Google’s CAPTCHA service (code). 

This came up in UAT testing recently for a web product I work on so I thought I would share.  It might save you some time explaining to your customers about cross browser compatibility testing.

First off, Google has a free service for trying to detect bots on your site called “CAPTCHA”. CAPTCHA is an acronym for “Completely Automated Public Turing Test to tell Computer and Humans Apart”.

Google’s free CAPTCHA service called reCAPTCHA requires developers to register your website to get an API key which you will use along with some code to call the API from your site.  Pretty cool stuff, right?

I’m really simplifying this but to render the reCAPTCHA you would insert their code snippet. Make sure the code is loading from a a page using the HTTPS protocol or else it might not work.

<html>
  <head>
    <title>reCAPTCHA demo: Simple page</title>
     <script src="https://www.google.com/recaptcha/api.js" async defer></script>
  </head>
  <body>
    <form action="?" method="POST">
      <div class="g-recaptcha" data-sitekey="your_site_key"></div>
      <br/>
      <input type="submit" value="Submit">
    </form>
  </body>
</html>

Once the reCAPTCHA is loading on the page, it will be loading its contents in an IFRAMEThis is really important to our story!

There are links in the Google CAPTCHA that point to a privacy page and terms of service page on the Google.com domain which both have a “target =_blank” attribute on the link. This means these links should open in new windows or tab depending on other pressed keys.

The links are working just fine in Chrome and Firefox and opening in new windows but not IE 11.

What is the issue here?

It could have been earlier than IE 11 but, Microsoft implemented a security feature to restrict links loading in IFRAMES from linking out to a domain other than the one it originally loaded from.

The CAPTCHA code is loading from your WhatEverDomain.com but all the links in the IFRAME are pointing to the Google.com domain are now all disabled.

References:

https://github.com/google/recaptcha/issues/191

https://answers.microsoft.com/en-us/ie/forum/ie11-iewindows_10/links-that-open-in-new-browser-tabs-dont-work-on/55e7b147-bb66-4b4a-b88d-3533166a059a

Here is a video on how to install Google reCAPTCHA for your website. Good luck and happy coding!

Video: Google reCapthca 2.0

Apache Web Server: Blocking Countries By IP Range using .htaccess

Blocking Countries by IP Address on Your Apache Web Server

Before I show you how, the more important item to address is how do we know what IP addresses go to a specific country or region?

There are web sites like CountryIPblocks.net that help you create .htaccess entries for blocking countries and regions by IP address ranges.

Screenshot below show me building a deny list for Asia for example.

Copy the IP ranges to your .htaccess file, save then reset the Apache server service.

>service apache2 restart

Welcome to the New World of Cyber Warfare

Below is a screenshot from CountryIPblocks.net providing a list of IPs to block Iranian web traffic. If a threat actor is actively engaged in sneaky sneaky bad stuff then using this site will help you identify IP ranges to block.

WordPress Security: How to Fix xmlrpc.php Attacks

Today marks my first week of owning a WordPress blog.

I figured a week should be ample enough time to have the web server run and let the bad guys and bots take a swing at it. A review of my Apache web server log should show me what type of WordPress hacks would be attempted first.

My site is really new so I don’ t expect a lot of traffic. I downloaded my Apache web server log and noticed that apparently I had a lot of traffic for a brand new site that had not yet been promoted.

Once I downloaded and looked through the web server log file, a pattern quickly appeared. Lots of requests for a specific file called xmlrpc.php.

What the hell is xmlrpc.php?

I had found this in depth article about the xmlrpc file. For a more in-depth dive please check it out.

https://www.hostinger.com/tutorials/xmlrpc-wordpress

The super short version is, that XML-RPC is a WordPress feature enabling transmission of XML messages between systems using HTTP as the transport mechanism.

WordPress being an open system, occasionally needs to communicate with other systems, xmlrpc.php is supposed to handle that job.

My understanding is that xmlrpc.php is being deprecated in future versions of WordPress so why leave an artifact that can be used to enable a brute force attack on your site. Get rid of it ASAP!

Block Access to the xmlrpc.php file using Apache’s .htaccess file

.htaccess files are used by Apache web servers to allow or deny access to resources on your web site. We can allow or deny based on things like IP addresses or file names.

Your WordPress installation on Apache has a .htaccess file included by default.

You won’t see it using the >ls command as files beginning with a dot are hidden files. You can’t see it in the directory but we can open it.

In the screenshot below, I’ve opened the default WordPress .htaccess file using the nano text editor after connecting via SSH using PuTTY.

Setting an Access Restriction to the xmlrpc.php file using .htaccess file

Blocking access to the xmlrpc.php file to all users can be done using an entry in the .htaccess file that the Apache web server uses to grant or deny access to web resources.

When a request comes in to the Apache web server for the xmlrpc.php file, the server will apply this access rule which states that only local request will be granted and all others will be denied.

Navigate to your WordPress root folder. Mine was in: /var/www/html

I opened the .htaccess file by entering the command >sudo nano .htaccess

In the screenshot below, you see the special entry for <Files xmlrpc.php>.

.htaccess code for Denying Access to xmlprc.php

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

One More Thing: Check Your Apache Config AllowOverride Setting

Of course I did not realize for 24 hours that my .htaccess settings were not actually working. There was one more thing we had to configure on the Apache web server.

Double check your Apache2.conf file to see if the AllowOverride setting is set to All for you WordPress public html directory. Mine was in the /var/www directory.

My AllowOverride setting was set to None by default as you can see the /srv/ is still set to None. Your installation maybe different.

SEO: Google Sitemaps not Worth the Effort

In his Oct 2, 2019 blog article, SEO Round Table’s Gary Schwartz has reported that Google’s John Mueller posted on Reddit that he agrees, that HTML sitemaps are not worthwhile for SEO purposes.

See Gary’s article here: https://www.seroundtable.com/google-html-sitemaps-seo-28312.html

I’ve been in SEO for as long as SEO has existed and I’ll agree with John Mueller on this issue.

In my opinion, web site developers should be more focused on simplification of their site’s navigation. If it is simple, it is good for people and for search engine bots.

I’ve spent time and money in the past creating very large site maps using tools like Screaming Frog software to index and create sitemaps of my site. Screaming Frog’s prices eventually increased too much over a couple of years so I stopped using them and briefly considered writing my own tools to do the same thing.

In the end, I used my time to focus on design improvement including a major simplification in the U/I which dramatically reduced the amount of links per page making it easier for people to navigate as well as Google, Bing and Yahoo search engine bots.

Don’t waste your time with sitemaps, use your time more wisely on design improvements.