I have added a function to my WordPress site to modify the login page by including a custom field. This field is intended to require users to enter a specific value in addition to their username and password. However, the custom field is not functioning as expected.
When users submit the login form, they can input any value in the custom field, and the login process does not validate this input against the expected value stored in the option portal_access_code
. As a result, users can log in as long as they provide a valid username and password, regardless of the value they enter in the security code field.
I have checked the implementation using error_log and confirmed that it logs both the actual value of the option set ('portal_access_code')
and the value entered by the user. However, the login process allows users to authenticate without validating the custom field, bypassing the intended check. It’s as if the login mechanism is running before the custom validation takes place, so users can log in without error, even if their input does not match the expected value. I think this happens after WordPress has already authenticated the user based on the username and password.
When any user trying to login, this code log both codes (code that stored in database, and code that user entered) on error_log
file:
[31-Aug-2024 08:13:05 UTC] Portal Access Code: NTM-81641992@BRHPUL-nu581p
[31-Aug-2024 08:13:05 UTC] Submitted Security Code: 1234
So the actual code in the database is NTM-81641992@BRHPUL-nu581p
(it’s generating automatically with another function) but users can bypass it by entering any value into the login field!
<?php
// Add the security code field to the login form
add_action('login_form', 'add_security_code_field_ntm');
function add_security_code_field_ntm() {
echo '<p>
<label for="security_code">'.__('Security Code').'<br />
<input type="text" name="security_code" id="security_code" class="input" value="" size="100" required /></label> <!-- Added required attribute -->
</p>
<script>
document.getElementById("loginform").onsubmit = function() {
var securityCode = document.getElementById("security_code").value;
if (securityCode === "") {
alert("Please enter the Security Code field"); // Alert message for the empty field
return false; // Prevent form submission
}
return true; // Allow form submission
}
</script>';
}
// Validate the security code
add_filter('authenticate', 'validate_security_code_ntm', 30, 3);
function validate_security_code_ntm($user, $username, $password) {
// Check if the login form was submitted with a security code
if (isset($_POST['security_code'])) {
$portal_access_code = get_option('portal_access_code', 'error_code');
$security_code = sanitize_text_field($_POST['security_code']);
error_log("Portal Access Code: " . $portal_access_code);
error_log("Submitted Security Code: " . $security_code);
// Compare with the stored access code
if (empty($security_code)) {
return new WP_Error('empty_security_code', __('Please Enter the Security Code.'));
}
if ($security_code !== $portal_access_code) {
return new WP_Error('invalid_security_code', __('Security Code is not correct!'));
}
}
return $user; // Return the user object if there are no errors
}
// Restrict login methods except wp-login.php
add_action('init', 'restrict_login_methods_ntm');
function restrict_login_methods_ntm() {
if (is_user_logged_in() || !isset($_REQUEST['log'])) {
return;
}
$request_uri = $_SERVER['REQUEST_URI'];
if (!preg_match('/wp-login.php/', $request_uri)) {
wp_die('You should use normal way to login to admin panel!');
}
add_filter('xmlrpc_enabled', '__return_false');
}