Securing Ghost Blog Authentication with Cloudflare's ZeroTrust Access Policy

Securing Ghost Blog Authentication with Cloudflare's ZeroTrust Access Policy

How to implement MFA in Ghost Blog with Cloudflare's Zerotrust Access Policy.

But first a short rant about why I'm posting this here, and not on forum.ghost.org

Account suspended: no constructive purpose to their actions other than creating dissent within the community

That's what I see when I try to login to http://forum.ghost.org

I initially wrote a slightly sarcastic post citing that the only mention of secure authentication mechanics was a collection of threads that where all left wanting from just a few years back (2018 the earliers ) when asking in general, can we improve our authentication. and that was removed, fair. but when I followed up with a step by step guide to using cloudflare's ZeroTrust Access Policy, and toned down the ridicule, it earned me a ban from the forum, the threads are below.

Multi-factor authentication
We will be hopeful.
Two factor authentication?
Just came across this post as I set up my first Ghost instance. It is 2021 and MFA via TOTP would be really a great feature. And it is really an accepted and widely available standard these days. #MFANow
Best method to integrate 2FA for our members and staff?
We are hosting Ghost on a cloud-based service and installed Ghost core. We have everything working, but are very uncomfortable with the lack of 2FA or MFA. For those unaware, this is two-factor or multi-factor authentication. We just loaded the last version of Ghost, the security update, and still…
How complex is it to plug an external auth provider
Hey team! I’m in the same boat: with introduction of Members (fantastic feature!) I must find a way to integrate the members that I already have elsewhere (in my case, they are in https://auth0.com) and let them login with their prefered method and existing credentials. It would also allow users to…

Where Ghost does have some defence capability it lacks mature authenticaiton mechanics fit for 2000 and beyond

spicy

From here https://github.com/TryGhost/Ghost/blob/5ca082cd7c2b9aca56182bd3f0632b54c6149865/ghost/core/core/server/web/shared/middleware/brute.js

I'll talk about some of the relevent middleware functions that some Ghost developers reach for instead of offering MFA.

Middleware Functions

globalBlock & globalReset: Blocks or resets blocks per route per IP. It uses the path of the request URL as the key to track the block status.

IP-Blocklisting isn't really meaningful, IP-Rotating proxy services are available, deploying it in AWS is also an option (Fireproxy)

userLogin & userReset: Blocks or resets blocks based on user login. userLogin uses the string 'user_login' as the key, and userReset uses the username with 'reset' appended as the key.

Not ideal if you have people abusing this to lock out your team

privateBlog: Blocks based on IP for a private blog, using 'privateblog' as the key.

This is as useful for security as it is useless for audiance (unless it's a small userbase, internal blog.

membersAuth: Blocks too many password guesses for the same email address. Uses the email concatenated with 'login' as the key.

This falls short the same way userLogin & UserReset does, scriptable attack, very annoying for (paying ?) subscribers - a slight scope creep but relative 

membersAuthEnumeration: Specifically aimed at blocking user enumeration attacks.

This is void by way of inference, if the MembersAuth function blocks on too many password guesses for the same email address, then you can infer that that account is present, access really should be granted via magic link email access to avoid inference

So, if you host a small website with a small 1-10 staff members, these are probably okay, providing you get visibility over login attempts, (Time, IP Address, valid users failed auths) but you won't get that in the GUI, and there's real problems with locking legit users and addresses out.

Wouldn't it be easier if we could just have MFA? The way Ghost Pro has for its management WordPress instance over at wp.ghost.org  (but not for its users), having MFA normalises strong authentication mechanics, many are familiar with it and we do not have to pander to poor architectural design choices and the creative side effects we see above, they like MFA are not without their shortcomings, but addressing MFA shortcomings versus addressing these shortcomings is a much smarter move.

My Advice is not to use Ghost Pro but to host your own instance and use Cloudflares ZeroTrust Access Policy on your /ghost/* admin zone, it will be cheaper more secure and you'll have more visibility over your traffic.

I think the guys on the ghost forum may be extra salty because I'd suggested the lack of MFA for ... let's say 2013 (when ghost began) is a result of poor architectural design decisions with security on the retrofit pile. I don't think i'll change that view, it's a shame, I enjoy Ghost, and I enjoy it more now that I've got stronger authentication mechanics fit for 2013 and onwards.

Over To CloudFlare

You can see in the Cloudflare Zerotrust zone, under Access, and Applications, this blog, what I've targetted is the /ghost path, so anything that is /ghost/* falls under the policy criteria for interjecting and inviting that visitor to prove entitlements to those resources (authenticate)

I've configured mine to send a one-time pin to any of the email addresses I've pre-defined, but you can go further, and have an authenticator, sms, and other out-of-band means to authenticate.

Now when I come to log in, I have to provide my known-to-me email(s) and if they're the same, those emails will receive a one-time pin

You get your code and you're good to go!

That's it, any questions, happy to help, Ping me on twitter @thecontractorio