October 30: 25 Simple Ways To Secure Your Apps

He that is without sin among you, let him first cast a stone… go, and sin no more.

Jesus Christ, John 8:7-11
Glass houses and stone throwing donʼt mix

2024.01.29 update: Microsoft’s Midnight Blizzard breach prompted three more simple ways to secure your apps, bringing the total to 28.

2024.01.31 update: CISA Director Jen Easterly’s statement before Congress: “The technology underpinning our critical infrastructure is inherently insecure.”

No one’s perfect. Each of us has made mistakes. I’ve even created a hall of fame page for those who have highlighted where my company has fallen short in enterprise security. But it’s our recovery from mistakes that defines us and helps me to help others. With that said, let’s learn from two recent security breaches.

Okta: use phishing-resistant credentials!

Okta’s customer support system experienced a breach on October 20th. This followed a previous breach of their outsourced support partner Sitel in 2022. The recurring breaches in the same department are concerning. Despite Okta’s status as an enterprise security leader, these breaches raise questions about their authentication methods. Phishing-resistant credentials stored in secure hardware are nearly unbreachable (unless you have 200 trillion guesses).

Grammarly: verify your OAuth tokens!

Authenticating is great. I love it. But most developers (who are not me) spend a tiny fraction of their time working on authentication. And no time agonizing over Public vs. Confidential Clients, the dangers of implicit flows, or how to interpret the latest IETF admonitions against JavaScript OAuth libraries. Instead, the vibe as I talk to clients is more like: “we were prompted for creds, we provided them, we got a token, we stored it and moved on!” OAuth requires a bit more care. The folks at Salt Labs do a great job of explaining the reasons to validate the audience as well as the issuer of OAuth tokens (and they are now on my hall of fame page).

Here’s the problem: Have you noticed when assembling a firearm (or vacuum cleaner) that the pieces only fit together one way? That’s on purpose. The manufacturer knows people will put it together wrong and complain when it blows up. Authentication platforms aren’t like that (though Entra Security Defaults and the new Automatic Conditional Access Policies head in that direction). They don’t care if you validate the audience claim, use obsolete high-risk flows, or get hacked. Any insecure scenario to which a platform says “no” becomes a design loss to a competitor. Not enough people say, “You can’t do that; it’s insecure.” It’s more profitable to say, “We can do whatever you like.” My favorite conspiracy theory? Eran Hammer’s #fuckoauth talk 11 years ago.

Not Another Security Acronym

Reviewing these breaches and recent conversations with clients, I noticed a gap between frameworks like NIST, ISO 27001, and CMMC and the concrete guidance I needed to implement secure enterprise authentication. I may have tunnel vision on authentication. But I don’t need to know how high a fence has to be to deter a determined intruder (it’s 8 feet). I mainly care about building apps that don’t get hacked. With that, I humbly present my 25 considerations when authenticating enterprise apps.

Arvind Suthar’s Simple Web App Security Handbook

1. align your culture

The team has to value web application security to take action. The first step is to baseline where the team is and assess the need for change.

2. use an established cloud-based IDP

Any established IDP must provide 8 of the 25 listed measures (i.e. numbers 2-9) to even exist as a viable offering. You don’t want to re-invent multi-factor authentication, phishing-resistant auth methods, device compliance checks, and single-sign-on across resources and organizations. To show how simple and platform-agnostic these IDPs are, I’ve created a small sample here that authenticates to Azure AD from React (can run in any browser) to an Entra ID protected API implemented in Spring Boot (can run in Amazon Web Services).

That being said, some developers want to store usernames and passwords in databases and Microsoft wants to support them. The enterprise scenarios justifying this approach are increasingly rare. I go into detail on this point here.

3. multi-factor authentication

Multi-factor authentication dramatically lowers the risk of compromise. Number matching is better than Approve/Deny. Even better is phishing-resistant MFA that locks the MFA response to a particular app challenge. Layering on device compliance checks provides another level of “what you have”.

4. secure credential storage

IF you need to store passwords (you probably don’t), use cryptographic hashing algorithms like bcrypt, scrypt, or Argon2 to store passwords. Never store passwords in plaintext. Use salts with hashes to prevent rainbow table attacks. Windows Server Active Directory Domain Controllers go a step further and store user passwords as non-reversible hashes.

5. rate limiting and lockouts

Implement rate limiting to prevent brute-force attacks. Temporarily lock out accounts after a certain number of failed login attempts.

6. proven methods and protocols

Avoid Security Through Obscurity. Rely on proven methods and protocols. Don’t attempt to create your own cryptographic algorithms.

7. input validation and sanitization

Properly validate and sanitize all inputs (e.g., usernames, passwords) to prevent injection attacks.

8. logging and monitoring

Log authentication attempts, especially failures. Monitor for suspicious activities such as multiple failures from a single IP.

9. API security

If your web application exposes an API, ensure that it has proper authentication mechanisms, such as API keys or JWTs (JSON Web Tokens).

Secure your IT environment

You can have the greatest IDP, but still experience a compromise if you don’t manage your environment well.

10. document your architecture

Simply writing down how your system works will surface things that aren’t quite right and inspire resolution. Fix what you can and track the deferred items in a risk register (we use Azure Dev Ops). Big thanks to Jennifer Johnson at Microsoft for insisting on high-level security collateral. This is making our product better.

11. document your processes

Similarly, writing down how you manage your system will surface best practice violations that are often easily addressed. Thank you to Peter Carson at Envision IT for asking the simple questions to help us get our operational house in order. Again, fix what you can and track the deferred items in a risk register.

12. passwordless and phishing resistant credentials

I don’t believe training is effective in preventing compromise. The best password is no password. I can’t divulge a password I don’t know. FIDO authenticators can’t divulge their keys just because a service URL looks “close” to a legitimate service. Go passwordless with phishing-resistant credentials and stop the phishing.

13. separate admin and productivity accounts

If you never open an email or browse the web, you will be safer. While that isn’t feasible, you can lower the chance of privileged accounts getting compromised by blocking those accounts from checking email and browsing the web – the most common attack vectors.

14. don’t federate highly privileged cloud accounts

Similarly, disallowing federation of highly privileged cloud accounts prevents compromise in an external identity provider from lateral movement into your cloud environment. See the Protecting Microsoft 365 article for full details.

15. notifications for auth method registration

Finally, no admin can watch everything at once. The person most likely to detect the registration of a fraudulent auth method on an account is the owner of that account. Sending a notification (and perhaps even requiring approval or offering a chance to revoke) when a new auth method is registered provides an extra set of eyes that can detect and block an attack.

Secure your development practices

Using an established IDP within a secure IT environment provides a solid foundation for a dev team to develop the most secure enterprise apps possible.

16. use HTTPS

Always use HTTPS to encrypt data in transit between the client and server, especially during login and authenticated actions.

17. verify token audience and token issuer

Even though your code will work fine without verifying the token audience, your code will accept any token from any app that’s managed to get into your tenant. See the very nice explanation by the folks at Salt Labs.

18. prefer authorization code flow with PKCE, avoid implicit flow

The implicit flow returns access tokens immediately in the redirect. The authorization code flow returns a code, which must be then (in combination with a PKCE code generated at the start of the process) exchanged for an access token. Essentially, an attacker needs to do several coordinated actions instead of just one to intercept an access token. As is often the case, Okta provides a gold standard explanation of the situation.

19. prefer the BFF pattern and Confidential Clients

I wrote about this here and then later here. The IETF is preparing a best practice recommendation here that takes a strong stand against JavaScript auth libraries: Summary

To summarize, the architecture of a browser-based OAuth 2.0 client application is straightforward, but results in a significant increase in the attack surface of the application. The attacker is not only able to hijack the client, but also to extract a full-featured set of tokens from the browser-based application.

This architecture is not recommended for business applications, sensitive applications, and applications that handle personal data.

Internet Engineering Task Force (IETF)

20. careful with storing customer data

GDPR, PCI, HIPAA, FedRAMP, SOC 1 & 2, etc. all more or less come down to this: take great care to protect your customers’ data, extract it for them when they ask, and let them know if you’ve been compromised.

21. session management

  • Use secure, random session identifiers.
  • Store session data securely, either in a secure cookie or on the server side.
  • Implement session expiration.
  • Allow users to log out and invalidate sessions.

22. protect against CSRF (cross-site request forgery) attacks

Implement anti-CSRF tokens in your forms. Your established cloud-based IDP will certainly have done this for their login forms.

23. cross-origin considerations

If your app uses resources from multiple domains, be aware of CORS (Cross-Origin Resource Sharing) and ensure it’s configured securely.

24. CI/CD pipeline with security and regression testing

Automated builds, static and dynamic code analysis, and regression tests enable catching some set of vulnerabilities early in the development process. I highly recommend the SANS SEC540 DevOps course if you have interest in this area.

25. regularly update and review

Security isn’t a one-time task. Regularly review and update your authentication methods to accommodate new security findings and best practices. For those using Azure AD, consider the Azure AD Assessment to track and enhance your security related to Azure AD.

Further Reading

If you’re hungry to learn more, this amazing list was posted by Matthew Zorich.

  1. Token Tactics: How to prevent, detect, and respond to cloud token theft
  2. AiTM/ MFA phishing attacks and “new” Microsoft protections (2023)
  3. Replay of PRT and other issued tokens from an Azure AD joined device
  4. Why using a FIDO2 security key is important
  5. Abusing Azure AD SSO with the Primary Refresh Token
  6. How Storm-1101 enables AiTM with open-source phishing kit
  7. Dr. Nestori Syynimaa’s AADInternals Toolkit
  8. Token Tactics toolkit from rvrsh3ll, another great token toolkit
  9. Microsoft’s Token Theft Playbook

Feel free to reach out!

We are charging forward with Identity Bridge security fixes, process and architecture documentation, sovereign cloud support, and “Free” and “Assessor” plans to enable more people to engage in more ways with our multi-tenant platform.

We are also very interested in taking on custom development projects in the areas of Entra ID, Security Assessment & Monitoring, and Active Directory.

Thanks so much for all the support and well-wishes!