there was quite along learning curve but start feeling comfortable using Traefik on a daily base.
Recently I went into the details on how to secure Traefik.
I'm afraid, that the information that is given in the tutorial Traefik 2.0 & Docker 101 and in the docs are misleading, may even imply a security risk.
The first makes you belive setting a password is all that has to be done, the latter even advertises an insecure hash algorithm.
May I start with the latter.
It is strongly advised not to use MD5 and SHA1 as mentioned in/by
- MD5, SHA1 are · Issue #6201 · containous/traefik
- Open Web Application Security Project (OWASP)
- a team of researchers at Google and CWI have published a collision, see
Scientific Working Group on Digital Evidence (SWGDE)
but Traefik's docs still lists both als option although BCrypt is supported and even worse the hash used in the example code is MD5 based. Ok, it is fortified using APR1 but it cannot be considered that safe, e.g. read Is every hash format that Nginx accepts for HTTP Basic Auth weak against brute force? - Information Security Stack Exchange or Bruteforce Apr1 hashes.
- backed with some numbers from 2010, showing how unsafe it was 10 years ago!
- but to use Bcrypt, see How To Safely Store A Password | codahale.com
So why is BCrypt strongly recommended and used in the code example?
Now the first.
Reading Traefik's blog entries Traefik 2.0 & Docker 101 can lead to the imagination that settings the password barrier is all that is needed.
That is definitely not the case and poses an operational risk as a proper BCrypt hash can take time to be generated following recommended cost factors.
Years ago a cost factor of 10 was default and 12 recommended, read:
- security - How can bcrypt have built-in salts? - Stack Overflow, in late 2018, 12 became the default value in e.g. bcrypt-ruby,a Ruby binding for the OpenBSD'S bcrypt()
- Recommended # of rounds for bcrypt - Information Security Stack Exchange
So you may go for >=13 nowadays, what as quite time-wise impact, see Hashing in Action: Understanding bcrypt.
This decision has an impact on the server and the usability of Traefik dashboard. On the one hand that can slow down your server when it suffers a brute-force attack, see dashboard loads longer with BasicAuth & Bcrypt Hash · Issue #6200 · containous/traefik, plus in there referenced issues.
On the other hand, if a brute-force attack, originating from multiple corners of the internet, is on-going, the additional load that is put on the server can be quite high as it needs lot of CPU power to answer each log-in attempt.
So I'm wondering that there are not any warning and recommendations to implement:
- RateLimit - Traefik
- InFlightReq - Traefik
- (CircuitBreaker - Traefik)
- and may tell that it safer to use https and
Basicsounds like minimum approach what could be improved by better a more sophisticated authentication, such as
ForwardAuthand recommend an external service like Keycloak to prove the credentials.
- DDOS detection/mitigation support · Issue #431 · containous/traefik
Traefik and ddos protection · Issue #4803 · containous/traefik
are still open at the time I write this and it is clear that doing manual brute force attack detection, to adapat configuration, is not trivial as well explained in Brute Force: Anatomy of an Attack.
So that is my humble opinion on this, coming from learning by doing approach.
It is properly easier to understand why I say this when I state what I have learned so far and what sources are to blame
To be honest, the first time I read the documentation I was quite confused by the hash syntax and trying to understand how the password is stored/checked.
So I began to ask google and I found a nice visualization of the Bcrypt result string in
Understanding bcrypt salt as used by PHP password_hash - Stack Overflow
giving me clue about the cryptic string in the docs
I continued reading the essence of the difference between Encryption, Hashing and Salting and how it can be combined, see An Illustrated Guide to Cryptographic Hashes.
Moreover, I found good explanation on the difference of Salting and Hashing, reading:
- Understanding Password Authentication & Password Cracking
- node.js - How does node.bcrypt.js compare hashed and plaintext passwords without the salt? - Stack Overflow
and good illustration on how all if cab be combined: RSA sign and verify using Openssl : Behind the scene
So I learned that ashing and salting won't prevent a brute force attack but it will slow down the process, as well commented in How is hashing and salting a password going to stop Brute Force attack. : webdev.
Another point is, taht if the database is breached by either SQL injection vulnerability or obtaining a backup of the database they are able to crack any of the hashes, so it is recommended to pepper the salts.
There is a nice explanation of all this in What is hashing? - Tech Tales - Medium and an excellent presentation, what you can enjoy on Safely storing passwords.
As I generated some hashed I was quite irritated that the result different each time I press the generate button. It turned it wasn't only me and the reason is simple, it is due salting and/or encoding, depending on your hash function:
- grails - Bcrypt generates different hashes for the same input? - Stack Overflow
- go - Bcrypt encryption different every time with same input - Stack Overflow
Last but not least I found a good explanation of why you should not use Digest access authentication - Wikipedia. Wikipedia lists the risk clearly and you find the risk in a nutshell on Flaw in HTTP Digest Authentication - Information Security Stack Exchange. My main concern is that since either the password or the digested username, realm and password must be recoverable, it means it isn't digested/hashed.
For information here a the tools I used during my journey