Let’s Encrypt: certbot error “No vhost exists with servername or alias of”

It’s about time–or rather, years past time–I enabled HTTPS for this site. I decided to try Let’s Encrypt. It wasn’t as turnkey as I expected, so I’ve included some notes here in case anyone else has similar issues.

The Let’s Encrypt site suggested installing Certbot and included specific instructions for using Certbot with Apache on CentOS 7. It suggested that a single command might do the trick:

$ sudo certbot --apache

Unfortunately, I received a couple error messages and it was ultimately able to create the certificate for me, but unable to update my Apache configuration. An excerpt of the output of the certbot command is below:

Saving debug log to /var/log/letsencrypt/letsencrypt.log
No names were found in your configuration files. Please enter in your domain
name(s) (comma and/or space separated) (Enter 'c' to cancel):osric.com,www.osric.com
...
No vhost exists with servername or alias of: osric.com (or it's in a file with multiple vhosts, which Certbot can't parse yet). No vhost was selected. Please specify ServerName or ServerAlias in the Apache config, or split vhosts into separate files.
Falling back to default vhost *:443...
No vhost exists with servername or alias of: www.osric.com (or it's in a file with multiple vhosts, which Certbot can't parse yet). No vhost was selected. Please specify ServerName or ServerAlias in the Apache config, or split vhosts into separate files.
Falling back to default vhost *:443...
...
No vhost selected

IMPORTANT NOTES:
- Unable to install the certificate
...

I’m guessing it’s because my Apache virtual host configuration is in /etc/httpd/conf/vhosts/chris/osric.com instead of the expected location.

I looked at the certbot documentation hoping to find a way I could pass the certbot command the path to my virtual host configuration file. I did not find an option to do that. The logs at /var/log/letsencrypt/letsencrypt.log are fairly verbose, but it still does not indicate what files or directories it looked at to attempt to find my Apache configuration.

I noted that /etc/letsencrypt/options-ssl-apache.conf contains Apache directives. I thought maybe I could just include it in my config file using Apache’s Include directive, e.g.:

Include /etc/letsencrypt/options-ssl-apache.conf

I restarted Apache using systemctl (I know, I should be using apachectl restart instead):

$ sudo systemctl restart httpd
Job for httpd.service failed because the control process exited with error code. See "systemctl status httpd.service" and "journalctl -xe" for details.

Two problems there. One, options-ssl-apache.conf appears to be a generic file with no data specific to the host or cert. Additionally, I had just added it to a VirtualHost directive listening on port 80.

I duplicated the VirtualHost directive in my config file at /etc/httpd/conf/vhosts/chris/osric.com and made a few modifications and additions:

<IfModule mod_ssl.c>
<VirtualHost 216.154.220.53:443>
...all the directives from the port 80 VirtualHost...
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/osric.com/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/osric.com/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/osric.com/chain.pem
</VirtualHost>
</IfModule>

I restarted Apache:

$ sudo apachectl restart

The server restarted, but still did not respond to HTTPS requests. It didn’t appear to be listening on 443:

$ curl https://www.osric.com
curl: (7) Failed connect to www.osric.com:443; Connection refused

As a sanity check, I confirmed that mod_ssl was indeed installed:

$ yum list mod_ssl
Installed Packages
mod_ssl.x86_64 1:2.4.6-45.el7.centos @base

And I checked to confirm that Apache was loading mod_ssl:

$ cat /etc/httpd/conf.modules.d/00-ssl.conf
LoadModule ssl_module modules/mod_ssl.so

I looked at some other Apache configurations where I knew SSL was working and I noted the Listen directive:

Listen 443

I added that line to the top of my configuration file at /etc/httpd/conf/vhosts/chris/osric.com, above the VirtualHost directive. I restarted Apache and it worked!

Browser metadata phishing?

I was checking my Google Analytics stats and noticed a strange entry in the Languages section of the demographics. Ranking fifth, after en-us, en-gb, en-ca, and en-au was the following:

Secret.ɢoogle.com You are invited! Enter only with this ticket URL. Copy it. Vote for Trump!

Do not visit that URL, by the way. You can see that the first “G” in “Google” is an unusual character — it’s the symbol for a voiced uvular stop.

I usually use urlQuery to check out potentially malicious sites, but it didn’t like this URL. I used vURL Online instead, which reported it was malicious:

This domain is listed in the Malware Domain List. Website’s [sic] in this database should be viewed with extreme caution.

These 1500 or so sessions on my site are presumably from some hijacked browser or malicious plug-in/extension, and the end-user has no idea they are sending this bizarre language string in the HTTP headers.

Why put a malicious URL there at all? Did the creator hope that those of us perusing our web stats would be intrigued enough to fall for this trap? Even as I ask that question, I know that some percentage of users must have done just that. I assume they are now broadcasting their language as the same unusual string.

As a site owner, is there anything I should do? I could detect this string and notify the user. E.g. use an Apache re-write rule to redirect the user to a page telling them their browser is infected? This is only a partially rhetorical question. If you have suggestions, let me know.

Block an IP address via iptables

I was monitoring the mail logs on a Postfix server and noted repeated failed connection attempts from the same IP address. The source was likely up to no good, and it was making it more difficult to monitor the logs for legitimate connections, so I decided to block it:

iptables -A INPUT -s 123.456.789.101 -j DROP

(IP address changed to protect…the innocent?)

However, the IP address was still making connections:
Dec 2 17:19:05 mercutio postfix/smtpd[15230]: connect from unknown[123.456.789.101]
Dec 2 17:19:06 mercutio postfix/smtpd[15230]: lost connection after AUTH from unknown[123.456.789.101]
Dec 2 17:19:06 mercutio postfix/smtpd[15230]: disconnect from unknown[123.456.789.101]

How is that possible? First I checked iptables to check my sanity and confirm that the rule had been added:

# iptables -L
...
DROP all -- 123.456.789.101 anywhere
...

OK, it’s there. That’s good!

The problem in this case was a different rule that had been added previously. Rules in iptables are processed in order, and no further rules are processed after a matching rule is found. Well above my newly-added rule was this rule:
ACCEPT tcp -- anywhere anywhere state NEW tcp dpt:smtp

That rule makes sense for a mail server, but I needed my rule to be inserted before it. I determined which rule it was in the INPUT chain like this:
iptables --line-numbers -L INPUT

It was the 5th rule, so I was able to insert the new rule just above it like this:
iptables -I INPUT 4 -s 123.456.789.101 -j DROP

After that, the offending IP address stopped creating entries in the mail.log.

However, my new rule would disappear after a system restart. Since I am using iptables-persistent, I saved the rules to the config file:
iptables-save > /etc/iptables/rules.v4

To confirm everything worked, I attempted to restart iptables:
# service iptables-persistent restart
Failed to restart iptables-persistent.service: Unit iptables-persistent.service

Apparently the service name changed to netfilter-persistent in Debian 8. The config files are still in the same location, but the service name has changed.

I restarted iptables:
# service netfilter-persistent restart

I checked the rules again and my new rule was there, above the rule allowing connections from any IP on port 25. However, I also noticed the following rule above either of those:
ACCEPT all -- anywhere anywhere

I freaked out. That rule indicates that all traffic from any source on any port should be accepted. That’s the worst firewall rule I’ve ever seen. It basically negates the entire concept of a firewall. It clearly should not be there!

However, using the verbose switch on iptables:
iptables -vL INPUT

I discovered that the rule only applied to the lo interface (loopback). That’s a relief–that rule gets to stay.

Social Engineering through Surveys

I received an invitation to a survey today. I was selected as an alumnus of the University of Michigan, an enormous university. The e-mail implies that the survey is possibly on behalf of the university. It includes the well-recognized “Block M” logo.

However:

  • The “From” address is alumnisurvey@lrwonlinesurvey.com.
  • Links to unsubscribe go to click.skem1.com.
  • The survey itself is at survey.bz.

It all looks pretty fishy/phishy.

Nowhere are there any links to umich.edu.

Also, I happen to know that the University of Michigan tends to use Qualtrics for surveys. Why wouldn’t the university send out a Qualtrics survey from a umich.edu e-mail address with umich.edu unsubscribe links instead of a survey.bz survey from a lrwonlinesurvey.com address with click.skem1.com unsubscribe links?

The survey is likely legitimate. The alumni department probably contracted with a research firm, that research firm probably uses a third-party survey software, and they probably use a different third-party service to handle mailing lists.

But I will not be filling out such a survey. You shouldn’t either. And, if you’re in the business of creating surveys or hiring companies to create surveys, you should think about these factors. Why create something that looks this suspicious?

I’ve always said that survey results automatically exclude those who don’t have time to waste on surveys (this one suggested it would take 18 minutes to complete!), but now it seems they also exclude anyone with a mind for security and privacy.

ColdFusion session fixation and jsessionid

A web application is vulnerable to a session fixation attack if an unauthenticated user’s session ID does not change after authentication. A malicious user could start an unauthenticated session and give the associated session ID to the victim. Once the victim authenticates, the malicious user now shares that authenticated session.

ColdFusion introduced SessionRotate in CF10 to mitigate such attacks. However, it only applies to CFID and CFTOKEN (ColdFusion sessions). If you are using J2EE sessions, there is no SessionRotate. This is unfortunate, as the ColdFusion documentation has stated for years that J2EE sessions have advantages over ColdFusion sessions (see Configuring and using session variables), the foremost being that J2EE sessions are not persistent. It’s also unfortunate, because this is an important security-related tag that only works under certain server configurations–and fails silently under others!

As a side note, J2EE has been called JEE (Java Enterprise Edition) since Java 1.4. The ColdFusion administrator continues to refer to it as J2EE, but you are likely to see references to JEE in reference material online.

Session rotation basically consists of:

  • Deleting the user’s current session
  • Creating a new session containing the same data, but with a different ID

Jason Dean at 12robots.com wrote about mitigating session fixation on ColdFusion in Session token rotation REVISITED and other articles. His posts were helpful in explaining the issue and offering a solution for rotating ColdFusion sessions on pre-CF10 systems. However, he posted no solution for JEE sessions.

But according to the CF documentation on Ending a session: You cannot destroy the session and create a session on the same request, as creating a new session involves sending session cookies back.

That’s problematic. Once a user authenticates, we can destroy the user’s session. But how do we create the new, authenticated session?

An answer posted in response to ColdFusion Session Fixation on StackOverflow suggests the solution is to store necessary data in a secure way and pass the data, or a token associated with that data, on to a new HTTP request. I considered, for example, generating a UUID as a nonce and storing it in a database along with the username and a near-future timestamp. The user would then be directed to a URL with the nonce appended as a token, which could be validated against the database to authenticate the user.

Fortunately, a simpler solution exists. Pete Freitag posted SessionRotate solution for JEE Sessions in March, 2014. By accessing properties of the Java servlet session running under ColdFusion, his methods perform the following steps:

  • Copy the session scope into a temporary variable
  • Remove the ID and URL tokens from the temporary variable
  • Invalidate the existing session
  • Create a new session
  • Copy the attributes of the temporary variable into the new session

The final step is somewhat more complicated, as the new session is apparently not immediately available, and copying the attributes happens in the Application.cfc’s OnSessionStart. Still, it can happen in a single request! The JEE documentation on Creating and Managing User Sessions has more information about the underlying JEE sessions.

When I implemented Pete Freitag’s solution, I made the following modifications:

  • I created a jeeSession.cfc containing:
    1. rotate (originally named jeeSessionRotate)
    2. copy (containing most of onSessionStart)
  • I created jeeSecureApp.cfc containing:
    1. onSessionStart
    2. an instance of jeeSession.cfc

I can modify the cfcomponent tag in the Application.cfc of any app to include:
extends="jeeSecureApp"

Then jeeSession.rotate() is available.

Caveats:

  • If your application already extends a CFC, you’d have to adjust this approach.
  • If your application already defines an onSessionStart, you’d want to add a call to super.onSessionStart

SQL Injection Goes Mainstream

Note to the web development world: even a mainstream media source like Time Magazine knows about SQL injection. Don’t you think it’s time you protected your web applications against it?

Last week’s issue of Time featured an article that focused on LulzSec‘s activities. In Hack Attack, author Bill Saporito went a step beyond most journalists covering web security by mentioning an actual technique: SQL injection.

SQL injection is a subclass of injection attacks, wherein a malicious user manipulates input so as to insert (or inject) a tag-along command into the application code. It’s #1 on OWASP’s Top Ten Vulnerabilities for 2010, in part because such vulnerabilities are:

  • Common
  • Easy to exploit
  • Have a huge payoff (i.e. devastating impact)

Because it is so common and easy-to-exploit, there are a lot of automated tools that malicious users (often by way of compromised machines) use to scan sites and test them for vulnerabilities. If a vulnerability is found, the application may be targeted for further attacks. Basically, attackers are on the lookout for low-hanging fruit in the same way that thieves look for valuables sitting in plain sight in a parked car. Don’t take the car analogy too far, though: if someone breaks into your car, there will be broken glass and your iPod will be gone. If someone exploits a SQL injection vulnerability on your site, they may have all your user data (and more), with hardly a trace: entries in your access logs and error logs, which are too-often completely ignored.

As the joke goes, you don’t have to outrun the bear to avoid being mauled and eaten–you just have to outrun the other guy. One of the best ways to make sure your web application is not targeted for further attacks is to make sure the relatively simple SQL injection scanners don’t find any vulnerabilities.

SQL injection is fairly simple to defend against using parameterized input, and your development language of choice should have documentation on how to do this. OWASP also offers a SQL Injection Prevention Cheat Sheet. There are also automated tools to you can use to check your code for SQL injection flaws (such as QueryParam Scanner for ColdFusion), or test your site for vulnerabilities–also known as penetration testing or pen testing–such as the (currently out-of-date) SQL Inject Me add-on for Firefox.

Checking your web applications for SQL injection vulnerabilities is the first thing you should do, but it is hardly the last. Although fending off automated SQL injection attempts is definitely a good thing, there are many other categories of vulnerabilities, and a determined attacker will find them. Stay informed, and make sure you know what attackers are up to before you read about it in Time.

Why I’m Not Friends with My Bank on Facebook

I received a request today from my financial institution asking me to follow them on Facebook, Twitter, Flickr, and YouTube.

Aside from the fact that I doubt that their updates on these various services will enrich my life, there is another very good reason not to follow them:

Security.

It’s easy to trace your connections online. Most of this information, for most users, is public. If you follow Bank A, it stands to reason that you have an account at Bank A–something a malicious person would not have known before. Even if your online persona isn’t directly connected to your name, you might be surprised at how easy it is to connect the two with a Google search.

(That last item says a lot, I think.)

Any bank that suggests you follow them on social media must be pretty confident of their security! Or, more likely, their marketing teams and their security teams don’t talk to each other.

You wouldn’t stand on a street-corner handing out cards that say, “My name is Bob Billiards and I have an account at Bank A” would you? Then don’t follow your bank on a social media site.

WordPress Security Tips

I attended the WordCamp Birmingham conference this past weekend to find out more about all things WordPress. WordPress is an open source blog engine/lightweight Content Management System (CMS) that has a huge community of users and developers, and an enormous repository of plugins to extend its functionality.

One of the presentations I attended, Mitch Canter‘s session on WordPress Security, had 6 good tips for making your WordPress-based site more secure:
Continue reading WordPress Security Tips

Validating the Referer: Not as Useless as I Thought?

I used to validate the HTTP referer header to verify that users were accessing certain pages from certain other pages. For example, users accessing sampleapp/edit.cfm should be getting there from sampleapp/index.cfm. Anyone accessing sampleapp/edit.cfm without coming from sampleapp/index.cfm was probably monkeying around and should be send back to the index page, or possibly even logged out.

However, it is fairly trivial to modify your referer header, so anyone who wants to monkey around with sampleapp/edit.cfm can make it look like they are coming from sampleapp/index.cfm. (If you’re interested in modifying your HTTP headers, I suggest checking out the Tamper Data Firefox plugin.) The check provides absolutely no assurance that the user is really coming from the page. Therefore, I decided the check was useless.

I’ve been attending a weekly web application security study group with some of my colleagues for the past several weeks, where we’ve been reading and discussing The Web Application Hacker’s Handbook. The past couple sessions have been about cross-site scripting (XSS). Justin Klein Keane brought up a good point at today’s session: checking the referer may not keep a malicious user from altering his or her referer string, but could help identify victims of XSS attacks who were possibly directed to submit malicious data from a third-party site.

Checking the referer isn’t a sufficient protection against malicious users, by any means, but it could still be helpful. What do you think?