Categories
Cryptography Software Security Technology

On The Toxicity of Zed A. Shaw

Boycott Zed Shaw’s writing. (With bonus zero-days in his work.)

Let me say up front, I’m no stranger to negative or ridiculous feedback. It’s incredibly hard to hurt my feelings, especially if you intend to. You don’t openly participate in the furry fandom since 2010 without being accustomed to malevolence and trolling. If this were simply a story of someone being an asshole to me, I would have shrugged and moved on with my life.

It’s important that you understand this, because when you call it like you see it, sometimes people dismiss your criticism with “triggered” memes. This isn’t me being offended. I promise.


My recent blog post about crackpot cryptography received a fair bit of attention in the software community. At one point it was on the front page of Hacker News (which is something that pretty much never happens for anything I write).

Unfortunately, that also means I crossed paths with Zed A. Shaw, the author of Learn Python the Hard Way and other books often recommended to neophyte software developers.

As someone who spends a lot of time trying to help newcomers acclimate to the technology industry, there are some behaviors I’ve recognized in technologists over the years that makes it harder for newcomers to overcome anxiety, frustration, and Impostor Syndrome. (Especially if they’re LGBTQIA+, a person of color, or a woman.)

Normally, these are easily correctable behaviors exhibited by people who have good intentions but don’t realize the harm they’re causing–often not by what they’re saying, but by how they say it.

Sadly, I can’t be so generous about… whatever this is:

What the fuck.

Having never before encountered a living example of a poorly-written villain towards the work I do to help disadvantaged people thrive in technology careers, I sought to clarify Shaw’s intent.

The shitshow is archived too.

This is effectively a very weird hybrid of an oddly-specific purity test and a form of hazing ritual.

Let’s step back for a second. Can you even fathom the damage attitudes like this can cause? I can tell you firsthand, because it happened to me.

Interlude: Amplified Impostor Syndrome

In the beginning of my career, I was just a humble web programmer. Due to a long story I don’t want to get into now, I was acquainted with the culture of black-hat hacking that precipitates the DEF CON community.

In particular, I was exposed the writings of a malicious group called Zero For 0wned, which made sport of hunting “skiddiez” and preached a very “shut up and stay in your lane” attitude:

Geeks don’t really come to HOPE to be lectured on the application of something simple, with very simple means, by a 15 year old. A combination of all the above could be why your room wasn’t full. Not only was it fairly empty, but it emptied at a rapid rate. I could barely take a seat through the masses pushing me to escape. Then when I thought no more people could possibly leave, they kept going. The room was almost empty when I gave in and left also. Heck, I was only there because we pwned the very resources you were talking about.

Zero For 0wned

My first security conference was B-Sides Orlando in 2013. Before the conference, I had been hanging out in the #hackucf IRC channel and had known about the event well in advance (and got along with all the organizers and most of the would-be attendees), and considered applying to their CFP.

I ultimately didn’t, solely because I was worried about a ZF0-style reception.

I had no reference frame for other folks’ understanding of cryptography (which is my chosen area of discipline in infosec), and thought things like timing side-channels were “obvious”–even to software developers outside infosec. (Such is the danger of being self-taught!)

“Geeks don’t really come to B-Sides Orlando to be lectured on the application of something simple, with very simple means,” is roughly how I imagined the vitriol would be framed.

If it can happen to me, it can happen to anyone interested in tech. It’s the responsibility of experts and mentors to spare beginners from falling into the trappings of other peoples’ grand-standing.

Pride Before Destruction

With this in mind, let’s return to Shaw. At this point, more clarifying questions came in, this time from Fredrick Brennan.

What an arrogant and bombastic thing to say!

At this point, I concluded that I can never again, in good conscience, recommend any of Shaw’s books to a fledgling programmer.

If you’ve ever published book recommendations before, I suggest auditing them to make sure you’re not inadvertently exposing beginners to his harmful attitude and problematic behavior.

But while we’re on the subject of Zed Shaw’s behavior…

This is actually the dude’s pinned tweet.

If Shaw thinks of himself as a superior cryptography expert, surely he’s published cryptography code online before.

And surely, it will withstand a five-minute code review from a gay furry blogger who never went through Shaw’s prescribed hazing ritual to rediscover specifically the known problems in OpenSSL circa Heartbleed and is therefore not as much of a cryptography expert?

Soatok is _TOTALLY_ innocent
(Art by Khia.)

May I Offer You a Zero-Day in This Trying Time?

One of Zed A. Shaw’s Github projects is an implementation of SRP (Secure Remote Password)–an early Password-Authenticated Key Exchange algorithm often integrated with TLS (to form TLS-SRP).

Zed Shaw’s SRP implementation

Without even looking past the directory structure, we can already see that it implements an algorithm called TrueRand, which cryptographer Matt Blaze has this to say:

You should be using /dev/urandom.

As noted by the README, Shaw stripped out all of the “extraneous” things and doesn’t have all of the previous versions of SRP “since those are known to be vulnerable”.

So given Shaw’s previous behavior, and the removal of vulnerable versions of SRP from his fork of Tom Wu’s libsrp code, it stands to reason that Shaw believes the cryptography code he published would be secure. Otherwise, why would he behave with such arrogance?

SRP in the Grass

Head’s up! If you aren’t cryptographically or mathematically inclined, this section might be a bit dense for your tastes. (Art by Scruff.)

When I say SRP, I’m referring to SRP-6a. Earlier versions of the protocol are out of scope; as are proposed variants (e.g. ones that employ SHA-256 instead of SHA-1).

Professor Matthew D. Green of Johns Hopkins University (who incidentally used to proverbially shit on OpenSSL in the way that Shaw expects everyone to, except productively) dislikes SRP but considered the protocol “not obviously broken”.

However, a secure protocol doesn’t mean the implementations are always secure. (Anyone who’s looked at older versions of OpenSSL’s BigNum library after reading my guide to side-channel attacks knows better.)

There are a few ways to implement SRP insecurely:

  1. Use an insecure random number generator (e.g. TrueRand) for salts or private keys.
  2. Fail to use a secure set of parameters (q, N, g).

    To expand on this, SRP requires q be a Sophie-Germain prime and N be its corresponding Safe Prime. The standard Diffie-Hellman primes (MODP) are not sufficient for SRP.

    This security requirement exists because SRP requires an algebraic structure called a ring, rather than a cyclic group (as per Diffie-Hellman).
  3. Fail to perform the critical validation steps as outlined in RFC 5054.

In one way or another, Shaw’s SRP library fails at every step of the way. The first two are trivial:

  1. We’ve already seen the RNG used by srpmin. TrueRand is not a cryptographically secure pseudo random number generator.
  2. Zed A. Shaw’s srpmin only supports unsafe primes for SRP (i.e. the ones from RFC 3526, which is for Diffie-Hellman).

The third is more interesting. Let’s talk about the RFC 5054 validation steps in more detail.

Parameter Validation in SRP-6a

From a client’s perspective, you must verify that (B % N) != 0. This is critical to the security of SRP. This check prevents dictionary attacks on the password from a man-in-the-middle.

From the server’s (or a peer’s) perspective, you must also verify (A % N) > 0 to prevent the server’s session key from being forced to a known value (i.e. zero).

Additionally, the value u must not be revealed by the server until the client has sent A. It must also not be set to 0. Failure to uphold these constraints can allow clients to impersonate their peers.

These are obvious and well-known SRP constraints first published in 1997 by Tom Wu.

Server-Side Validation in Zed Shaw’s Library

Zed Shaw’s SRP server logic begins here:

cstr *ssrp_server_verify(SRP *srps, cstr *client_pub, cstr *client_proof)
{
    SRP_RESULT rc;
    cstr *server_proof = NULL;
    rc = SRP_compute_key(srps, &server_proof, client_pub->data, client_pub->length);
    check(SRP_OK(rc), "SRP_compute_key failed\n");
    rc = SRP_verify(srps, client_proof->data, client_proof->length);
    check(SRP_OK(rc), "SRP_verify failed: %d", rc);
    rc = SRP_respond(srps, &server_proof);
    check(SRP_OK(rc), "Failed creating the response.");
    return server_proof;
error:
    return NULL;
}

Through a bit of indirection, SRP_compute_key() points to the srp6_server_key() function and SRP_verify() points to srp6_server_verify().

Client-Side Validation in Zed Shaw’s Library

Zed Shaw’s SRP client logic begins here:

cstr *ssrp_client_respond(SRP *srpc, cstr *server_pub, const char *pass)
{
    cstr * key_client = NULL;
    SRP_RESULT rc = SRP_set_auth_password(srpc, pass);
    check(SRP_OK(rc), "SRP_set_authenticator failed\n");
    rc = SRP_compute_key(srpc, &key_client, server_pub->data, server_pub->length);
    check(SRP_OK(rc), "SRP_compute_key failed\n");
    rc = SRP_respond(srpc, &key_client);
    check(SRP_OK(rc), "SRP_respond failed\n");
    return key_client;
error:
    return NULL;
}

Through a similar round of indirection as the server-side code, the heavy-lifting (mostly in SRP_compute_key()) is performed by the srp6_client_key_ex() function.

Protocol Vulnerability in Zed Shaw’s Library

As stated above, the value for u must be a) generated by a secure random number generator and b) not revealed by the server until after the client has revealed their public key (A) to the server.

Zed Shaw’s SRP library simply doesn’t do any of that.

It doesn’t use a secure random number generator for calculating private keys. It doesn’t enforce A to be transmitted before revealing B and u. You don’t have to call the prescribed steps in any particular order (especially with inputs over a network, rather than from benchmarking code).

Additionally, although u is calculated from H(A | B), these are both public values–which, I must remind you, are the outputs of insecure random number generator–and the client doesn’t validate that u != 0.

Vulnerability Summary and Impact

That’s a lot of detail, but I hope it’s clear to everyone that all of the following are true:

  1. Zed Shaw’s library’s use of TrueRand fails the requirement to use a secure random source. This weakness affects both the salt and the private keys used throughout SRP.
  2. The library in question ships support for unsafe parameters (particularly for the prime, N), which according to RFC 5054 can leak the client’s password.
  3. The lack of client-side validation on u–as well as the reliance on insecure RNGs for generating private keys and therefore u (as the hash of the public keys)–allows trivial client impersonation to the server.

Salts and private keys are predictable, the hard-coded parameters allow passwords to leak, and you can impersonate clients through active attacks.

Facepaw
But yes, OpenSSL is the real problem, right?
(Art by Khia.)

Low-Hanging ModExp Fruit

Shaw’s SRP implementation is pluggable and supports multiple back-end implementations: OpenSSL, libgcrypt, and even the (obviously not constant-time) GMP.

Even in the OpenSSL case, Shaw doesn’t set the BN_FLG_CONSTTIME flag on any of the inputs before calling BN_mod_exp() (or, failing that, inside BigIntegerFromInt).

As a consequence, this is additionally vulnerable to a local-only timing attack that leaks your private exponent (which is the SHA1 hash of your salt and password). Although the literature on timing attacks against SRP is sparse, this is one of those cases that’s obviously vulnerable.

Exploiting the timing attack against SRP requires the ability to run code on the same hardware as the SRP implementation. Consequently, it’s possible to exploit this SRP ModExp timing side-channel from separate VMs that have access to the same bare-metal hardware (i.e. L1 and L2 caches), unless other protections are employed by the hypervisor.

Leaking the private exponent is equivalent to leaking your password (in terms of user impersonation), and knowing the salt and identifier further allows an attacker to brute force your plaintext password (which is an additional risk for password reuse).

Houston, The Ego Has Landed

Earlier when I mentioned the black hat hacker group Zero For 0wned, and the negative impact their hostile rhetoric, I omitted an important detail: Some of the first words they included in their first ezine.

For those of you that look up to the people mentioned, read this zine, realize that everyone makes mistakes, but only the arrogant ones are called on it.

Zero For 0wned

If Zed A. Shaw were a kinder or humbler person, you wouldn’t be reading this page right now. I have a million things I’d rather be doing than exposing the hypocrisy of an arrogant jerk who managed to bullshit his way into the privileged position of educating junior developers through his writing.

If I didn’t believe Zed Shaw was toxic and harmful to his very customer base, I certainly wouldn’t have publicly dropped zero-days in the code he published while engaging in shit-slinging at others’ work and publicly shaming others for failing to meet arbitrarily specific purity tests that don’t mean anything to anyone but him.

But as Dan Guido said about Time AI:

It’s high time we stopped tolerating Zed’s behavior in the technology community.

If you want to mitigate impostor syndrome and help more talented people succeed with their confidence intact, boycott Zed Shaw’s books. Stop buying them, stop stocking them, stop recommending them.

Learn Decency the Hard Way

(Updated on February 12, 2021)

One sentiment and question that came up a few times since I originally posted this is, approximately, “Who cares if he’s a jerk and a hypocrite if he’s right?”

But he isn’t. At best, Shaw almost has a point about the technology industry’s over-dependence on OpenSSL.

Shaw’s weird litmus test about whether or not my blog (which is less than a year old) had said anything about OpenSSL during the “20+ years it was obviously flawed” isn’t a salient critique of this problem. Without a time machine, there is no actionable path to improvement.

You can be an inflammatory asshole and still have a salient point. Shaw had neither while demonstrating the worst kind of conduct to expose junior developers to if we want to get ahead of the rampant Impostor Syndrome that plagues us.

This is needlessly destructive to his own audience.

Generally the only people you’ll find who outright like this kind of abusive behavior in the technology industry are the self-proclaimed “neckbeards” that live on the dregs of elitist chan culture and desire for there to be a priestly technologist class within society, and furthermore want to see themselves as part of this exclusive caste–if not at the top of it. I don’t believe these people have anyone else’s best interests at heart.

So let’s talk about OpenSSL.

OpenSSL is the Manifestation of Mediocrity

OpenSSL is everywhere, whether you realize it or not. Any programming language that provides a crypto module (Erlang, Node.js, Python, Ruby, PHP) binds against OpenSSL libcrypto.

OpenSSL kind of sucks. It used to be a lot worse. A lot of people have spent the past 7 years of their careers trying to make it better.

A lot of OpenSSL’s suckage is because it’s written mostly in C, which isn’t memory-safe. (There’s also some Perl scripts to generate Assembly code, and probably some other crazy stuff under the hood I’m not aware of.)

A lot of OpenSSL’s suckage is because it has to be all things to all people that depend on it, because it’s ubiquitous in the technology industry.

But most of OpenSSL’s outstanding suckage is because, like most cryptography projects, its API was badly designed. Sure, it works well enough as a Swiss army knife for experts, but there’s too many sharp edges and unsafe defaults. Further, because so much of the world depends on these legacy APIs, it’s difficult (if not impossible) to improve the code quality without making upgrades a miserable task for most of the software industry.

What Can We Do About OpenSSL?

There are two paths forward.

First, you can contribute to the OpenSSL 3.0 project, which has a pretty reasonable design document that almost nobody outside of the OpenSSL team has probably ever read before. This is probably the path of least resistance for most of the world.

Second, you can migrate your code to not use OpenSSL. For example, all of the cryptography code I’ve written for the furry community to use in our projects is backed by libsodium rather than OpenSSL. This is a tougher sell for most programming languages–and, at minimum, requires a major version bump.

Both paths are valid. Improve or replace.

But what’s not valid is pointlessly and needlessly shit-slinging open source projects that you’re not willing to help. So I refuse to do that.

Anyone who thinks that makes me less of a cryptography expert should feel welcome to not just unfollow me on social media, but to block on their way out.

By Soatok

Security engineer with a fursona. Ask me about dholes or Diffie-Hellman!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s