
Dès Changement de code nous avons mis en œuvre, chaque jour, des améliorations sur MYETV sécurité; le premier travail a été le service d'authentification expliqué dans le#sécurité chapitre et puis nous avons affiné les capacités des développeurs pour créer la sécurité exclusive pour notre site Web. Les développeurs ont fait une mise à jour chaque fois que nous avons trouvé une sorte de vulnérabilités; c'est extrêmement utile pour faire des corrections d'algorithme à la volée, c'est le moment de se concentrer sur la façon dont nous avons sécurisé les pages côté client qui doivent communiquer avec le côté serveur (comme les appels ajax et les mises à jour post/get). En fait, nous avons divisé les deux opérations : GET (données envoyées par des files de requête) et POST (données envoyées par un formulaire).
Dans le premier cas (GET), l'utilisateur doit suivre ces points pour demander avec succès la page:
- Authentifier (lorsque la demande est faite)
- Vérification d'en-tête pour être sûr qu'il est appelé uniquement via Javascript
- E/S enregistrer dans un endroit sécurisé du disque dur l'horodatage et les informations sur l'utilisateur, hashed avec SHA512; chaque fois qu'une page côté client est demandée le système peut compter la datetime et combien de fois la page est demandée dans une période spécifique de temps; vous pourriez être interdit temporairement si vous demandez la page trop de temps dans une période spécifiée de secondes
- Un jeton généralement envoyé par requêtestring et c'est le SHA1 ou SHA512 (dépend de la rapidité avec laquelle la requête doit être) hash de l'utilisateur
- Ce jeton doit correspondre à l'ID de session original de l'utilisateur, lorsque l'utilisateur fait une requête côté serveur
- Si le jeton correspond, alors vous pouvez faire une simple demande GET
En tant que requête GET, nous entendons toute requête qui ne touche pas les bases de données ou les E/S des disques durs et qui provient de requêtes.
Dans le deuxième cas (POST), l'utilisateur doit suivre ces points pour demander avec succès la page:
- Authentifier (lorsque la demande est faite)
- Vérification d'en-tête pour être sûr qu'il est appelé uniquement via Javascript
- E/S enregistrer dans un endroit sécurisé du disque dur l'horodatage et les informations sur l'utilisateur, hashed avec SHA512; chaque fois qu'une page côté client est demandée le système peut compter la datetime et combien de fois la page est demandée dans une période spécifique de temps; vous pourriez être interdit temporairement si vous demandez la page trop de temps dans une période spécifiée de secondes
- Un premier jeton habituellement envoyé par GET (querystring) et c'est le hachage SHA1 ou SHA512 de l'identifiant de session de l'utilisateur
- Un second jeton envoyé par POST (formulaire) et c'est la crypte aes256 du hachage avec SHA1 ou SHA512 (dépend de la rapidité avec laquelle la requête doit être) de l'utilisateur, plus des informations supplémentaires comme datetime et autres (crypté seulement avec aes256 et paquet avec toute la requête)
- Ces deux jetons doivent correspondre à l'ID de session original de l'utilisateur, et des informations supplémentaires sont déchiffrées
- Si le jeton correspond, alors vous pouvez faire une simple demande GET
- Avec la datetime précédemment cryptée, nous pouvons contrôler l'interaction des utilisateurs à chaque seconde et nous pouvons approuver ou non certaines actions en les limitant dans le temps
- Lorsque tout est déballé succès (jetons et informations supplémentaires), vous avez juste besoin de quelques secondes pour faire une demande normale côté serveur et alors cet accès sera obfusqué pour le futur
En tant que requête POST, nous entendons toute requête qui vient par un formulaire et/ou touche n'importe quelle base de données ou E/S des disques durs.
Vérification des en-têtes côté serveur :
//restreigne l'accès ajax seulement...
définir('IS_AJAX', isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH') == 'xmlhttprequest');
if(!IS_AJAX) {
die('Accès restreint');
}
$pos = strpos($_SERVER['HTTP_REFERERER'],getenv('HTTP_HOST'));
if($pos=false){
die('Accès restreint');
}Il s'agit d'un code côté serveur (PHP) vous donnera une idée de la manière dont les en-têtes sont vérifiés ; c'est une sécurité supplémentaire mais les en-têtes pourraient être spoofed facilement donc nous devons implémenter une autre couche de sécurité comme ci-dessous.
Vérification du disque dur E/S
// nombre de demandes de page autorisées pour l'utilisateur
définir("CONTROL_MAX_REQUESTSclientside", 1);
// intervalle de temps pour commencer à compter les requêtes de page (secondes)
définir("CONTROL_REQ_TIMEOUTside", 1);
// secondes pour punir l'utilisateur qui a dépassé les demandes
définir("CONTROL_BAN_TIMEclientside", 10);
// IP utilisateur
if(vide($_SERVER["REMOTE_ADDR"]):
définir("USER_IPclientside", désinfecterUSERIPclientside(hash('sha512','clientside'.session_id()));
Sinon:
définir("USER_IPclientside", désinfecterUSERIPclientside(hash('sha512', 'clientside'.$_SERVER["REMOTE_ADDR"]));
endif;
// répertoire en écriture pour conserver les données du script remplacer "[répertoire]" par un dossier sécurisé dans le disque dur
définir("SCRIPT_TMP_DIRclientside", "[répertoire]");
définir("CONTROL_DBclientside", "[répertoire2]");
définir("CONTROL_LOCK_DIRclientside", "[répertoire3]");
définir("CONTROL_LOCK_FILEclientside", "[répertoire4]".sanitizeUSERIPclientside(hash('sha512', USER_IPclientside));
@mkdir(côté clientCONTROL_LOCK_DIR);
@mkdir(côté client SCRIPT_TMP_DIR);
//afficher l'erreur si une erreur existe
si (file_exists(CONTROL_LOCK_FILEclientside)) {
si (time()-filemtime(CONTROL_LOCK_FILEclientside) > CONTROL_BAN_TIMEclientside) {
// cet utilisateur a terminé sa punition
unlink(CONTROL_LOCK_FILEclientside);
} autre {
// trop de requêtes
l'écho « Trop de demandes »;
contact(côté clientCONTROL_LOCK_FILE);
mourir;
}
}
fonction antiflood_countaccessCLIENTSIDE() {
// Requêtes de comptage et dernière heure d'accès
$control = Array();
si (file_exists(CONTROL_DBclientside)) {
$fh = fopen(CONTROL_DBclientside, "r");
$control = array_merge($control, (array)unserialize(fread($fh, filesize(CONTROL_DBclientside)));
fclose($fh);
}
Si (permis($control[USER_IPclientside])) {
Si (time()-$control[USER_IPclientside]["t"] < CONTROL_REQ_TIMEOUTclientside) {
$control[USER_IPclientside]["c"]++;
} autre {
$control[USER_IPclientside]["c"] = 1;
}
} autre {
$control[USER_IPclientside]["c"] = 1;
}
$control[USER_IPclientside]["t"] = time();
si (contrôle [du côté client de l'USER_IP]["c"] >= CONTRÔLE_MAX_REQUESTS côté client) {
// cet utilisateur a fait trop de requêtes dans un délai très court
$fh = fopen(CONTROL_LOCK_FILEclientside, "w");
fwrite($fh, côté client USER_IP);
fclose($fh);
}
// table de contrôle à jour
$fh = fopen(CONTROL_DBclientside, "w");
fwrite($fh, serialize($control));
fclose($fh);
}
//sanitiser IP utilisateur ou sessionID pour le nom du fichier à écrire sur disque
désinfecter la fonction Côté client de l'utilisateur($theuserIP) {
//sanitiser l'identifiant d'utilisation ou de session
$userIP = str_replace(array('[\', \']'), '', $theuserIP);
$userIP = preg_replace('/\[.*\]/U', '', $userIP);
$userIP = preg_replace('/&(amp;)?#?[a-z0-9]+;/i', '-', $userIP);
$userIP = htmlentities($userIP, ENT_COMPAT, 'utf-8');
$userIP = preg_replace('/&([a-z])(acute="uml="circ="grave="gredil="slash="tilde="caron="lig="quot="rsquo);/i', '\\1', $userIP );
la valeur de la valeur de référence de l'élément d'actif,
retourner strtolower(trim($userIP, '-'));
}c'est un code d'algorithme côté serveur (PHP) et écrira dans un endroit sécurisé des disques durs le nombre de fois que la requête est envoyée, l'horodatage et certaines informations uniques de cette requête hashed avec SHA512 (comme le nom du fichier); lorsque le nombre de fois dépassé ou l'horodatage est différent de celui spécifié, la requête échouera du tout et une erreur est affichée. Cet algorithme est un peu compliqué et fonctionne seul, avec le nombre donné de secondes et les bons dossiers sur le disque dur, sans aucune intervention humaine.
Authentification des jetons
$token1 = urlencode(sha1(session_id())); //avec AES256 CRYPT $token2 = AES256CRYPT(sha1(session_id()),"[initialvectorkey]"); //SANS AES 256 CRYPT //$token2 = sha1(session_id());
nous définissons la valeur des jetons dans l'exemple ci-dessus.
