Maison  >  Article  >  développement back-end  >  Le formulaire PHP empêche les soumissions répétées (vulnérabilité anti-csrf)

Le formulaire PHP empêche les soumissions répétées (vulnérabilité anti-csrf)

不言
不言original
2018-04-20 11:44:013743parcourir

Le contenu de cet article vise à empêcher la soumission répétée de formulaires PHP (en évitant les vulnérabilités CSRF). Il a une certaine valeur de référence. Maintenant, je le partage avec vous. Les amis dans le besoin peuvent s'y référer

Jeton Une brève discussion <span style="margin:0px;padding:0px;"></span>

Le jeton est un jeton. Sa plus grande caractéristique est le caractère aléatoire et l'imprévisibilité. Les pirates informatiques ou logiciels normaux ne peuvent pas le deviner.

Alors, quelle est la fonction du Token ? Quel est le principe ?

Le jeton est généralement utilisé à deux endroits : pour empêcher les soumissions répétées de formulaires et les attaques anti-csrf (falsification de requêtes intersites).

Les deux sont en principe implémentés via des jetons de session. Lorsque le client demande une page, le serveur génère un jeton à nombre aléatoire, place le jeton dans la session, puis envoie le jeton au client (généralement en construisant un formulaire caché). La prochaine fois que le client soumettra une demande, le jeton sera soumis au serveur avec le formulaire.

Ensuite, s'il est appliqué à une "attaque anti-csrf", le serveur vérifiera la valeur du jeton pour déterminer si elle est égale à la valeur du jeton dans la session. Si elle est égale, la requête peut. être prouvé valide, pas faux.

Cependant, s'il est utilisé pour "empêcher la soumission répétée de formulaires", après la première vérification de celui-ci côté serveur, la valeur du jeton dans la session sera mise à jour si. l'utilisateur soumet à plusieurs reprises, le jugement de vérification secondaire échouera car le jeton dans le formulaire soumis par l'utilisateur n'a pas changé, mais le jeton dans la session côté serveur a changé.

L'application de session ci-dessus est relativement sûre, mais elle est également fastidieuse, lorsqu'il y a plusieurs pages et plusieurs requêtes, la méthode de génération de plusieurs jetons en même temps. doit être utilisé, ce qui consomme plus de ressources et réduit l’efficacité de l’exécution. Par conséquent, la méthode de stockage des informations de vérification dans les cookies peut également être utilisée à la place du jeton de session. Par exemple, lorsqu'il s'agit de « soumissions répétées », les informations soumises seront écrites dans le cookie après la première soumission. Lors de la deuxième soumission, puisque le cookie a déjà un enregistrement de soumission, la deuxième soumission échouera.

Cependant, le stockage des cookies présente une faiblesse fatale. Si le cookie est piraté (les attaques XSS peuvent facilement obtenir les cookies des utilisateurs), il y aura alors une autre partie. Les pirates mettront directement en œuvre les attaques CSRF.

1. Empêchez d'abord les attaques XSS

2. Vérifiez le référent

3. Les paramètres de cookies importants sont uniquement https, tels que le jeton

4 . Utilisez Signature, jeton

5. get n'est utilisé que pour interroger des informations

6. Utilisez post pour soumettre le formulaire

7. . Utilisez le texte croisé avec prudence Injection de script

La sécurité et l'efficacité sont donc relatives. Examinons en détail des problèmes spécifiques.


Ajouter un Token au formulaire php pour éviter les soumissions répétées

Le principe est de générer un aléatoire chaîne et mettez-la dans la session Ici, vérifier cette chaîne après avoir soumis le formulaire peut empêcher d'autres personnes d'écrire le formulaire eux-mêmes pour tromper la soumission, répéter la soumission ou double-cliquer sur la soumission.

Le code simple implémenté en php est le suivant :


<?php
/*
* PHP简单利用token防止表单重复提交
* 此处理方法纯粹是为了给初学者参考
*/
session_start();
function set_token() {
  $_SESSION[&#39;token&#39;] = md5(microtime(true));
}
function valid_token() {
  $return = $_REQUEST[&#39;token&#39;] === $_SESSION[&#39;token&#39;] ? true : false;
  set_token();
  return $return;
}
//如果token为空则生成一个token
if(!isset($_SESSION[&#39;token&#39;]) || $_SESSION[&#39;token&#39;]==&#39;&#39;) {
  set_token();
}
if(isset($_POST[&#39;test&#39;])){
  if(!valid_token()){
    echo "token error";
  }else{
    echo &#39;成功提交,Value:&#39;.$_POST[&#39;test&#39;];
  }
}
?>
<form method="post" action="">
  <input type="hidden" name="token" value="<?php echo $_SESSION[&#39;token&#39;]?>">
  <input type="text" name="test" value="Default">
  <input type="submit" value="提交" />
</form>

<span style="margin:0px;padding:0px;"></span>

上面的比较简单一点的方法,下面的代码更加安全一点。

Token.php


<?php
/*
 * Created on 2013-3-25
 *
 * To change the template for this generated file go to
 * Window - Preferences - PHPeclipse - PHP - Code Templates
 */
function getToken($len = 32, $md5 = true) {
  # Seed random number generator
  # Only needed for PHP versions prior to 4.2
  mt_srand((double) microtime() * 1000000);
  # Array of characters, adjust as desired
  $chars = array (
    &#39;Q&#39;,
    &#39;@&#39;,
    &#39;8&#39;,
    &#39;y&#39;,
    &#39;%&#39;,
    &#39;^&#39;,
    &#39;5&#39;,
    &#39;Z&#39;,
    &#39;(&#39;,
    &#39;G&#39;,
    &#39;_&#39;,
    &#39;O&#39;,
    &#39;`&#39;,
    &#39;S&#39;,
    &#39;-&#39;,
    &#39;N&#39;,
    &#39;<&#39;,
    &#39;D&#39;,
    &#39;{&#39;,
    &#39;}&#39;,
    &#39;[&#39;,
    &#39;]&#39;,
    &#39;h&#39;,
    &#39;;&#39;,
    &#39;W&#39;,
    &#39;.&#39;,
    &#39;/&#39;,
    &#39;|&#39;,
    &#39;:&#39;,
    &#39;1&#39;,
    &#39;E&#39;,
    &#39;L&#39;,
    &#39;4&#39;,
    &#39;&&#39;,
    &#39;6&#39;,
    &#39;7&#39;,
    &#39;#&#39;,
    &#39;9&#39;,
    &#39;a&#39;,
    &#39;A&#39;,
    &#39;b&#39;,
    &#39;B&#39;,
    &#39;~&#39;,
    &#39;C&#39;,
    &#39;d&#39;,
    &#39;>&#39;,
    &#39;e&#39;,
    &#39;2&#39;,
    &#39;f&#39;,
    &#39;P&#39;,
    &#39;g&#39;,
    &#39;)&#39;,
    &#39;?&#39;,
    &#39;H&#39;,
    &#39;i&#39;,
    &#39;X&#39;,
    &#39;U&#39;,
    &#39;J&#39;,
    &#39;k&#39;,
    &#39;r&#39;,
    &#39;l&#39;,
    &#39;3&#39;,
    &#39;t&#39;,
    &#39;M&#39;,
    &#39;n&#39;,
    &#39;=&#39;,
    &#39;o&#39;,
    &#39;+&#39;,
    &#39;p&#39;,
    &#39;F&#39;,
    &#39;q&#39;,
    &#39;!&#39;,
    &#39;K&#39;,
    &#39;R&#39;,
    &#39;s&#39;,
    &#39;c&#39;,
    &#39;m&#39;,
    &#39;T&#39;,
    &#39;v&#39;,
    &#39;j&#39;,
    &#39;u&#39;,
    &#39;V&#39;,
    &#39;w&#39;,
    &#39;,&#39;,
    &#39;x&#39;,
    &#39;I&#39;,
    &#39;$&#39;,
    &#39;Y&#39;,
    &#39;z&#39;,
    &#39;*&#39;
  );
  # Array indice friendly number of chars;
  $numChars = count($chars) - 1;
  $token = &#39;&#39;;
  # Create random token at the specified length
  for ($i = 0; $i < $len; $i++)
    $token .= $chars[mt_rand(0, $numChars)];
  # Should token be run through md5?
  if ($md5) {
    # Number of 32 char chunks
    $chunks = ceil(strlen($token) / 32);
    $md5token = &#39;&#39;;
    # Run each chunk through md5
    for ($i = 1; $i <= $chunks; $i++)
      $md5token .= md5(substr($token, $i * 32 - 32, 32));
    # Trim the token
    $token = substr($md5token, 0, $len);
  }
  return $token;
}
?>

<span style="margin:0px;padding:0px;"></span>

<?php
include_once("token.php");
$token = getToken();
session_start();
$_SESSION[&#39;token&#39;] = $token;
?>
<form action="action.php" method="post"
<input type="hidden" name="token" value="<?=$token?>" />
<!-- 其他input submit之类的 -->
</form>

<span style="margin:0px;padding:0px;"><p style="margin-bottom:0px;clear:both;min-height:1em;color:rgb(62,62,62);font-family:'Helvetica Neue', Helvetica, 'Hiragino Sans GB', 'Microsoft YaHei', Arial, sans-serif;line-height:25.6px;background-color:rgb(255,255,255);"></p></span>


<?php
session_start();
if($_POST[&#39;token&#39;] == $_SESSION[&#39;token&#39;]){
  unset($_SESSION[&#39;token&#39;]);
  echo "这是一个正常的提交请求";
}else{
  echo "这是一个非法的提交请求";
}
?>

<span style="margin:0px;padding:0px;"></span>

form.php

<span style="margin:0px;padding:0px;"></span>


action.php


<span style="margin:0px;padding:0px;"></span>

<span style="margin:0px;padding:0px;"></span>

Recommandations associées :

Le problème de l'utilisation de variables pour représenter la valeur du nom du formulaire PHP

Explication détaillée de l'exemple de téléchargement asynchrone iframe de fichier de formulaire php



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!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn