Wordfence Has Been Selling Info on Unfixed Vulnerability That Allows Website Takeover to Hackers for a Month
The WordPress security provider Wordfence makes a big deal about doing responsible disclosure of vulnerabilities, despite not doing that. Responsible disclosure involves notifying the developer first and giving them a chance to address the vulnerability, before notifying anyone else. In Wordfence’s disclosure policy, they claim to do responsible disclosure and then go on to say they will sell information about the vulnerabilities to those using their Wordfence Premium service in the form of firewall rules before even notifying the developer. That policy also obliquely acknowledges that those firewall rules could be misused:
Where possible, we develop a firewall rule to protect our customers. This rule is obfuscated to prevent reverse engineering.
You wouldn’t need to obfuscate the rules to prevent reverse engineering if the rules are harmless. As we have noted in the past, the obfuscation they use doesn’t actually prevent reverse engineering, which if they really have the security experts on staff that they claim to, they would know. But they often are not even doing that obfuscation.
Wordfence has now been selling information on two undisclosed unfixed vulnerabilities in the plugin Directorist for a month to any hacker willing to pay for their Wordfence Premium service. That plugin has 10,000+ installs according to WordPress. The more serious vulnerability allows an attacker with access to an account on the website to change any other user’s password as long as they know the email address associated with the account. The plugin allows anyone to create an account on the website. So an attacker who knows an Administrator’s email address could take control of their account and therefore website.
As the rules is now in Wordfence’s free data (as rules are made to non-paying customers after a month), even hackers not paying them have access to the information.
Wordfence’s customers have been partially protected from this, but others have not. So we want to get the word out not just to our customers, but to everyone else as well.
Privilege Escalation
Here is the rule for the more serious vulnerability:
if (versionLessThanEqualTo('7.5.2', wordpress.plugins['directorist']) and keyExists('directorist_reset_password', request.body)): block(id=576, category='priv-esc', score=100, description='WAF-RULE-576', whitelist=0)
There is no obfuscation of the rule, contrary to Wordfence’s claim.
What that says is that in versions of the plugin Directorist less than or equal to version 7.5.2 there is a privilege escalation vulnerability involving user input with the name directorist_reset_password.
If you search the files for version 7.5.2 of the plugin for usage of directorist_reset_password, you find that it is used in the file /templates/account/login.php. It is used in this code that allows resetting an arbitrary WordPress user’s password as long as you know the email address associated with the account:
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | $recovery = isset( $_GET['user'] ) ? sanitize_email( wp_unslash( $_GET['user'] ) ) : ''; $key = isset( $_GET['key'] ) ? $_GET['key'] : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- ignore password sanitization if ( ! empty( $recovery ) ) : $user = get_user_by( 'email', $recovery ); if ( ! empty( $_POST['directorist_reset_password'] ) && directorist_verify_nonce( 'directorist-reset-password-nonce', 'reset_password' ) ) : // Ignore password sanitization $password_1 = isset( $_POST['password_1'] ) ? $_POST['password_1'] : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized $password_2 = isset( $_POST['password_2'] ) ? $_POST['password_2'] : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized if ( ( $password_1 === $password_2 ) && ! empty( $password_1 && $password_2 ) ) : $update_user = wp_update_user( [ 'ID' => $user->ID, 'user_pass' => $password_2, ] ); |
The only restriction on that is that you have to have a valid nonce. That can be obtained by anyone with access to a WordPress account, by requesting that their own password be reset through the plugin.
The Vulnerability Still Exists
The rule only applies if a version of Directorist up to 7.5.2 are in use, but the vulnerability has not been fixed in the two subsequent versions of the plugin. In fact, there hasn’t even been an attempt to fix the vulnerability (or the other vulnerability Wordfence has been selling information about). Presumably, this would mean the Wordfence’s own paying customers are not protected if they are using a newer version of the plugin.
We have reached out to the developer to let them know about this and offered to help them fix the vulnerabilities, though, presumably Wordfence had been in touch with them already.