Précédent   Forum des professionnels en informatique > PHP > Langage
Langage Forum sur le langage PHP, la POO, les conventions, la sécurité, etc. Avant de poster : FAQ Langage, toutes les FAQ PHP, cours langage et sources PHP
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 16/09/2011, 11h55   #1
Invité de passage
 
Inscription : juin 2011
Messages : 7
Détails du profil
Informations forums :
Inscription : juin 2011
Messages : 7
Points : 0
Points : 0
Par défaut limiter un vote en fonction de l'IP

Bonjour; j'ai réalisé un petit concours où il est possible de voter pour son image préférée.
Mon script vérifie l'IP du votant et ne permet qu'un vote par photo et par IP (mais une même IP peut voter pour plusieurs photos différentes).

Le problème : en examinant mes tables; je remarque qu'il y a PLEIN d'entrées ou une même IP a voté plusieurs fois pour une même photo; généralement à quelques secondes d'intervalles.

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1066 	104 	2147483476 	2011-09-16 10:14:43
1065 	104 	2147483476 	2011-09-16 10:14:40
1064 	104 	2147483476 	2011-09-16 10:14:36
1063 	104 	2147483476 	2011-09-16 10:14:33
1062 	104 	2147483476 	2011-09-16 10:14:30
1061 	104 	2147483476 	2011-09-16 10:14:27
1060 	104 	2147483476 	2011-09-16 10:14:23
1059 	104 	2147483476 	2011-09-16 10:14:16
1058 	104 	2147483476 	2011-09-16 10:14:12
1057 	104 	2147483476 	2011-09-16 10:14:09
1056 	104 	2147483476 	2011-09-16 10:14:03
1055 	104 	2147483476 	2011-09-16 10:14:00
1054 	104 	2147483476 	2011-09-16 10:13:57
1053 	104 	2147483476 	2011-09-16 10:13:54
1052 	104 	2147483476 	2011-09-16 10:13:50
1051 	104 	2147483476 	2011-09-16 10:13:47
J'ai testé mon script; quand j'essaie moi-même il ne me permet pas le vote avec la même IP...

J'ai pensé que ces votants utilisaient qqch (proxy ou autre) pour "faker" leur IP; mais ça n'a pas l'air d'être cela puique l'IP sauvegardée dans la table et l'IP comparée dans la table (pour vérifier la possibilité de voter) sont la même.

Je ne sais vraiment pas quoi penser, en toute logique je vois pas du tout la faille de mon script... Mais on dirait bien qu'il y en ait une.
Quelqu'un aurait l'aimabilité de regarder mon code ?
Merci !

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
##VOTE
 
 
$sent=$_POST;
 
 
		case 'vote_picture';
			$ip = get_user_ip(); //get user IP
			$result->msg="Une erreur est survenue lors du vote"; //default error msg
 
			if ($sent['img_id']){ //vote for img_ID
 
 
				//check if a vote already exists with this IP for this picture
				$v_exists = $db->dcount("id", "img_vote", "img_id={$sent['img_id']} AND ip={$ip}");
 
				if ($v_exists) { //do not save vote
					$result->success=true;
				}else{ //save vote
					$sql_vote = "INSERT INTO img_vote (img_id,ip,time) VALUES ('{$sent['img_id']}','{$ip}',NOW())";
					$sql_vote_result = $db->query($sql_vote);
 
					$sql_img = "UPDATE img_upload SET rating=rating+1 WHERE id={$sent['img_id']}";
					$sql_result = $db->query($sql_img);
 
					if ($sql_result) {
						$new_rating = $db->dlookup("rating", "img_upload", "id={$sent['img_id']}");
						$result->rating=$new_rating;
						$result->success=true;
					}
 
				}
 
			}
			echo json_encode($result);
		break;
 
 
##GET IP
 
function get_user_ip() {
	$ip  = $_SERVER['REMOTE_ADDR']; 
	$dotted  = preg_split( "/[.]+/", $ip);
	$ip2 = (double) ($dotted[0]*16777216)+($dotted[1]*65536)+($dotted[2]*256)+($dotted[3]);
 
	return $ip2;
}
grosbouff est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/09/2011, 14h54   #2
Membre confirmé
 
Homme Dominique
Première S
Inscription : juillet 2010
Messages : 252
Détails du profil
Informations personnelles :
Nom : Homme Dominique
Âge : 15
Localisation : France

Informations professionnelles :
Activité : Première S

Informations forums :
Inscription : juillet 2010
Messages : 252
Points : 228
Points : 228
c'est étonnant ... même en ouvrant d'un coup plein d'onglet, ça ne devrait pas le faire ... pour le code, je ne connais pas la méthode utilisée, si tu essayais avec une requête normale ?
Code :
1
2
 
SELECT COUNT(*) FROM table WHERE ip = ip AND photo=photo
je serais de toi, je mettrait le binôme ip-photo en champs unique, come ça, c'est MySQL qui va lever une exception, et les petits malins en seront pour leur frais
Dominique49 est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 20/09/2011, 15h00   #3
Membre chevronné
 
Avatar de Marc3001
 
Homme
Ingénieur développement logiciels
Inscription : février 2008
Messages : 430
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 28
Localisation : France, Ille et Vilaine (Bretagne)

Informations professionnelles :
Activité : Ingénieur développement logiciels

Informations forums :
Inscription : février 2008
Messages : 430
Points : 682
Points : 682
Il faut que tu protèges tes variables récupérées par post car tu utilises dans ta requête ce filtre qui est facilement crackable par injection sql :
Code :
img_id={$sent['img_id']} AND ip={$ip}
__________________
Le logiciel, c'est comme le sexe, c'est meilleur quand c'est libre.

Linus Torvalds
Marc3001 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/09/2011, 15h21   #4
Invité de passage
 
Inscription : juin 2011
Messages : 7
Détails du profil
Informations forums :
Inscription : juin 2011
Messages : 7
Points : 0
Points : 0
Citation:
Envoyé par Marc3001 Voir le message
Il faut que tu protèges tes variables récupérées par post car tu utilises dans ta requête ce filtre qui est facilement crackable par injection sql :
Code :
img_id={$sent['img_id']} AND ip={$ip}
Bonjour, peux-tu m'en dire plus ?
Je dois donc juste vérifier que $sent['img_id'] et $ip sont des "numbers" ?
genre
Code :
if(!is_number($img_id)) $img_id=false;
Ou bien il y a quelque chose de plus "standardisé" pour ça ?

Merci
grosbouff est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/09/2011, 16h20   #5
Membre confirmé
 
Homme Dominique
Première S
Inscription : juillet 2010
Messages : 252
Détails du profil
Informations personnelles :
Nom : Homme Dominique
Âge : 15
Localisation : France

Informations professionnelles :
Activité : Première S

Informations forums :
Inscription : juillet 2010
Messages : 252
Points : 228
Points : 228
faut pas oublier les ipv6 qui contienne des lettres je crois ... non ?
Marc3001 à dit ça parce qu'avec ton système actuelle, il est effectivemet possible de passer une fausse ip.
la solution serait de récupérer l'ip grâce à la variable super_globale $_SERVEr['REMOTE_ADDR'] qui te renvoie l'ip du visiteur ... te je ne crois pas que cette variable soit falsifiable.
Dominique49 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/09/2011, 16h28   #6
Invité de passage
 
Inscription : juin 2011
Messages : 7
Détails du profil
Informations forums :
Inscription : juin 2011
Messages : 7
Points : 0
Points : 0
Citation:
Envoyé par Dominique49 Voir le message
faut pas oublier les ipv6 qui contienne des lettres je crois ... non ?
Marc3001 à dit ça parce qu'avec ton système actuelle, il est effectivemet possible de passer une fausse ip.
la solution serait de récupérer l'ip grâce à la variable super_globale $_SERVEr['REMOTE_ADDR'] qui te renvoie l'ip du visiteur ... te je ne crois pas que cette variable soit falsifiable.
C'est ce que je fais :

Code :
1
2
3
4
5
6
7
function get_user_ip() {
	$ip  = $_SERVER['REMOTE_ADDR']; 
	$dotted  = preg_split( "/[.]+/", $ip);
	$ip2 = (double) ($dotted[0]*16777216)+($dotted[1]*65536)+($dotted[2]*256)+($dotted[3]);
 
	return $ip2;
}
grosbouff est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/09/2011, 16h54   #7
Membre chevronné
 
Avatar de Marc3001
 
Homme
Ingénieur développement logiciels
Inscription : février 2008
Messages : 430
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 28
Localisation : France, Ille et Vilaine (Bretagne)

Informations professionnelles :
Activité : Ingénieur développement logiciels

Informations forums :
Inscription : février 2008
Messages : 430
Points : 682
Points : 682
Citation:
Envoyé par Dominique49 Voir le message
faut pas oublier les ipv6 qui contienne des lettres je crois ... non ?
Marc3001 à dit ça parce qu'avec ton système actuelle, il est effectivemet possible de passer une fausse ip.
la solution serait de récupérer l'ip grâce à la variable super_globale $_SERVEr['REMOTE_ADDR'] qui te renvoie l'ip du visiteur ... te je ne crois pas que cette variable soit falsifiable.
C'est pas passer une fausse IP qui est embêtant c'est faire une injection pour ne pas prendre en compte l'IP dans la requête ce qui arriverait à avoir des doublons comme tu le constates dans ta base.

Imagine que dans le champ img_id quelqu'un injecte la valeur "5';". Si tu ne sécurises pas ça, ta requête ne tient plus compte du filtre sur l'IP.....

C'est donc très important de toujours :
- vérifier le format de la variable si possible via expression rationnelle
- utiliser mysql_real_escape_string pour chacune des variables que tu insères dans une requête SQL
__________________
Le logiciel, c'est comme le sexe, c'est meilleur quand c'est libre.

Linus Torvalds
Marc3001 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/09/2011, 17h28   #8
Invité de passage
 
Inscription : juin 2011
Messages : 7
Détails du profil
Informations forums :
Inscription : juin 2011
Messages : 7
Points : 0
Points : 0
Citation:
Envoyé par Marc3001 Voir le message
C'est pas passer une fausse IP qui est embêtant c'est faire une injection pour ne pas prendre en compte l'IP dans la requête ce qui arriverait à avoir des doublons comme tu le constates dans ta base.

C'est donc très important de toujours :
- vérifier le format de la variable si possible via expression rationnelle
- utiliser mysql_real_escape_string pour chacune des variables que tu insères dans une requête SQL
Ok. Donc
Vérifier img_id pour être sur d'éviter une injection SQL...
Je le fais comme ceci, c'est OK ?

Code :
1
2
3
4
function number_sanitize($value){
    return filter_var($value, FILTER_SANITIZE_NUMBER_INT);
}
$img_id=number_sanitize($img_id);
Je comprend le problème d'une injection SQL, mais par contre :
Citation:
Imagine que dans le champ img_id quelqu'un injecte la valeur "5';". Si tu ne sécurises pas ça, ta requête ne tient plus compte du filtre sur l'IP.....
Ben alors le script va vérifier si l'IP a déjà voté pour l'image 5 et ça devrait pas changer grand chose; puisque de toute façon le script va vérifier si son IP a déjà voté pour l'image 5; et si pas voter pour celle là....
Au deuxième essai, il sera bloqué puisque son IP aura été enregistré pour l'image 5..
Ton exemple lui permettrait juste de voter une fois pour une autre image...Non ?

Déjà merci pour tes explications !
grosbouff est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/09/2011, 18h21   #9
Membre chevronné
 
Avatar de Marc3001
 
Homme
Ingénieur développement logiciels
Inscription : février 2008
Messages : 430
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 28
Localisation : France, Ille et Vilaine (Bretagne)

Informations professionnelles :
Activité : Ingénieur développement logiciels

Informations forums :
Inscription : février 2008
Messages : 430
Points : 682
Points : 682
La validation du format de l'id image semble correct.

Sur mon exemple, note le ";" qui si non échappé (via la fonction mysql_real_escape_string) indique la fin de la requête sql avant le AND et le filtre sur l'IP.
Du coup ta requête ne filtre plus sur le couple Image-IP mais juste sur l'image......

Je viens de me rendre compte que mon exemple est pourri car encore plus limitant que l’existant. Mais le principe est là.
__________________
Le logiciel, c'est comme le sexe, c'est meilleur quand c'est libre.

Linus Torvalds
Marc3001 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 21/09/2011, 09h16   #10
Membre confirmé
 
Homme Dominique
Première S
Inscription : juillet 2010
Messages : 252
Détails du profil
Informations personnelles :
Nom : Homme Dominique
Âge : 15
Localisation : France

Informations professionnelles :
Activité : Première S

Informations forums :
Inscription : juillet 2010
Messages : 252
Points : 228
Points : 228
Citation:
Envoyé par Marc3001 Voir le message
La validation du format de l'id image semble correct.

Sur mon exemple, note le ";" qui si non échappé (via la fonction mysql_real_escape_string) indique la fin de la requête sql avant le AND et le filtre sur l'IP.
Du coup ta requête ne filtre plus sur le couple Image-IP mais juste sur l'image......

Je viens de me rendre compte que mon exemple est pourri car encore plus limitant que l’existant. Mais le principe est là.
on peu aussi utiliser -- qui est le signal d'un commentaire en SQL
effectivement, les injections SQL existes, c'est pourquoi j'utilise toujours des requêtes préparées ..
Dominique49 est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 00h52.


 
 
 
 
Partenaires

Hébergement Web