Software Security

EduTech Spyware is Still Spyware: Proctorio Edition

Spyware written for educational institutions to flex their muscles of control over students and their families when learning from their home computer is still, categorically, spyware.

Depending on your persuasion, the previous sentence sounds like either needless pedantry, or it reads like tautology. But we need to be clear on our terms.

  1. Educational spyware is still spyware.
  2. Spyware is categorized as a subset of malware.

When vulnerabilities are discovered in malware, the normal rules of coordinated disclosure are out of scope. Are we clear?

(Art by Khia.)

So let’s talk about Proctorio!

The entire thread is unrolled here.

I won’t go into the details of Proctorio or why it’s terrible for (especially disadvantaged) students. Read Cassie’s Twitter thread for more context on that. Seriously. I’m not gonna be one of those guys that talks over women, and neither should you.

What I am here to talk about today is these dubious claim about the security of their product:

From their Data Security page.

Zero-Knowledge Encryption? OMGWTFBBQ!

In cryptography, there are a class of algorithms called Zero-Knowledge Proofs. In a Zero-Knowledge Proof, you prove that you possess some fact without revealing any details about the fact.

It’s kind of abstract to think about (and until we’re ready to talk about Pedersen commitments, I’m just going to defer to Sarah Jamie Lewis), but the only thing you need to know about “Zero Knowledge” in Cryptography is that the output is a boolean (True, False).

You can’t use “Zero Knowledge” anything to encrypt. So “Zero-Knowledge Encryption” is a meaningless buzzword.

So what are they actually describing when they say Zero Knowledge Encryption?

Also from their Data Security page.

Okay, so they’ve built their own key distribution system and are encrypting with AES-GCM… and shipped this in a Chrome extension. But before we get to that, look at this Daily Vulnerability Tests claim.


Running Nessus (or equivalent) on a cron job isn’t meaningful metric of security. At best, it creates alert fatigue when you accidentally screw up a deployment configuration or forget to update your software for 4+ years. (Y’know, like JsZip 3.2.1, which they bundle.)

A dumb vulnerability scan isn’t the same thing as a routine (usually quarterly) penetration test or a code audit. And if you’re working in cryptography, you better have both!

Timing Leaks in Proctorio’s AES-GCM Implementation

If you download version 1.4.20241.1.0 of the Proctorio Chrome Extension, run src/assets/J5HG.js through a JS beautifier, and then look at its contents, you will quickly realize this is a JavaScript cryptography library.

Since the “zero knowledge” encryption they’re so proud about uses AES-GCM, let’s focus on that.

Proctorio’s AES-GCM implementation exists in an object called dhs.mode.gcm, which is mildly obfuscated, but contains the following functions:

  • encrypt() – Encrypt with AES-GCM
  • decrypt() – Decrypt with AES-GCM
  • aa() – GHASH block multiplication
  • j() – XOR + GMAC utility function
  • O() – Called by encrypt() and decrypt(); does all of the AES-CTR + GMAC fun

If you’re not familiar with AES-GCM, just know this: Timing leaks can be used to leak your GMAC key to outside applications, which completely breaks the authentication of AES-GCM and opens the door to chosen-ciphertext attacks.

So is their implementation of AES-GCM constant-time? Let’s take a look at aa():

aa: function(a, b) {
  var c, d, e, f, g, h =;
  for (e = [0, 0, 0, 0], f = b.slice(0), c = 0; 128 > c; c++) {
    for (
      (d = 0 !== (a[Math.floor(c / 32)] & 1 << 31 - c % 32)) && (e = h(e, f)),
        g = 0 !== (1 & f[3]),
        d = 3;
      d > 0;
      f[d] = f[d] >>> 1 | (1 & f[d - 1]) << 31;
    f[0] >>>= 1,
    g && (f[0] ^= -520093696)
  return e

This is a bit obtuse, but this line leaks the lowest bit of f with each iteration: g = 0 !== (1 & f[3]).

Since f gets bitwise right-shifted 128 times, this actually leaks the bit of every value of f in each block multiplication, since the execution of (f[0] ^= -520093696) depends on whether or not g is set to true.

Timing leaks? So much for “zero-knowledge”!

Also, they claim to be FIPS 140-2 compliant, but this is how they generate randomness in their cryptography library.

(Although, that’s probably a lie.)

To mitigate these vulnerabilities, one needs look no further than the guide to side-channel attacks I published last month.

(Also, use WebCrypto to generate entropy! What the fuck.)

If Proctorio is Insecure, What Should We Use Instead?


Schools that demand students install spyware on their personal computers are only a step removed from domestic abusers who install stalkerware on their victims’ phones.

Proctorio isn’t the problem here, they’re only a symptom.

Schools that insist on violating the integrity and parental dominion of their students’ home computers are the problem here.


If you want to ensure the integrity of students’ education, try teaching them about consent and ethical computing. (Y’know, concepts that are fundamentally incompatible with the business model of Proctorio and Proctorio’s competitors.)

Disclosure Timeline

Really? Really?

This was a zero-day disclosure, because full disclosure is the responsible choice when dealing with spyware. Don’t even @ me.

Disclaimer: This security research was conducted by Soatok– some furry on the Internet–while bored on his off-time and does not reflect the opinions of any company.

Domains to Sinkhole

If you’re looking to protect your home network from this spyware, here are a list of domains to sinkhole (i.e. with Pi-Hole).


Update (2020-09-16): AES in a Hole

I got curious about the security of how they were encrypting data, not just the authentication of that encrypted data.

After all, if Proctorio decided to home-bake GCM in an insecure way, it’s overwhelmingly likely that they rolled their own AES implementation too.

Interlude: Software AES

Implementing AES in software is terrifying. Even moreso in JavaScript, since your code might be secure in a Node.js environment but insecure in a web browser–or vice versa! And you have no way of knowing as a JavaScript developer because you can’t verify the interpreter.

At the risk of being slightly reductionist, Software AES can be implemented in roughly two ways:

  1. The insecure but fast way.
  2. The slow but secure way.

Option 1 means using table look-ups, which are fast, but vulnerable to cache-timing attacks.

Option 2 means using a bitsliced implementation, like BearSSL provides.

Naturally, Proctorio’s AES Implementation Went For Option 1

I’m beginning to think Proctorio’s use of “zero-knowledge” is nothing more than self-description. (Art by Khia.)

You can find their AES implementation in the dhs.cipher.aes and w functions in J5HG.js.

What Is the Risk to Students?

Cache-timing vulnerabilities are much more dangerous to students than the previously disclosed issue with GMAC.

That is to say: They cough up your encryption keys. Furthermore, these only took 65 milliseconds to exploit (on 2006 hardware, to boot).

Cache-timing leaks can be easily exploited from other processes running on the same computer as Proctorio. This includes JavaScript code running in another browser window or tab.

Successfully exploiting this vulnerability would net you the keys used by Proctorio to encrypt and authenticate data, and exploiting it would not require violating any of the operating system’s security boundaries. Just running exploit code on the same hardware.

Isn’t cryptography fun?

By Soatok

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

2 replies on “EduTech Spyware is Still Spyware: Proctorio Edition”

Leave a Reply

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

You are commenting using your 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