Sécurité informatique web d'un chat.

Signaler
Messages postés
137
Date d'inscription
vendredi 11 juillet 2014
Statut
Membre
Dernière intervention
18 novembre 2020
-
Messages postés
13145
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
18 novembre 2020
-
Bonjour,

Je m'adresse à vous aujourd'hui pour me venir en aide contre un piratage que je subis par l'effacement des messages écrits sur mon chat intégré à mon site de jeu d'échecs https://www.jeuxechecs.fr/echecs/login.php
Je vous présente d'abord les fichiers utilisés pour le fonctionnement de ce chat:
Fichier chat_modele.php
<?php
session_start();
$participant=$_SESSION['username'];
echo <<<EOF
<h1><FONT COLOR="Blue">Bienvenue sur ce chat $participant</FONT></h1>
EOF;

function bdd()
{
//return $db = new PDO('mysql:host=localhost;dbname=test2; charset=utf8', 'root', '');
return $db = new PDO('mysql:host=XXXXXXX;dbname=XXXXXXX; charset=utf8', 'XXXXXXX', 'XXXXXXX');
}
function ajout_message($bdd,$username,$message)
{
	$req = $bdd->prepare("INSERT INTO message(Pseudo,Message,Date) VALUES(:Pseudo,:Message,NOW())");
	$req->execute(array("Pseudo"=>$_SESSION['username'],
	                    "Message"=>$message));
}

function message($bdd)
{
	$req = $bdd->query("SELECT * FROM message ORDER BY Date DESC");
	
	return $req;
}

function expire_message($bdd)
{	
	//$req = $bdd->query("DELETE FROM message WHERE Date < DATE_SUB(NOW(), INTERVAL 172800 MINUTE)");//120 jours
//La ligne ci dessus en étant placée en commentaire n'est jamais utilisée pour effacer les messages de la table message	
}

function pair($nombre)
{
    if ($nombre%2 == 0) return true;
    else return false;
}

function getRelativeTime($date) {
    // Déduction de la date donnée à la date actuelle
    $time = time() - strtotime($date); 

    // Calcule si le temps est passé ou à venir
    if ($time > 0) {
        $when = "il y a";
    } else if ($time < 0) {
        $when = "dans environ";
    } else {
        return "il y a 1 seconde";
    }
    $time = abs($time); 

    // Tableau des unités et de leurs valeurs en secondes
    $times = array( 31104000 =>  'an{s}',       // 12 * 30 * 24 * 60 * 60 secondes
                    2592000  =>  'mois',        // 30 * 24 * 60 * 60 secondes
                    86400    =>  'jour{s}',     // 24 * 60 * 60 secondes
                    3600     =>  'heure{s}',    // 60 * 60 secondes
                    60       =>  'minute{s}',   // 60 secondes
                    1        =>  'seconde{s}'); // 1 seconde         

    foreach ($times as $seconds => $unit) {
        // Calcule le delta entre le temps et l'unité donnée
        $delta = round($time / $seconds); 

        // Si le delta est supérieur à 1
        if ($delta >= 1) {
            // L'unité est au singulier ou au pluriel ?
            if ($delta == 1) {
                $unit = str_replace('{s}', '', $unit);
            } else {
                $unit = str_replace('{s}', 's', $unit);
            }
            // Retourne la chaine adéquate
            return $when." ".$delta." ".$unit;
        }
    }
}
?>

En ligne 30 j'ai mis hors service celle ci afin de localiser le problème par l'empêchement d'effacer la table par ce moyen.Mais sans succès malgré cela.

Fichier chat_control.php
<?php
session_start();
require_once("chat_modele.php");
$bdd = bdd();
$messag=htmlspecialchars($_GET['message']);
if(isset($_GET['name']) AND isset ($messag))
{	
	ajout_message($bdd,$_GET['name'], $messag);
}
else
{
	expire_message($bdd);
	$message = message($bdd);
	require_once("chat_vue.php");
}
?>

Je soupçonne la ligne 5 de ne pas être suffisamment sécuritive.

Fichier chat_vue.php
<?php
session_start();
?>
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8" />
<title>chat</title>
</head>
<body>
<table id="table_message">
<?php
while($don = $message->fetch())
{
	if(pair($don['ID']))
	{
		$color = "";
	}
	else
	{
		$color = "#EDEDED";
	}
?>
<tr style="background-color:<?php echo $color; ?>">
	<td class="info_message" valign="top">	   
	 <span style="font-size:small"><?php echo 'De ' .$don['Pseudo'];?></span></br> 
<?php 
$_SESSION['joueur']=$don['Pseudo'];
	sscanf($don['Date'], "%4s-%2s-%2s %2s:%2s", $annee, $mois, $jour, $heure, $minute);
	$heure=$heure+1;
	echo $jour.'/'.$mois.'/'.$annee.' '.$heure.':'.$minute;
?>	
	</td>
	<td class="message" >
	<div class="message2" >
	<?php 
	echo $don['Message'];	
	?>
	</div>	
	</td>
</tr>
<?php
}
?>
</table>
</body>
</html>

Rien à signaler de particulier dans ce fichier à ce jour.

Fichier chat.php
<?php
session_start();
?>
<!doctype html>
<html lang="FR-fr">
<head>
<title>Chat</title>
<meta charset="UTF-8">
<link rel="stylesheet" href="chat.css"/>
</head>
<body>
<?php
if (empty ($username)) 
{
?>
<table id="body">
	<tr>
	<td>  
	</td>
	</tr>
		<tr >
		<td style="height:320px">
		<div id="chat_aff"></div>
		</td>
		</tr>
	<tr >
	<td id="form" valign="top">
<table id="form2">
<tr>
	<td style="text-align: center;font-size:16px;width:90%">
	<label for="message" style="color:blue;font-family:Comic Sans MS;font-size:18px;">Ecrire les messages ci dessous.</label>
	</td>
	<td>
	</td>
	</tr>
	<tr>
	<td>
		<textarea id="message" 
          rows="3" cols="33">
		</textarea>
	</td>	
	<td>	
		<button id="submit">Envoi</button>	
	</td>
</tr>
</table>
</td>
</tr>
</table>
<?php
}
?>
<script src="https://code.jquery.com/jquery.min.js"></script>
<script>
	setInterval(function()
	{
	$("#chat_aff").load("chat_control.php",function(){});	
	},1000);
	

	$("#submit").click(function()
	{
	var name =  $("#name").val();
	
	var message = $("#message").val();
	
	$("#message").val("");
	
	$.ajax({
		async: false ,
		type: 'GET',
		url: 'chat_control.php?name='+name+'&message='+message
		
	});
	
	});


</script>
</body>
</html>

Rien de particulier non plus pour cet autre fichier.
Hormis le fait que j'ai pris la peine de sécurisé mon site par le cryptage des données transmises sur internet en le translatant de HTTP à HTTPS pour une meilleure sécurité pour les "clients".

Merci d'avance pour votre soutien.





Configuration: Windows / Opera 36.0.2130.80

7 réponses

Messages postés
30196
Date d'inscription
mercredi 22 octobre 2003
Statut
Modérateur
Dernière intervention
18 novembre 2020
2 982

function bdd()
{
//return $db = new PDO('mysql:host=localhost;dbname=test2; charset=utf8', 'root', '');
REQUIRE_ONCE 'connexion.php';
}

et tu ne fais pas de RETURN de la variable $bdd ?

ça ne marchera donc pas...

pour le coup, j'aurais plutôt fait :
<?php
//fichier connexion.php 
function bdd(){
  try{
    $bdd =new PDO('mysql:host=localhost;dbname=mabdd; charset=utf8', 'user', 'password');  
    // Activation des erreurs PDO
    $bdd->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    // mode de fetch par défaut : FETCH_ASSOC / FETCH_OBJ / FETCH_BOTH
     $bdd->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
   } catch(PDOException $e) {
      die('Erreur : ' . $e->getMessage());
   }
  return  $bdd;
}
?>


et pour ton fichier chat_modele.php
<?php
//fichier chat_modele.php
  
require_once  'connexion.php';

function ajout_message($username,$message)
{
  $bdd = bdd();
  $sql = "INSERT INTO message(Pseudo,Message,Date) VALUES(:Pseudo,:Message,NOW())");
  $datas = array(":Pseudo"=>$_SESSION['username'],":Message"=>$message));
  //Execution de la requete
  try{
    $requete = $bdd -> prepare($req) ;
    $requete->execute($datas) ;
  }catch(Exception $e){
    // en cas d'erreur :
     echo " Erreur ! ".$e->getMessage();
     echo " Les datas : " ;
    print_r($datas);
  }
}
	
?>



Cela veut il indiquer que le fonction htmlspecialchars ne peut servir contre le piratage?

Ca veut surtout dire que : En BDD on stocke les données "brut"
et qu'avec les requêtes préparées, c'est inutile de vouloir faire ce genre de "protection"


Tu remarqueras au passage que j'ai corrigé ton code... tu avais écrit n'importe quoi !!
Messages postés
30196
Date d'inscription
mercredi 22 octobre 2003
Statut
Modérateur
Dernière intervention
18 novembre 2020
2 982 >
Messages postés
137
Date d'inscription
vendredi 11 juillet 2014
Statut
Membre
Dernière intervention
18 novembre 2020

Tu plaisantes ???
je t'ai dit :

La fonction htmlspecialchars ne doit servir que pour de l'affichage ... en aucun cas pour "sécuriser" les données à insérer en bdd...

Ensuite, je t'ai également dit

En BDD on stocke les données "brut"
et qu'avec les requêtes préparées, c'est inutile de vouloir faire ce genre de "protection"



Alors pourquoi on stocke les données "brutes" et pas "encodées" avec le htmlspecialchar... ?....
Et bien, aujourd'hui, tu te sers de ces données pour les afficher dans des pages web, donc le htmlspecialchar n'est pas dérangeant... mais imagine que demain tu veuilles utiliser les données qui sont dans ta bdd pour une application mobile ou tout simplement pour pouvoir faire des stats dans excel ... et bien là, les caractères html risquent de te déranger plus qu'autre chose.
La base de données sert à stocker ( on se fou de la mise en forme à l'intérieur...)
Ce n'est qu'à l'affichage que tu "DOIS" gérer éventuellement le "rendu" et l'encodage éventuel des caractères html ...

Je te rassure, tu fais parti des millions de débutants qui font ce genre d'erreur.... par manque d'expérience.
Messages postés
137
Date d'inscription
vendredi 11 juillet 2014
Statut
Membre
Dernière intervention
18 novembre 2020
>
Messages postés
30196
Date d'inscription
mercredi 22 octobre 2003
Statut
Modérateur
Dernière intervention
18 novembre 2020

D'accord.
Avec cet exemple concret maintenant j'ai bien compris pourquoi il vaut mieux stocker des données brutes en base. Et que par conséquent le htmlspecialchar ne doit pas servir pour cela avec les requêtes préparées.
Mais cela ne me dit pas comment empêcher les pirates de vider ma table message. ?
Je pense à la faille qui consisterait à utiliser la barre d'adresse.Si je ne me trompe.
Mais dans ce cas comment puis je faire?
Messages postés
30196
Date d'inscription
mercredi 22 octobre 2003
Statut
Modérateur
Dernière intervention
18 novembre 2020
2 982 >
Messages postés
137
Date d'inscription
vendredi 11 juillet 2014
Statut
Membre
Dernière intervention
18 novembre 2020


Je pense à la faille qui consisterait à utiliser la barre d'adresse.Si je ne me trompe.


Tu comprends vite.. si on t'explique longtemps........ !!!!!!!
Il faut que je te répète les choses combien de fois ?????!!


1 - Passer en POST au lieu du GET comme je te l'ai déjà indiqué ( ça sera déjà mieux )
2 - Avec les requêtes préparées .en PDO.. plus de soucis d'injection SQL
Messages postés
13145
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
18 novembre 2020
732 >
Messages postés
137
Date d'inscription
vendredi 11 juillet 2014
Statut
Membre
Dernière intervention
18 novembre 2020

il faut sans doute également adapter le code ajax dans chat.php, pour utiliser POST au lieu de GET.
Messages postés
13145
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
18 novembre 2020
732 >
Messages postés
13145
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
18 novembre 2020

Messages postés
30196
Date d'inscription
mercredi 22 octobre 2003
Statut
Modérateur
Dernière intervention
18 novembre 2020
2 982
Bonjour,

Vu que tu utilises PDO
1 - Active la gestion des erreurs ET place CHAQUE requête dans un bloc TRY/CATCH
https://www.commentcamarche.net/faq/46512-pdo-gerer-les-erreurs

2 - Utilises pour tes requêtes, des requêtes préparées (comme pour ta fonction ajout_message )
rien que ça, déjà, ça protègera contre l'injection SQL ...


Concernant ta ligne
$messag=htmlspecialchars($_GET['message']);

La fonction htmlspecialchars ne doit servir que pour de l'affichage ... en aucun cas pour "sécuriser" les données à insérer en bdd...

Messages postés
137
Date d'inscription
vendredi 11 juillet 2014
Statut
Membre
Dernière intervention
18 novembre 2020

Je viens de créer un fichier connexion.php que voici:
<?php
try{
$bdd =new PDO('mysql:host=localhost;
 dbname=mabdd; charset=utf8', 'user', 'password');
// Activation des erreurs PDO
 $bdd->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// mode de fetch par défaut : FETCH_ASSOC / FETCH_OBJ / FETCH_BOTH
 $bdd->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
} catch(PDOException $e) {
    die('Erreur : ' . $e->getMessage());
}
?>

Puis modifié le fichier chat_modele.php au niveau de ces ligne ci dessous:
function bdd()
{
//return $db = new PDO('mysql:host=localhost;dbname=test2; charset=utf8', 'root', '');
REQUIRE_ONCE 'connexion.php';
}
function ajout_message($bdd,$username,$message)
{
	$req = $bdd->prepare("INSERT INTO message(Pseudo,Message,Date) VALUES(:Pseudo,:Message,NOW())");
	$req->execute(array("Pseudo"=>$_SESSION['username'],
	                    "Message"=>$message));
						//Execution de la requete
						try{
						  $requete = $bdd -> prepare($req) ;
						  $requete->execute($datas) ;
						}catch(Exception $e){
						  // en cas d'erreur :
						   echo " Erreur ! ".$e->getMessage();
						   echo " Les datas : " ;
						  print_r($datas);
						}
}


Cela est il correct?
PHP.ini est configuré pour obtenir d'éventuels messages d'erreur par mon serveur.

Lorsque tu écrit: "La fonction htmlspecialchars ne doit servir que pour de l'affichage ... en aucun cas pour "sécuriser" les données à insérer en bdd... "
Cela veut il indiquer que le fonction htmlspecialchars ne peut servir contre le piratage?
Mais uniquement pour pour convertir des caractères en entités HTML correspondantes?
Messages postés
13145
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
18 novembre 2020
732
bonjour,
quel chat est victime de piratage? le chat principal ou le chat par partie?
comment se manifeste se piratage?
des messages sont affichés à un moment, visible par tous, et disparaissent ensuite?
as-tu vérifié si ces messages sont encore présents dans la base de données?
Messages postés
137
Date d'inscription
vendredi 11 juillet 2014
Statut
Membre
Dernière intervention
18 novembre 2020

C'est le chat principal qui est piraté comme indiqué par l'image ci dessous:

Le piratage se manifeste purement et simplement par l'effacement de tous les messages.
Et la table message ne contient plus aucune donnée.
Si au paravent j'ai sauvegardé celle ci, il me suffit de copier les données dans cette table pour retrouver les messages dans le chat.
Mais ce n'est pas le but de procéder ainsi pour retrouver la table complète.
Les messages peuvent être affichées plusieurs mois sans problème.Puis un jour au gré de l'humeur du pirate, celui ci agit de telle manière à vider ma table de toute données.
Je précise que la table n'est pas supprimer pour autant.
Messages postés
13145
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
18 novembre 2020
732
tu as écrit "En ligne 30 j'ai mis hors service celle ci afin de localiser le problème par l'empêchement d'effacer la table par ce moyen.Mais sans succès malgré cela."

après avoir changé cela, tu observes encore des disparitions de messages?
Messages postés
137
Date d'inscription
vendredi 11 juillet 2014
Statut
Membre
Dernière intervention
18 novembre 2020

Oui j'ai effectivement mis hors servie la ligne 30 pour ne plus effacer la table en février dernier lorsque l'effacement est apparu pour le 2ème ou 3 ème fois en quelques semaines.
Messages postés
137
Date d'inscription
vendredi 11 juillet 2014
Statut
Membre
Dernière intervention
18 novembre 2020
>
Messages postés
137
Date d'inscription
vendredi 11 juillet 2014
Statut
Membre
Dernière intervention
18 novembre 2020

J'observe toujours toutes les disparitions de données.
Messages postés
13145
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
18 novembre 2020
732
je suis très surpris par cette instruction:
$_SESSION['joueur']=$don['Pseudo'];

à quoi sert-elle?
Messages postés
137
Date d'inscription
vendredi 11 juillet 2014
Statut
Membre
Dernière intervention
18 novembre 2020

Elle sert à établir une valeur à $_SESSION['joueur']
Mais sans intérêt en ce qui concerne ce piratage.
Orientons nous sur ce que nous savons en la matière au sujet de l'écriture des barres d'adresse des navigateurs permettant de s'introduire dans les tables pour les effacer.
Je reste convaincu sauf erreur de ma part que c'est pas ce procédé que le pirate réussi à commettre ces méfaits.
Car j'ai rechercher ailleurs sans rien trouver au regard de mes connaissances.
Messages postés
30196
Date d'inscription
mercredi 22 octobre 2003
Statut
Modérateur
Dernière intervention
18 novembre 2020
2 982 >
Messages postés
137
Date d'inscription
vendredi 11 juillet 2014
Statut
Membre
Dernière intervention
18 novembre 2020

Et avec ce que je t'ai répondu... Tu ne devrais plus avoir ce souci (qui se nomme faille d'injection sql)
Messages postés
13145
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
18 novembre 2020
732 >
Messages postés
30196
Date d'inscription
mercredi 22 octobre 2003
Statut
Modérateur
Dernière intervention
18 novembre 2020

n'était-ce déjà pas une requête préparée?
Messages postés
30196
Date d'inscription
mercredi 22 octobre 2003
Statut
Modérateur
Dernière intervention
18 novembre 2020
2 982 >
Messages postés
13145
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
18 novembre 2020

Ah si...
donc son souci ne vient pas de cette partie du code ....

Si la table se vide toute seule, c'est qu'il a d'autre code ailleurs qui peuvent provoquer son pb .... ou que la bdd est corrompue...
Mais ce n'est clairement pas son "insert" qui pose problème.
Messages postés
137
Date d'inscription
vendredi 11 juillet 2014
Statut
Membre
Dernière intervention
18 novembre 2020

INSERT ne m'a jamais posé de problème.
J'ai cru lors de l'avant dernier effacement de ma table en février dernier que c'est DELETE qui pouvait la vider.C'est ainsi que j'ai mis HS la ligne 30 de chat_modele.php mais cela sans effet puisque hier j'ai retrouvé ma table effacée après plusieurs moi de tranquillité.
Sachant que les $_GET peuvent créer des failles de sécurité, aujourd'hui je ne peux sortir de cette idée.
Pour en avoir la certitude il faudrait que je remplace $_GET par $_POST.
Mais cela je ne sais pas faire actuellement.
:(
Messages postés
30196
Date d'inscription
mercredi 22 octobre 2003
Statut
Modérateur
Dernière intervention
18 novembre 2020
2 982
Post ou get... Il est toujours possible d'envoyer ce qu'on veut dans les variables.
la seule différence c'est que d'un côté en get tu peux modifier la variable directement dans l' url.
Mais là n'est pas le problème vu que tu fais de l'Ajax... Et que n'importe qui peut modifier le code javascript sur ta page pour envoyer ce qu'il a envie...

Les requêtes préparer en PDO permettent de se prémunir des risques d'injection de faille SQL.

mais comme on peut te dire ce qu'on veut, tu n'as pas envie d'écouter, je t'invite à lire le contenu du lien suivant
https://analyse-innovation-solution.fr/publication/fr/php/objet-pdo-et-securite-mysql

et je maintiens donc, que ton soucis de disparition de données dans ta base ne viens pas du code que tu nous a montré.
Messages postés
13145
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
18 novembre 2020
732
toutes les pages du site utilisent-elles partout uniquement des requêtes préparées?
je pense que c'est plus utile que de changer tous les GET en POST.
Messages postés
137
Date d'inscription
vendredi 11 juillet 2014
Statut
Membre
Dernière intervention
18 novembre 2020

Le propre d'un scientifique est de toujours douter.
Comment serait il possible d'effacer la table correspondante au chat à partir d'une page php ou autre n'ayant aucun rapport avec celui ci?
Quand à celles se rapportant au chat je les ai mis ici à disposition.Sauf le fichier SQL auquel tout le monde imaginera facilement sa structure.
Ce n'est pas que je n'ai pas envie d'écouter et j'en veux pour preuve les modifications que j'ai accomplis sur tes conseils.
Mais pour que quelqu' un écoute jusqu' au bout il faut être suffisamment convainquant en sachant se placer à son niveau.
Après la pédagogie est encore autre chose....
Messages postés
13145
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
18 novembre 2020
732 >
Messages postés
137
Date d'inscription
vendredi 11 juillet 2014
Statut
Membre
Dernière intervention
18 novembre 2020

Il ne suffit pas de douter pour être scientifique.

Un exemple simple:
txtUserId= $_POST['id']
txtSQL = "SELECT * FROM Users WHERE UserId = " + txtUserId;


que se passe-t-il si $_POST['id'] contient
105; DROP TABLE Suppliers
?
Messages postés
30196
Date d'inscription
mercredi 22 octobre 2003
Statut
Modérateur
Dernière intervention
18 novembre 2020
2 982 >
Messages postés
137
Date d'inscription
vendredi 11 juillet 2014
Statut
Membre
Dernière intervention
18 novembre 2020

pour ce qui est de la pédagogie ... je l'ai quand je dois donner des cours ....
mais ici on est sur un forum qui traite de problématiques techniques clairement identifiées..... pas pour te donner des cours....
Quand tu as un "doute", google est ton ami et j'invite fortement à te former grâce aux nombreux tutos/cours que tu pourras y trouver sans souci.
Pour ma part, on a répondu clairement à ta question de départ.

Pour ma part, je m'arrêterai là. Je ne vais pas perdre plus de temps à essayer de convaincre quelqu'un qui pense déjà connaitre la réponse et qui ne tient pas compte de nos explications.

Bonne jounrée.
Messages postés
13145
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
18 novembre 2020
732 >
Messages postés
137
Date d'inscription
vendredi 11 juillet 2014
Statut
Membre
Dernière intervention
18 novembre 2020

Personnellement, je ne trouve pas que tu te comportes en scientifique, en agissant sur base de vagues impressions.
S'agit-il de piratage, s'agit-il de manipulation d'url?
Le scientifique essaie de travailler sur base de faits, pas d'impressions.
Que fais-tu pour rassembler et analyser des faits?
Une approche rationnelle serait, au moment où les messages disparaissent, de déterminer pendant quelle période cela s'est produit.
Ensuite, d'analyser ce qui s'est passé pendant cette période.
As-tu fait cela? Qu'as-tu découvert, qu'en as-tu déduit?