Vous n'êtes pas identifié(e).

Top posteurs

Statistiques

Partenaires

  • eXolia Hosting
  • Eggdrop.fr

#1 06/03/2015 23:07:31

sianur
IRCzien en herbe
Lieu : dordogne
Inscription : 17/05/2013
Messages : 79
Site Web

Anti Attaque PDO / PHP / TCL

Bonjour,

Je viens partager avec vous un petit bout de code pour lutter
contre les attaques de clones. (un cron viendra dans la semaine)

Ce code s'adresse à tous les réseaux IRC de petite ou grosse envergures, vous
comprendrez mieux ci-dessous, ce code en TCL est une modification de LEA SERVICE.

- Je laisserais les PRO du TCL améliorer le code (le langage TCL est loin d'être mon point fort)

QUELQUES EXPLICATIONS:

Je vous conseille de lire avant de copier/coller bêtement le code sur votre réseau !

1) Nous considérerons qu'un clone ne passera pas l'applet webchat de notre site :
Nous exclurons des gline toutes les connexions en provenance de notre serveur web.

2) Si une personne ne vient pas de l'applet webchat, elle sera gline à chaque fois :
Nous protégerons donc les personnes qui se sont connectés plus de 10 fois.

3) Si on reçoit 5 connexions en 2 secondes on active le système de sécurité (système classique de Lea)

- Cependant, certains clones entrent avant l'activation avec le système classique.

4) Optimisation du système de sécurité : Détection des dernières connexions dans les 2 minutes
précédentes l'activation du système de sécurité (gline / retrait des hosts de la base de donnée si ils ne se sont pas connecté au tchat au moins 10 fois et ne viennent pas de l'applet)

PRÉ-REQUIS:

- Un serveur UnrealIRCd
- Un eggdrop (mysqltcl requis)
- Un serveur WEB / mySQL / PDO
- S'assurer que la fonction gethostbyaddr fonctionne en PHP - Activation " d'un truc " pour que ça marche.

Voici les codes sources :

1) on créé une base de donnée

Code: SQL
 
 
--
-- Structure de la table `ipcheck`
--
 
CREATE TABLE IF NOT EXISTS `ipcheck` (
  `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  `ip` VARCHAR(255) NOT NULL DEFAULT '',
  `connect` INT(15) NOT NULL DEFAULT '1',
  `lastconnect` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `http` enum('Y','N') NOT NULL DEFAULT 'N',
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1;
 
 

2) on ajoute le fichier ipchecksecu.php dans le(s) dossier(s) de votre/vos applets

Code: PHP
 
<?php
//changer vos informations de connexion à la base de donnée si dessous
$db_host = 'localhost';
$db_name = 'nombdd';
$db_username = 'user';
$db_password = 'pass';
 
 
//fin des modifications ne modifier le reste que si vous savez exactement ce que vous faites
 
 
//connexion à la base de donnée pdo
try
{
       $connect = new PDO('mysql:host='.$db_host.';dbname='.$db_username, $db_name, $db_password);
}
catch(Exception $e)
{
        echo 'Une erreur est survenue avec la base de donée!';
        die();
}
 
/* 
*  fonction ipcheck
* require_once 'ipchecksecu.php'; 
* ipcheck(gethostbyaddr($_SERVER['REMOTE_ADDR']));   
*/
 
function ipcheck($str) {
global $connect;
//on recherche l'ip du visiteur dans la bdd
$pdo = $connect->prepare('SELECT * FROM ipcheck WHERE ip= ?');
$pdo->execute(array($str));
//si l'ip existe
if ($pdo->rowCount() > 0) {
//on update le nombre de connexions
$pdo = $connect->prepare('UPDATE ipcheck SET connect=connect+1 WHERE ip = ?');
$pdo->execute(array($str));
 }
//sinon on ajoutel'ip dans la base de donnée en precisant qu'il vien de l'applet (Y)
 else {
$pdo = $connect->prepare('INSERT INTO ipcheck (ip, http) VALUES(?, \'Y\')');
$pdo->execute(array($str));
 }
 }
 
 ?>
 

3) sur la page de votre applet on appel la fonction

Code: PHP
 
//code a ajouter sur la page de votre applet oublier pas de mettre ipchecksecu.php dans le meme dossier
//on appel le fichier ipchecksecu.php
 require_once 'ipchecksecu.php'; 
//on envois l'host du visiteur à la fonction ipcheck
 ipcheck(gethostbyaddr($_SERVER['REMOTE_ADDR']));   
 

je vous conseil d'ajouter un truc avant du genre if (isset($_GET['machin']) {appel ipcheck} ou encore if  (isset($_POST['truc'])) enfin a vous de voir

4) on créé un block link sur unreal

Code: Bash
 
link Security.Discutea.com {
        username *;
        hostname votre_ip;
        bind-ip *;
        port Votre_port;
        hub *;
        password-connect "mot_de_passe";
        password-receive "mot_de_passe";
        class servers;
};
 

on oublie pas de rehash unreal : ./unreal rehash ou /rehash sur irc

5) on ajoute le tcl a sont eggdrop oublier pas de l'ajouter en source dans votre eggdrop.conf

Code: TCL
 
 
bind evnt n init-server discutea:initialisation
bind evnt n disconnect-server discutea:evenement
bind evnt n prerestart discutea:evenement
bind evnt n sighup discutea:evenement
bind evnt n sigterm discutea:evenement
bind evnt n sigill discutea:evenement
bind evnt n sigquit discutea:evenement
bind dcc n discuteaconnect discutea:connect
bind dcc n discuteadeconnect discutea:deconnect
 
package require mysqltcl
 
# Configuration mySQL # 
set discutea(sqllogin) "login_sql"
set discutea(sqlpass) "pass_sql" 
set discutea(sqldb) "db_sql"
set discutea(sqlhost) "localhost"
#link $discutea(nick)
 
set discutea(nick) "Security"
set discutea(salon) "#Security"
set discutea(ip) "IP_DU_LINK"
set discutea(link) "Security.Discutea.com"
set discutea(port) "PORT_DU_LINK"
set discutea(pass) "PASS_DU_LINK"
set discutea(secuco) "5 2"
 
set discutea(counter)        "0"
set discutea(init)           "0"
if {[info exists discutea(maxthrottle)]} {unset discutea(maxthrottle)}
if {[info exists discutea(maxthrottle2)]} {unset discutea(maxthrottle2)}
 
#############
# discutea Arret #
#############
 
proc discutea:arret {} {
	global discutea
	foreach kill [utimers] { if {[lindex $kill 1]=="discutea:verif" || [lindex [lindex $kill 1] 0]=="discutea:uncountkill"} { killutimer [lindex $kill 2] } }
}
 
 
############
# discutea Secu #
############
proc discutea:presecu {} {
	global discutea
	if {[info exists discutea(maxthrottle)]} {break}
	if {[info exists discutea(maxthrottle2)]} {
		putdcc $discutea(idx) ":$discutea(nick) PRIVMSG $discutea(salon) : Désactivation total du système de sécurité"
        unset discutea(maxthrottle2)
	}
}
proc discutea:secu {} {
	global discutea
	if {![info exists discutea(maxthrottle2)]} {set discutea(maxthrottle2) "1"; utimer 15 discutea:presecu}
	if {[info exists discutea(maxthrottle)]} {
		if {[info exists discutea(throttle)]} { unset discutea(throttle) }
		putdcc $discutea(idx) ":$discutea(nick) PRIVMSG $discutea(salon) : Désactivation du système de protection dans 15 secondes"
        unset discutea(maxthrottle)
	}
	if {[info exists discutea(maxthrottle2)]} {utimer 15 discutea:presecu}
}
 
 
###################
# discutea Uncountkill #
###################
 
proc discutea:uncountkill {arg} {
	global countkill
	set arg [split $arg]
	set host [string tolower [lindex $arg 0]]
	if {[info exists countkill($host)]} { unset countkill($host) }
}
 
#################
# discutea Evenement #
#################
 
proc discutea:evenement {arg} { 
	global discutea
	if {[info exists discutea(idx)] && [valididx $discutea(idx)]} {
		putdcc $discutea(idx) ":$discutea(nick) QUIT :Maintenance Technique"
		putdcc $discutea(idx) ":$discutea(link) SQUIT $discutea(link) :Maintenance Technique"
		discutea:arret
	}
}
 
 
###############
# discutea Connect #
###############
 
proc discutea:connect {nick idx arg} { 
	global discutea
	set discutea(counter) "0"
		if {![info exists discutea(idx)]} {
			putdcc $idx "01\[ 03Connexion01 \] 01 Lancement du systeme..."; discutea:connexion
		} else {
			if {![valididx $discutea(idx)]} { 
				putdcc $idx "01\[ 03Connexion01 \] 01 Lancement du systeme..."; discutea:connexion
			} elseif {[info exists discutea(idx)]} { putdcc $idx "01\[ 04Impossible01 \] 01 systeme déjà connecté..." }
		}
}
 
#################
# discutea Deconnect #
#################
 
proc discutea:deconnect {nick idx arg} { 
	global discutea
		if {[info exists discutea(idx)]} {
			if {[info exists discutea(maxthrottle)]} { discutea:secu }
			if {[info exists discutea(maxthrottle2)]} { discutea:presecu }
			putdcc $idx "01\[ 03Déconnexion01 \] 01 Arret du systeme..."
			putdcc $discutea(idx) ":$discutea(nick) QUIT :Maintenance Technique"
			putdcc $discutea(idx) ":$discutea(link) SQUIT $discutea(link) :Maintenance Technique"
			discutea:arret
		} else {
			if {[valididx $discutea(idx)]} {
				if {[info exists discutea(maxthrottle)]} { discutea:secu }
				if {[info exists discutea(maxthrottle2)]} { discutea:presecu }
				putdcc $idx "01\[ 03Déconnexion01 \] 01 Arret du systeme..."
				putdcc $discutea(idx) ":$discutea(nick) QUIT :Maintenance Technique"
				putdcc $discutea(idx) ":$discutea(link) SQUIT $discutea(link) :Maintenance Technique"
				discutea:arret
			} else { putdcc $idx "01\[ 04Impossible01 \] 01 systeme n'est pas connecté..." }
		}
}
 
 
 
 
#################
# discutea Connexion #
#################
proc discutea:connexion {} {
	global discutea olines vhosts ulines links bl data fin countkill sconnect result
	if {![catch "connect $discutea(ip) $discutea(port)" discutea(idx)]} {
		if {[info exists olines]} { unset olines }
		if {[info exists vhosts]} { unset vhosts }
		if {[info exists ulines]} { unset ulines }
		if {[info exists links]} { unset links }
		if {[info exists data]} { unset data }
		if {[info exists countkill]} { unset countkill }
		if {[info exists sconnect]} { unset sconnect }
		if {[info exists discutea(quit)]} { unset discutea(quit) }
		if {[info exists discutea(cmd)]} { unset discutea(cmd) } 
		if {[info exists discutea(rep)]} { unset discutea(rep) } 
		if {[info exists discutea(aff)]} { unset discutea(aff) }
		if {[info exists discutea(throttle)]} { unset discutea(throttle) }
		set discutea(init) "1"; utimer 15 [list set discutea(init) 0]
		utimer 5 [list unset discutea(noactive)]
		utimer 7 [list putdcc $discutea(idx) ":$discutea(nick) PRIVMSG $discutea(salon) :03Activation 04:14 Service de securité activé"]
		set discutea(uptime) [clock seconds]
		putdcc $discutea(idx) "PROTOCTL NICKv2 SJOIN2 UMODE2 NOQUIT VL TKLEXT"
		putdcc $discutea(idx) "PASS $discutea(pass)"
		putdcc $discutea(idx) "SERVER $discutea(link) 1 :Service tcl pour Discutea/Rezochat"
		putdcc $discutea(idx) ":$discutea(link) SQLINE $discutea(nick) :Service tcl pour Discutea/Rezochat"
		putdcc $discutea(idx) ":$discutea(link) NICK $discutea(nick) 1 [unixtime] Service Discutea.com $discutea(link) 0 +oqS Discutea.com :99 M Service"
		putdcc $discutea(idx) ":$discutea(link) EOS"
		putdcc $discutea(idx) ":$discutea(nick) MODE $discutea(nick) +oOaANG"
		putdcc $discutea(idx) ":$discutea(nick) JOIN $discutea(salon)"
		putdcc $discutea(idx) ":$discutea(nick) MODE $discutea(salon) +sO"
		putdcc $discutea(idx) ":$discutea(nick) MODE $discutea(salon) +q $discutea(nick)"
		if {[info exists discutea(maxthrottle)]} { discutea:secu }
		set discutea(noactive) 1
		incr discutea(counter) 1
		control $discutea(idx) discutea:link
		utimer 15 discutea:verif
	} elseif {[info exists discutea(idx)]} { unset discutea(idx) }
}
 
proc discutea:initialisation {arg} { 
	global discutea
	discutea:connexion
}
 
####################
# discutea Verification #
####################
 
proc discutea:verif {} {
	global discutea
	if {[valididx $discutea(idx)]} { 
		utimer 15 discutea:verif
	} else { 
if {$discutea(counter)<="10"} {
			discutea:connexion
		} else { discutea:arret }
	}
}
 
############
# discutea Link #
############
proc discutea:link {idx arg} {
	global discutea cdiscutea olines vhosts ulines links sconnect version
	set arg [split $arg]
	switch -exact [lindex $arg 0] {
		"PING" { 
			set discutea(counter) "0"
			putdcc $discutea(idx) "PONG [lindex $arg 1]"
		}
		"NICK" {
		if {[info exists discutea(noactive)]} { return 0 }
		    set stop 0
			set user [lindex $arg 1]
			set vuser [string tolower $user]
			set ident [string tolower [lindex $arg 4]]
			set host [string tolower [lindex $arg 5]]
			set host2 [lindex $arg 5]
			set servs [lindex $arg 6]
			set umode [lindex $arg 8]
			set vservs [string tolower $servs]
			set real [string trim [string tolower [join [lrange $arg 10 end]]] :]
			set real2 [string trim [join [lrange $arg 10 end]] :]
			set age [string trim [join [lrange $arg 10 10]] :]
			if {![info exists vhosts($vuser)]} { set vhosts($vuser) $host2 }
			if {![info exists links($vuser)]} { set links($vuser) $vservs }	
# on se connect à la base de donnée
			set discutea(connect) [mysqlconnect -host "$discutea(sqlhost)" -user "$discutea(sqllogin)" -password "$discutea(sqlpass)" -db "$discutea(sqldb)"]
# systeme d'activtion du systeme de secu pas nombre de connexions / secondes
				if {![info exists discutea(maxthrottle)]} {
					     if {![info exists discutea(throttle)]} {
						     set discutea(throttle) "1"
							 utimer [lindex $discutea(secuco) 1] [list unset discutea(throttle)]
							 }
					     if {$discutea(throttle)<[lindex $discutea(secuco) 0]} { 
						     incr discutea(throttle) 1 
							 } else { 
# activation du systeme de secu
						 putdcc $discutea(idx) ":$discutea(nick) PRIVMSG $discutea(salon) :Activation du système de protection du réseau."
						 set discutea(maxthrottle) "1"
						 utimer 300 discutea:secu
# on liste les hosts connecté dans les 2 dernières minutes qui ne sont pas venu en applet et qui ce sont pas connecté au moins 10 fois
						 set res [mysqlquery $discutea(connect) "SELECT * FROM ipcheck WHERE TIMESTAMPDIFF(MINUTE, lastconnect, NOW()) <= 2 AND http = 'N' AND connect < 10"]
# on boucles les hosts ci-dessus
                         while {[set row [::mysql::fetch $res]]!=""} {
# variables pour sortir l'host ( row un derrière l'id )
                         set hostcheck [lindex $row 1]
# on banni l'host
						 putdcc $discutea(idx) ":$discutea(link) TKL + G * $hostcheck $discutea(nick) [expr [unixtime] + 120] [unixtime] :Connexion refusé suite à l'activation du système de protection. Merci de retenter dans quelques minutes"
# on logs le ban
                         putdcc $discutea(idx) ":$discutea(nick) PRIVMSG $discutea(salon) :4Attaquant 1-> 14$hostcheck --> Gline add"
# on retir l'host de la base de donnée
						 mysqlexec $discutea(connect) "DELETE FROM ipcheck WHERE ip = '$hostcheck'"
						 }
# on purge la demande $res
						 mysqlendquery $res
					    }	
# si le système de secu est desactiver on cherche l'host dans la bdd
                            set result [mysqlquery $discutea(connect) "SELECT * FROM ipcheck WHERE ip= '$host2'"]
# si l'host n'existe pas
                            if {[set row [mysqlnext $result]] == ""} {
# on ajoute l'host en ne specifoant pas qu'il viens de l'applet
								mysqlexec $discutea(connect) "INSERT INTO ipcheck (ip) VALUES('$host2')"		                    
 								} else {
# si il existe on update le nombre de connexions si il la dernire fois qu'il est venu été ya plus d'une minute
								mysqlexec $discutea(connect) "UPDATE ipcheck SET connect=connect+1 WHERE TIMESTAMPDIFF(MINUTE, lastconnect, NOW()) >= 1 AND ip = '$host2'"		
								}
# on purge la demande $result
							mysqlendquery $result
                }
# si il y a une attaque 
			    if {[info exists discutea(maxthrottle)] || [info exists discutea(maxthrottle2)]} {
# on regarde si l'host eciste dans la bdd et si il a plus de 10 connexions ou si il est vanu par applet
                 set resu [mysqlquery $discutea(connect) "SELECT * FROM ipcheck WHERE ip= '$host2' AND (http = 'Y' OR connect > 10)"]
# si il n'i a pas de resultats
				 if {[set row [mysqlnext $resu]] == ""} {
# on ban
				 putdcc $discutea(idx) ":$discutea(link) TKL + G * $host2 $discutea(nick) [expr [unixtime] + 120] [unixtime] :Connexion refusé suite à l'activation du système de protection. Merci de retenter dans quelques minutes"
# on logs ca
                 putdcc $discutea(idx) ":$discutea(nick) PRIVMSG $discutea(salon) :4Attaquant $servs 1-> 14 $user !$ident@$host2: --> Gline add"
				 }
# on purge la demande
				 mysqlendquery $resu
				 }
# on ferme la connexion a la base de donnée
					mysqlclose $discutea(connect)
            }
		}
	}
 
 
 

je pense que j'ai rien oublier
le système s’améliorera de jours en jours
si vous avez besoin de plus d'aide vous pouvez poster ici ou nous rejoindre sur le salon #informatique de discutea.com

Cordialement

Dernière modification par sianur (10/03/2015 21:47:14)


Un jour j'irai vivre en Théorie, car en Théorie tout se passe bien.

Hors ligne

#2 07/03/2015 13:47:29

Harakiri
Administrateur
Lieu : Paris
Inscription : 02/07/2011
Messages : 260

Re : Anti Attaque PDO / PHP / TCL

Salut,

Merci pour le partage.
Si tu penses que le système est à améliorer de manière collaborative, je te recommande Github. Ca rendrait VRAIMENT plus simple son évolution.
Si tu crées un repository pour ce projet, en plus du fait de diposer d'un moyen très simple pour se procurer l'ensemble du code source, cela permet à tout le monde de participer au développement avec ton approbation.

Une peitte idée d'amélioration : rendre certains paramètres configurables (exemple : les 5 connexions en 2 secondes, ou le délai de ton point n°4).


EOF

Hors ligne

#3 07/03/2015 13:55:55

sianur
IRCzien en herbe
Lieu : dordogne
Inscription : 17/05/2013
Messages : 79
Site Web

Re : Anti Attaque PDO / PHP / TCL

Salut, Harakiri
je connais Github que de nom mais oui c'est une bonne idée je regarderai ça la semaine prochaine sinon oui tous le monde peut participer no soucis. Je regarderais ca pour les 2 variables aussi
Bon week


Un jour j'irai vivre en Théorie, car en Théorie tout se passe bien.

Hors ligne

#4 08/03/2015 04:45:39

Damien
Méchant Modérateur.
Lieu : Bruxelles
Inscription : 20/06/2011
Messages : 237
Site Web

Re : Anti Attaque PDO / PHP / TCL

Salut,

Je pense que certes le but du TCL est bien, mais, je pense que la sécurité qu'il procure pourrait assez facilement être cassée par une personne qui le voudrait.

Je prends l'exemple: le client fait en sorte que sa mauvaise ip tente une connexion à l'applet via la page de celle-ci, si j'en crois ton code dans ce cas, tu encodes l'ip en question dans une base de données... ok. Mais si l'utilisateur viendrait au même moment ou dans un (très) court délais à se connecter avec la même IP en dehors de l'applet? Quelle sera la réaction du système, puisque l'ip sera considérée comme... exceptée? Ou alors, j'ai (très) mal compris le code et les variables.

--> ça serait bien d'éventuellement essayer de commenté un peu le code, histoire de s'y retrouve plus facilement.

Ensuite, la science du "gethostbyaddr" n'est pas une science exacte non plus, car parfois les valeurs retournées ne sont pas équivalente, notamment selon les DNS que les serveurs utilisent et/ou les réponses, tandis que l'ip que le serveur web reçoit est en théorie, la même que le serveur IRC reçoit, sinon, tu as réellement un problème, donc il ne faudrait pas travailler avec les reverses DNS mais plutôt avec les IPs elle même.

D'ailleurs, l'ip possède un avantage supplémentaire: pouvoir utilisé le gzline (TKL + Z) et non le gline (TKL + G), la différence réside dans le fait que le premier ne laisse pas à l'IRCd le temps de résoudre l'IP pour obtenir le reverse pour pouvoir faire une comparaison, puisqu'on possède l'ip à bannir et l'ip que l'IRCd doit résoudre, tandis que dans le second cas, il faut que l'IRCd fasse une résolution DNS sur l'ip pour pouvoir faire la comparaison.

C'est des points assez bêtes, en soit, mais qui permettent une détection plus "safe" avec un usage de ressource moins intensif. Tu possèdes toujours l'ip quelque soit l'endroit où tu vérifies les données (côté IRC ou serveur web), ça te permet de faire moins de requêtes de résolution.

Autre petite "critique" si je puis dire, c'est l'usage du latin1 sur les données sql, quand on sait que les noms de domaine peuvent comportés de l'UTF-8.... ;-)

Il y en a sûrement d'autres encore, mais je pense déjà avoir quelques points à traités ainsi.

Ps: pour la fonction gethostbyaddr aucune activation ni configuration n'est nécessaire, c'est une fonction de base de PHP4/5, il suffit donc de juste posséder PHP actif : http://php.net/manual/fr/function.gethostbyaddr.php

Modo:: j'ai fais quelques rectifications sur ton post d'origine, pour quelques incohérences d'explication qui pourrait induire en erreur les personnes voulant l'utiliser.


En informatique il n'y a pas de mauvais outils, il n'y a que de mauvais utilisateurs. Le problème le plus récurrent est celui qui se trouve entre la chaise et le clavier.

Hors ligne

#5 08/03/2015 10:21:06

sianur
IRCzien en herbe
Lieu : dordogne
Inscription : 17/05/2013
Messages : 79
Site Web

Re : Anti Attaque PDO / PHP / TCL

Salut Damien
La fonctin gethstbyaddr fonctionne très bien sur mon serveur.

Ensuite pour la sécurité je vois bien comment connecté les ips une a une sur nos applets mais pour le cas d'un kiddies qui utilise une proxylist je vois pas comment il ferais un while sur l applet avec un post suffit d'intégrer l appel de la fonction au bonne endrois et d avoir une page qui renvoie pas des (variables inconnue)
En gros je concidere ton post plus ou moins inutiles

Pour le manque de commentaires je regarderai ça mais le code est simple suffit de lire les requêtes sql

Cordialement sianur


Un jour j'irai vivre en Théorie, car en Théorie tout se passe bien.

Hors ligne

#6 10/03/2015 21:48:20

sianur
IRCzien en herbe
Lieu : dordogne
Inscription : 17/05/2013
Messages : 79
Site Web

Re : Anti Attaque PDO / PHP / TCL

Salut

Commentaires ajoutés


Un jour j'irai vivre en Théorie, car en Théorie tout se passe bien.

Hors ligne

Pied de page des forums

448551 visites ( 122 aujourd'hui ) 3 visiteurs en ligne
Copyright © 2004 - 2013 IRCz