Compromise of 2FA secrets through read-only SQLi – (iThemes Security <= 8.1.2)

Affected pluginiThemes Security
Active installs1+ million
Vulnerable version<= 8.1.2
Audited version8.1.2
Fully patched version
Recommended remediationRemoval of the plugin


The plugin stores users’ TOTP secrets in plaintext in the database.
An attacker that can obtain one of the seemingly never-ending read-only SQL-Injections will be able to bypass all 2FA checks for all users indefinitely.

Proof of concept

A look into the Two_Factor_Totp::validate_2fa() method quickly proves that TOTP secrets are stored in plaintext in the database:

* Validates authentication.
* @param WP_User $user WP_User object of the logged-in user.
* @return bool Whether the user gave a valid code
public function validate_authentication( $user ) {
	$key = get_user_meta( $user->ID, self::SECRET_META_KEY, true );

	return $this->_is_valid_authcode( $key, trim( $_REQUEST['authcode'] ) );

An attacker can use a read-only SQLi to bypass all 2FA checks for all users indefinitely.

SELECT user_id, meta_value FROM wp_usermeta WHERE meta_key = '_two_factor_totp_key'


Vendor contactedSeptember 07, 2022
First Response (from a developer)
Fully patched at
Publicly disclosedApril 24, 2023


  • The vendor made us send the POC through third-party chat software to support staff despite asking explicitly for a security@ email.

Leave a Reply

Your email address will not be published. Required fields are marked *