Saturday, April 18, 2015

Chase Bank Using Outdated Security

I noticed today that Chrome started showing the “secure, but with minor errors” icon for Chase bank's website.  Taking a closer look, they are using a SHA1 signed certificate:

This is with Chrome 42.  Seems amazing that a major bank like Chase would still be using a SHA1 signed certificate, even though it has been known for a while to not be fully secure.

Thursday, January 29, 2015

phpBB3 MOD for Banning Registrations by Country

Our Fund Manager forum was getting spammy posts, despite a well written Q&A question designed to prevent spambots from registering.  All the posts were coming from a particular country, so I wanted to block all registrations from that country.  I couldn't find a mod for phpBB3 to do this, so I wrote it myself.  I saw several requests for this same mod, and the common answer was to write a better Q&A question instead.  I was convinced a real person was spamming our board, so no matter how good a question I asked, they would always be able to circumvent that protection.  We also receive very few or zero customers from this country, so I didn't believe it would hamper legitimate users.

As an aside, I found it interesting that often these spammy posts would happen late in the evening, or on a Friday night, like they were trying to get at least a weekend out of it, before an administrator could delete them Monday morning.

I have never published an official MOD before, so I'm just going to describe how to implement these changes manually.  This is not push button like other mods, but with some basic PHP, Perl, and mysql knowledge you should hopefully be able to follow these steps.  There are 2 parts to implementing this mod:

1) Set up a database that allows a lookup from an IP address to a country
2) Modify ucp_register.php to perform this lookup, and country check

1) Set up a database that allows a lookup from an IP address to a country:

Create a new mysql database and then save the following to a file named createtable.sql:

CREATE TABLE `bycountry` (
  `ID` mediumint(8) unsigned NOT NULL auto_increment,
  `min` int(10) unsigned NOT NULL,
  `max` int(11) unsigned NOT NULL,
  `ctry` varchar(2) NOT NULL,
  `country` varchar(255) NOT NULL,
  KEY `minval` (`min`),
  KEY `maxval` (`max`)

You need to know the database username/password that you created in the last step, and have command line access to mysql.  You could also use something like phpMyAdmin.  Somehow you need to create this database and a table with the above format.  For the mysql approach, run this from a command line:

mysql -u username -ppassword dbasename < createtable.sql

Now that the database and table format are created, populate the table with data.  You can download this data in a CSV file (IpToCountry.csv) from:

We will use a Perl script to transfer the data from this downloaded CSV file into our database.  Save the following to


use strict;
use DBI;

my $database_host = "";
my $database_port = 3306;
my $database_username = "username";
my $database_password = "password";
my $db_name = "dbasename";
my $ip_file = 'IpToCountry.csv';

# connect to the database
my $dbh = DBI->connect("dbi:mysql:$db_name:$database_host:$database_port", $database_username, $database_password);
unless ($dbh) {
    print "-E- Could not connect to mySQL database\n";

# remove all the current rows, leaving table structure/definition in tact
my $add_sth = $dbh->prepare("DELETE FROM bycountry");

# re-add new ones
$add_sth = $dbh->prepare("INSERT IGNORE INTO bycountry (min, max, ctry, country) VALUES(?, ?, ?, ?)");

open(FILE, "< $ip_file") || die "Could not open $ip_file";
while (<FILE>) {

# File format is:
# "1346797568","1346801663","ripencc","20010601","IL","ISR","ISRAEL"

    next if (/^#/);
    my ($startip, $endip, $registry, $assigned, $ctry, $cntry, $country) = split('","');
    next if (! defined($country));
    $startip =~ s/^\"//;
    $country =~ s/\"$//;

    $add_sth->execute($startip, $endip, $ctry, $country);

You will need to adjust the relevant items at the top of the script, like the path to your perl, your database info, etc.  Once you have this done, run this script from the command line to fill in your table.  If completed properly, your table should have over 140,000 rows as of the time of this writing.  You can also use this script again to periodically refresh the table with updated data.  Just re-download the IPToCountry.csv file, and then run this script again.

2) Modify ucp_register.php to perform this lookup, and country check

Open up the existing file: <phpbb3_path>\includes\ucp\ucp_register.php in an editor.  Below the section that does the optional DNSBL check we will add our modification.  Search for "DNSBL" and below that "if" block, add this:

// My MOD for banning registrations by country
$mabmod_dbhost = '';
$mabmod_dbusername = 'username'; // read only user
$mabmod_dbuserpassword = 'password';
$mabmod_default_dbname = 'dbasename';

$mabmod_link_id = mysqli_connect($mabmod_dbhost, $mabmod_dbusername, $mabmod_dbuserpassword, $mabmod_default_dbname, 3306);
$error[] = "Connection failed to the host $mabmod_dbhost.";
$mabmod_ips = explode('.', $user->ip);
$mabmod_ipnumber = ($mabmod_ips[3] + $mabmod_ips[2] * 256 + $mabmod_ips[1] * 256 * 256 + $mabmod_ips[0] * 256 * 256 * 256);
$mabmod_query = "SELECT country FROM bycountry WHERE '$mabmod_ipnumber' >= min AND '$mabmod_ipnumber' <= max LIMIT 1";
$mabmod_result = mysqli_query($mabmod_link_id, $mabmod_query);
if(!$mabmod_result) $error[] = mysqli_error($mabmod_link_id);
if(mysqli_num_rows($mabmod_result) > 0)
if(!($mabmod_db_data = mysqli_fetch_array($mabmod_result))) $error[] = "Error fetching data.";
if (preg_match('/Pakistan/i', $mabmod_db_data['country'])) $error[] = "Registrations banned from this country";
// End my MOD

Again you will need to modify the database info at the top, and optionally change the country check to whatever you want to block.  You can add additional lines to block multiple countries if necessary.

To test this mod out, you might add another line for checking your own country, something like:

if (preg_match('/United States/i', $mabmod_db_data['country'])) $error[] = "Testing - Registrations temporarily disabled...";

I hope this proves helpful to others in preventing spammers on your board.

Monday, October 13, 2014

Fix for PrimoPDF opening PDF files with spaces in filename

Today I was using PrimoPDF to print and got an error from Adobe Reader XI:

"There was an error opening this document.  This file cannot be found."

after the PDF file was created and it was attempting to be opened.  (I use the PrimoPDF setting for "Post Process" to "Open PDF".)  At first I thought there was a problem with Adobe Reader XI as this was newly installed, and I had never noticed this problem before with Adobe Reader X.  The PDF file was printed, and did exist, so something else was going wrong.  I was able to open the PDF file manually from Adobe.  Upon further investigation  it appears that PrimoPDF is not passing the path to the PDF file in double quotes to Adobe, so any files with spaces in their names will not open.  The fix is to either not have spaces in your filenames, or I wrote a small batch file to correct this issue.  The batch file is simply:

REM Helper batch file to launch Adobe from PrimoPDF
"C:\Program Files (x86)\Adobe\Reader 11.0\Reader\AcroRd32.exe" "%*"

Just save those 2 lines to a text file, and save it as something like "p2a11.bat".  In your PrimoPDF settings, change it to call this batch file, instead of the Adobe Reader directly.  For example:

Now I am able to print to PDF files with spaces in their names, and have PrimoPDF automatically open them up for me afterwards.

Monday, September 29, 2014

Google "Less Secure Apps" Explained

Google has a security setting in your account for enabling or disabling "Less Secure Apps".  What is a "Less Secure App" exactly doing or not doing to make it less secure?  Google's answer is relatively vague, and mentions "modern security standards".  You can read Google's description here.

Less Secure Apps:

Google considers apps that directly use your account email address and password less secure.  Many older apps request your login details in order to access Google's services on your behalf.  This is not ideal from a security perspective for several reasons:

  1. You must trust that app to not be dishonest.
  2. You are also trusting these apps to adequately protect the password information from being compromised by 3rd parties. For example, storing the password un-encrypted in the registry or a file on your hard drive would leave it open to easily being compromised should someone or some malicious software gain access to your computer.
  3. Finally, you are also giving that app access to all of your Google account's features, including e-mail, contacts, calendar, drive, etc.  If that app only needs to access your contacts, giving it permission to access all your other services opens up permissions more than necessary.
There is a better method for authentication available...

More Secure Apps:

Google supports an improved method to give apps access to your Google services with a protocol called OAuth2.  Using this authentication method allows apps to access only the Google services within your account that they need.  OAuth2 also eliminates the need for the user to provide the app with an account password.  Instead you get an access code, specific to that app, your account, and needed permissions. The details of how you obtain this access code vary depending on the platform of the app.  The basic idea is that the app directs you to a Google website where you log into your Google account and view the permission request from this app.  The permission request lists all the specific services this app will be able to access.  If you approve, you will be given an access code to enter into the app.  (Some apps can accept this access code automatically, behind the scenes, once you approve the request.)

OAuth2 eliminates the need for users to enter their Google account password.  It also solves the issue of only providing permissions to the necessary services, instead of your whole account.  Also, the access code can only be used by the requesting app.  To use the access code the app must also provide a clientID and client secret, which are registered with Google by the app developer.  Therefore, even if the access code were compromised the malicious party couldn't use it unless it knew the clientID and client secret.  If the malicious party had the access code, clientID, and client secret it could use this, but then it would at least be restricted to the services approved.  Access codes can also be easily revoked when desired.

Thursday, September 18, 2014

Case Study: Google Ranking Results During HTTP to HTTPS Transition

I recently decided to transition several websites for my company from HTTP to HTTPS.  My main concern was to not cause any detrimental effects on my ranking in Google's search results.  I used the data available to me in Google Webmaster to monitor the impressions and clicks my sites were getting during this transition. My hope was to not see any drop-off in site traffic.  I transitioned my lowest traffic sites first and watched them to confirm nothing bad happened, before I transitioned my higher traffic sites.  I've plotted the results for 4 sites that I transitioned.

My highest traffic site is, and that was transitioned last, on Sep 4, 2014.  The yellow "Change Date" point graphically shows the date where the site was changed from HTTP to HTTPS. I'm plotting both the "HTTP Impressions", as well as the "HTTPS Impressions", plus the sum of these two as "Combined Impressions".  You can see shortly after the change date, the HTTP impressions drop off quickly, while the HTTPS impressions take over.  Their combined sum stays relatively consistent with impressions before the HTTPS transition.  The "Combined Clicks" are also shown, and you can see these also stay relatively consistent with pre-transition values.

My next highest traffic site is  This site was transitioned on Aug 31, 2014.  Again you can see how quickly the impressions transition from HTTP to HTTPS after the change date.  For some unknown reason there happened to be a spike in impressions shortly after the transition, but the clicks remained relatively consistent with pre-transition values.
The site has less traffic, and was transitioned on Aug 21, 2014.  Looking at the combined impressions and combined clicks the data looks relatively consistent with pre-transition values.  It does look like there might have been a slight drop in impressions after the conversion, but it is hard to say, as there started to be some lower impression counts right before the transition as well.

My lowest traffic site is, and it was also transitioned to HTTPS on August 21, 2014. This site's results also indicate impressions/clicks remained relatively constant through and after the transition.


From examining the impressions and clicks on these 4 sites during the transition from HTTP to HTTPS I have concluded there were no detrimental or positive effects from the transition.  Any slight changes are most likely due to random variations, and not the HTTPS transition.  I'm glad I made the change.

Monday, September 15, 2014

Poor Bank Online Security Practices

You would think of all the businesses that would work hard on getting security correct, banks would be at the top of the list.  As of right now, Bank Of America's homepage has both secure and insecure content. This same page asks the user for their Online ID (not the password though).  How is the average user supposed to know for sure that this Online ID can't be observed by anyone else if all the content is not secure?  Here is a screen shot of Bank Of America's homepage right now as viewed in Chrome:

Measured Power Usage of Various Light Bulbs

Power Measurements:
In our house we have migrated from incandescent to CFLs, and now partly to LEDs.  I was curious to verify if the power consumption of these newer light bulbs was really as good as advertised.  I borrowed a Kill A Watt meter from our local electric company (SRP) through the library.  I measured a variety of different bulbs in a regular lamp (non-dimmable).  Here are the results:

I was pleasantly surprised to see all of the measurements were less than the advertised wattage.  It was also interesting to see that CFLs have the lowest power factor, and on average the LED bulbs had a better power factor.  As expected the incandescent have the best, as they're pretty much just a resistor.  Our electric company meters Watt-Hours, and bills us by the same, so the lower power factor numbers don't really matter to my electric bill.

LED versus CFL:
LEDs have recently come down in price so they are more cost effective.  I've started only buying LEDs for replacements instead of CFLs.  We never had great luck with CFLs.  My biggest complaint was that they didn't last nearly as long as advertised on the package.  The other problem with CFLs is their turn-on delay, and warm-up time.  Lastly the fact that they contain mercury isn't attractive.  The LEDs I've purchased so far have a much better turn-on time, and don't require time to warm up to their full brightness like CFLs do.  They also do not contain any mercury.  The jury is still out on their longevity, but I'm hopeful they will perform better here too.