Anthony Ferrara (ircmaxell) writes about PHP, password hashing, cryptography, and security vulnerabilities, including his own disclosures.
Commenters cite it for password hashing guidance, such as why he doesn't recommend scrypt, and for his WordPress SQL injection disclosure.
Udacity has a Networking for Web Developers course[0], but I'd recommend trying out things (such as running a simple web-app on your own server). Things like:
- Running https://certbot.eff.org/instructions
- Trying out a few different web servers (apache/nginx/caddy)
- Playing around with load-balancers on $cloud_provider.
- Spending time with docker networking (https://docs.docker.com/config/containers/container-networking/)
- Playing around with various X-Forwarded header options in the context of your application
For a web developer, the most useful skill is knowing what each and every component on the pipeline is doing before your code executes on the request. As a common eg, if your application seems to be loading stylesheets from `http://` instead of `https://` despite being loaded over HTTPS, it is often because your application didn't honor the X-Forwarded-Proto header (which most frameworks will do for you). Similarly, seeing a local IP address (192.168.x.y for eg) on a log, and realizing that you should be using the X-Forwarded-Ip by "trusting your proxy"[1] and doing it securely[2].[3].
[0]: https://www.udacity.com/course/networking-for-web-developers--ud256
[1]: https://expressjs.com/en/guide/behind-proxies.html
[2]: https://shubs.io/enumerating-ips-in-x-forwarded-headers-to-bypass-403-restrictions/
[3]: https://blog.ircmaxell.com/2012/11/anatomy-of-attack-how-i-hacked.html
Wordpress, Joomla and Drupal are not good examples of "good" PHP code. They work, and are used extensively, but experienced developers who care about code quality blow a gasket when they look at the source code.
To do proper PHP development you should have a local VM. I created something to help in that regard[0]. It's been fairly well received.
There's also websites like PHP The Right Way [1] that act like a collection of best practices. If you're not using Composer[2] you should start doing so. I wish Javascript had a package manager as robust and useful as Composer (I know of Bower, but imo it's not nearly as good!). PHP Developer[3] is a source of good daily blog posts. The ones I read on a regular basis are ircmaxell [4], fabpot[5], lornajane[6], philsturgeon[7], richardmiller[8], and phparch[9]. I also sometimes write some things[10].
[0] https://puphpet.com
[1] http://phptherightway.com
[2] http://getcomposer.org
[3] http://phpdeveloper.org
[4] http://blog.ircmaxell.com
[5] http://fabien.potencier.org
[6] http://lornajane.net
[7] http://philsturgeon.co.uk/blog
[8] http://richardmiller.co.uk
[9] http://phparch.com
[10] https://jtreminio.com
> These functions belong to a family of functions known as key derivation functions: they use hashing to produce a digest which is suitable for use as a password hash.
KDFs are not for storing password hashes, they are for key derivation. This is a subtle point, the main thing is to use KDFs as KDFs (to derive keys that are then used to encrypt data). Details in the first link here (the second is about common mistakes when using scrypt):
- http://blog.ircmaxell.com/2014/03/why-i-dont-recommend-scrypt.html (bad title, he's referring to pass storage, not KDF usage)
- http://vnhacker.blogspot.com/2014/04/fairy-tales-in-password-hashing-with.html
Another consideration is plausible deniability (PD) for situations where you're compelled to disclose your password(s). Our company writes Mac encryption software that specializes in this (and it uses scrypt). Here's a list of tools that offer PD (ours is called Espionage):
https://en.wikipedia.org/wiki/Deniable_encryption#Software
I compared Espionage's PD to TrueCrypt's on reddit:
http://www.reddit.com/r/security/comments/2b5icu/major_advancements_in_deniable_encryption_arrive/cj24a1n
> A properly implemented, simple pepper can only help password security and can't hurt it.
Well, yes. But what is the definition of "properly"? There are definitely constructions of "pepper" that look simple, but drastically hurt overall security:
bcrypt(hmac(password, key), salt)
If hmac returns raw bytes, you're in real trouble: http://blog.ircmaxell.com/2015/03/security-issue-combining-bcrypt-with.html
It's sort of like the difference between birth control and counting based contraceptive methods (Standard Days Method). Executed perfectly, they are equally as effective. But with a slight error, one stays roughly as effective (losing maybe 5 to 10% effectiveness overall) while the other drops drastically (down to 10 to 20% effectiveness).
Considering using encryption is as effective as using a pepper, and it's less prone to weakening the core password hash, I suggest using encryption instead of peppers.
This is almost always less secure than KC alone, when KC is a well-known secure cipher.
A simple example would be a CC that hex-encodes the plaintext before applying some transformation on the data (before you laugh, this exists in enterprise systems today). This means CC would effectively expand the underlying data 200% (0xA1 -> 0x4131) and substantially degrade the security of a block-based cipher (32-bit block -> effectively 16-bits).
Here's a link to a practical case of unsafe composition (in hashing): http://blog.ircmaxell.com/2015/03/security-issue-combining-bcrypt-with.html
A bit more detail on randomly composing encryption algorithms: http://blog.cryptographyengineering.com/2012/02/multiple-encryption.html
edit: It would be better to compose CC(KC(P)) so CC can't leak any information about P or degrade KC. Any reluctance to show the world the output of CC should suggest the low-practical-value of CC.
Just because you choose to ignore valid criticism, that doesnt mean there is no criticism.
Go read https://blog.ircmaxell.com/2017/10/disclosure-wordpress-wpdb-sql-injection-technical.html#The-Correct-Fix
A couple of little snippets to highlight the point I'm trying to make:
> The current system is insecure-by-design. That doesn’t mean it’s always hackable, but it means you have to actively work to make it not attackable. It’s better to switch to a design that’s secure-by-default and make the insecure the exceptional case.
> The best path forward would be to switch to PDO/MySQLi and use real prepared statements and not emulate them in PHP land. That’s the best path forward.
But given that the core wordpress team basically ignore this type of suggestion from PHP core contributors, why would I expect you to believe me about it here?