Cet article de blog explique comment prévenir efficacement les attaques de contournement d'OTP (One-Time Password), en se concentrant sur Node.js et React.js, mais applicable à d'autres technologies. Il détaille les techniques et les bonnes pratiques pour sécuriser la mise en œuvre de votre OTP.
Comprendre les attaques de contournement OTP
Le contournement OTP exploite les vulnérabilités des applications pour obtenir un accès non autorisé sans OTP valide. Les attaquants peuvent utiliser des OTP invalides ou expirés, ou manipuler les réponses de l'API (souvent à l'aide d'outils tels que Burp Suite) pour contourner la vérification OTP. Une attaque courante consiste à intercepter une réponse valide d'un utilisateur légitime et à la réutiliser pour un accès non autorisé.
Prévenir la manipulation des réponses
Le simple chiffrement des réponses de l'API n'est pas suffisant. Alors que le chiffrement (à l'aide d'AES ou RSA) protège les données en transit, des réponses identiques pour tous les utilisateurs créent une vulnérabilité. Même avec le cryptage, si les critères de réussite/échec sont basés uniquement sur le code d'état HTTP ou sur un message de réussite cohérent (« OTP vérifié avec succès »), un attaquant peut toujours contourner la vérification OTP en rejouant une réponse réussie capturée.
Une solution robuste : des identifiants de réponse uniques
La solution consiste à générer un identifiant unique par utilisateur pour chaque demande. Cela empêche les attaques par réexécution de réponse. La méthode décrite évite l'utilisation de la base de données :
Implémentation côté client (exemple React.js) :
rsid
). Vous pouvez utiliser n'importe quelle méthode de génération d'ID aléatoire appropriée.rsid
dans l'en-tête de la demande.rsid
au serveur.rsid
reçu dans la réponse avec celui envoyé dans l'en-tête de la demande. Une correspondance indique une vérification réussie ; une disparité signifie une tentative d'attaque.<code class="language-javascript">const OnSubmit = async () => { let data = await AesEncrypt(form); let verifyobj = { "encdata": data }; let getid = await makeid(7); let config = { headers: { "rsid": getid } }; let ApiCallverify = await axios.post("http://localhost:4000/api/verifyotp", verifyobj, config); let decryptedData = await Aesdecrypt(ApiCallverify.data.dataenc); if (ApiCallverify && ApiCallverify.data.dataenc && ApiCallverify.status === 200) { if (decryptedData.rsid === getid) { alert(decryptedData.message); } else { alert("Invalid User"); } } else { alert(decryptedData.message); } };</code>
Implémentation côté serveur (exemple Node.js) :
rsid
.rsid
original de l'en-tête de la demande.<code class="language-javascript">const OnSubmit = async () => { let data = await AesEncrypt(form); let verifyobj = { "encdata": data }; let getid = await makeid(7); let config = { headers: { "rsid": getid } }; let ApiCallverify = await axios.post("http://localhost:4000/api/verifyotp", verifyobj, config); let decryptedData = await Aesdecrypt(ApiCallverify.data.dataenc); if (ApiCallverify && ApiCallverify.data.dataenc && ApiCallverify.status === 200) { if (decryptedData.rsid === getid) { alert(decryptedData.message); } else { alert("Invalid User"); } } else { alert(decryptedData.message); } };</code>
Efficacité démontrée : L'article de blog comprend des captures d'écran montrant les connexions réussies et les tentatives infructueuses d'utilisation de Burp Suite pour intercepter et modifier les réponses. L'unique rsid
empêche les attaques par rejeu réussies.
Les images restent dans leurs positions d'origine. Notez que les URL des images sont conservées. Pour les afficher correctement, un système doit pouvoir accéder à ces URL.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!