Aller au contenu principal

Authentication

Epirootkit uses SHA-256 password hashing with constant-time comparison to authenticate access, both locally and remotely.

Password Flow

The password is never stored in plain text inside the kernel module. Here's how it flows from installation to authentication:

  1. At install time: the install.sh script takes a plain-text password, hashes it with SHA-256, and passes the hash as a module parameter.
    password_hash=$(echo -n "$password" | sha256sum | cut -d' ' -f1)
    insmod epirootkit.ko password_hash="$password_hash" ...
  2. At runtime: the hash is stored in the password_hash kernel parameter (read-only, permission 0400).
  3. On authentication: the operator provides the password (in the browser UI). The C2 server hashes the password with SHA-256 and forwards the 64-character hex digest to the module for verification. The module compares the received 64-char hex string against the stored password_hash.
info

For local escalation via /proc/epirootkit, the user must write the SHA-256 hash directly (64 hex characters). For remote authentication via C2, the server hashes the operator's plain-text password with SHA-256 and sends the 64-character hex digest to the module for comparison.

Constant-Time Comparison

The password check uses a custom ct_strcmp function instead of standard strcmp or memcmp. This is a security measure against timing attacks.

A standard string comparison returns as soon as it finds a mismatched character. An attacker could measure response times to determine how many characters of their guess are correct. The constant-time function always compares all 64 characters regardless of where a mismatch occurs:

static int ct_strcmp(const char *a, const char *b, size_t len) {
volatile int diff = 0;
for (size_t i = 0; i < len; i++) {
diff |= a[i] ^ b[i];
}
return diff;
}

Key properties:

  • Uses XOR (^) and OR (|=) to accumulate differences without short-circuiting.
  • The volatile qualifier prevents the compiler from optimizing the loop away.
  • Returns 0 only if all bytes are identical.

Validation Rules

The check_password() function enforces these checks before comparing:

  1. The input must not be NULL.
  2. The input length must be exactly 64 characters (the length of a SHA-256 hex digest).
  3. If both checks pass, the constant-time comparison is performed.

Any failure results in AUTH_FAILED being returned.