Archives pour la catégorie php

Documentation d’API automatique sur Symfony avec NelmioApiDoc

Plop à tous,

De retour en dev PHP, depuis quelques temps je me retrouve à faire des API sur Symfony (voir mon article sur FosRestBundle). Je cherchais un moyen d’automatiser la doc des API, mais aussi de pouvoir les tester côtés back sans avoir à faire de front, tout en ayant la possibilité d’utiliser des token d’authentifications, …

C’est justement ce que permet NelmioApiDoc !!

Continuer la lecture de Documentation d’API automatique sur Symfony avec NelmioApiDoc

monter un serveur PHP en une ligne de commande (ou presque)

Dans le genre « news de webg33k » en voici une …

A la base, je cherchais à utiliser/écrire un serveur http en python (pas mal de classes existent dans le domaine) pour servir une page html bidon après un man in the middle avec redirection dnspoof sur le serveur http en question, au lieu de déployer l’artillerie lourde apache ou nginx.
Continuer la lecture de monter un serveur PHP en une ligne de commande (ou presque)

Marre du spam sur wordpress ??

Plopinou …

Une rapide technique pour baisser d’un nombre assez important le spam sur un blog wordpress, en profitant de la gentillesse des spammers ^^.
En effet, la plupart du temps :

  • les ip tournent (donc impossible de bannir toutes les ip)
  • les adresses mails sont générées à la volées et comme c’est sur le domaine de gmail, bannir le domaine est impossible
  • Les commentaires changent …

Il reste donc une information qu’ils donnent, et qu’ils ne semblent pas changer … l’url de leurs sites, qui terminent toujours par « map.html » … sympa non ??

Donc pour leurs envoyer un message plein d’amour et de paix on peut gentillement modifier le fichier wp-comments-post.php : (après la ligne 38)
[sourcecode language=php]
if(preg_match("#^.*/map.html$#",$comment_author_url))
die("Go home and die!!!");
[/sourcecode]
Et voilà … 90% du spam de vos blogs devraient disparaitre. (reste plus qu’à trouver un filtre pour les casinos et on héradique toutes forme de spam sur les blogs ^^ (pas complexe je pense, mais ça fait un bail que j’en ai plus chopé donc je peux pas créer la regexp :D) ).

Petite note : J’ai testé le code ci-dessous pendant une journée et ma liste de commentaires indésirables est encore vide … ce qui est un miracle !!! Je chopais entre 25 et 50 spams par jour … (ok c’est pas beaucoup … mais c’est quand même ça de moins).

EDIT : Ne pas oublier de refaire la modification, après une mise à jour de wordpress (comme tous les fichiers sont réecrit, on perd les modifications et on remarque tout de suite le spam qui revient ;))

Administration de serveurs apache : modsecurity2

Bijour

Bé voilà vé parler du modsecurity2 … pourquoi ?? Ben on trouve pas mal de tut’s sur le net, mais c’est que pour le mod_security (sans le 2 ^^), et la syntaxe à malheureusement changée depuis.

Donc voilà …

Il faut tout d’abord rajouter un dépôt (le mien ^^) au fichier /etc/apt/sources.list :

deb http://ppa.launchpad.net/cipher.16/ppa/ubuntu intrepid main

et rajouter la clé associée au dépôt :

sudo apt-key adv --recv-keys --keyserver keyserver.ubuntu.com DA27D37831F6D1C0BC85566CDD2A2A8817FB9A87

Ensuite faire un apt-get install modsecurity2 && a2enmode mod-security2.

Pourquoi préférer cette version à celle de inittab (proposé par la doc de modsecurity) ?? … parce que c’est la dernière version stable (2.5.7, qui permet des trucs sympa … cf. la fin de l’article ;))

Par défaut, tous les fichiers de configuration liés au modsecurity2 sont bazardés dans le dossier /usr/share/apache/mod_security2_rules (je suis pas assez doué pour faire du post-install dans mes paquets …), vous pouvez soit les déplacer dans le dossier  /etc/apache2/conf.d/, mais il faudra un peu les retoucher (surtout le modsecurity_crs_10_config.conf en modifiant les fichiers de logs, sinon des erreurs apparaitront lors du démarrage du serveur).

Pour utiliser les fichiers de configuration fournit par le paquet :

cat /usr/share/apache2/mod_security2_rules/*.conf >> /etc/apache2/conf.d/security

et modifier toutes les lignes en rapport avec les logs, pour cela, remplacez :

SecAuditLog logs/modsec_audit.log par SecAuditLog /var/log/apaches2/modsec_audit.log
SecDebugLog logs/modsec_debug.log par SecDebugLog /var/log/apache2/modsec_debug.log

Ou bien, vous pouvez faire votre propre fichier de configuration, grâce à la superbe doc.

Pour cela, allez dans le dossier /etc/apache2/conf.d/ et modifiez le fichier security.conf, ou bien en créer un nommé … du nom que vous voulez.

Dans lequel il faudra mettre (au minimum, histoire de faire propre) :

<IfModule mod_security2.c>
ServerTokens Full
ServerSignature On
TraceEnable Off

SecRuleEngine On
SecRequestBodyAccess On
SecResponseBodyAccess On

SecAuditLog /var/log/apache2/mod_secure.log
## RESTE DE LA CONFIG A METTRE ICI

## NE PAS TOUCHER PLUS LOIN

Et on met quoi dans cette configuration ???

Plein de choses diverses et variées (on peut aussi rajouter quelque lignes des fichiers d’exemple dans /usr/share/apache2/mod_security2_rules, qui peuvent être très intéressante pour bloquer les injections, …).
Pour induire en erreurs/bloquer certains scanners :

Changement de la signature du serveur (un peu grossié ^^ mais ça peut induire en erreur les n00b … ça fait toujours ça de moins) :

SecServerSignature "Windows 2003 IIS/6.0"
SecRule REQUEST_HEADERS:User-Agent ".*perl.*" "t:none,msg:'Perl based user agent identified'"
SecRule REQUEST_HEADERS:User-Agent ".*nikto.*" "t:none,msg:'Nikto Scanners Identified'"
SecRule REQUEST_HEADERS:User-Agent "(?:\b(?:m(?:ozilla\/4\.0 \(compatible\)|etis)|webtrends security analyzer|pmafind)\b|n(?:-stealth|sauditor|essus|ikto)|b(?:lack ?widow|rutus|ilbo)|(?:jaascoi|paro)s|webinspect|\.nasl)" \
"phase:2,t:none,t:lowercase,deny,log,auditlog,status:404,msg:'Request Indicates a Security Scanner Scanned the Site',id:'990002',tag:'AUTOMATION/SECURITY_SCANNER',severity:'2'"
SecRule REQUEST_HEADERS_NAMES "\bacunetix-product\b" \
"phase:2,t:none,t:lowercase,deny,log,auditlog,status:404,msg:'Request Indicates a Security Scanner Scanned the Site',id:'990901',tag:'AUTOMATION/SECURITY_SCANNER',severity:'2'"
SecRule REQUEST_FILENAME "^/nessustest" \
"phase:2,t:none,t:lowercase,deny,log,auditlog,status:404,msg:'Request Indicates a Security Scanner Scanned the Site',id:'990902',tag:'AUTOMATION/SECURITY_SCANNER',severity:'2'"

Bloquer les requêtes zarb :

SecRule REQUEST_LINE "!(^((?:(?:pos|ge)t|head))|http/(0\.9|1\.0|1\.1)$)" \
"t:none,t:lowercase,msg:'Un imbécile qui connait pas le http'"

Bloquer les accès direct à l’ip du serveur : (cas courant de scan)

SecRule REQUEST_HEADERS:Host "^[\d\.]+$" \
"log,deny,status:404,t:lowercase,msg:'Connexion direct a l\'ip du serveur'"

Protection contre des fuites lors  d’erreurs mysql : (qui pourrait permettre à des petits malin de connaître les tables utilisées, …)

SecRule RESPONSE_BODY "(?:\b(?:(?:s(?:elect list because it is not contained in (?:an aggregate function and there is no|either an aggregate function or the) GROUP BY clause|upplied argument is not a valid (?:(?:M(?:S |y)|Postgre)SQL|O(?:racle|DBC)))|S(?:yntax error converting the \w+ value .*? to a column of data type|QL Server does not exist or access denied)|Either BOF or EOF is True, or the current record has been deleted(?:; the operation|\. Requested)|The column prefix .{0,50}? does not match with a table name or alias name used in the query|Could not find server '\w+' in sysservers\. execute sp_addlinkedserver)\b|Un(?:closed quotation mark before the character string\b|able to connect to PostgreSQL server:)|(?:Microsoft OLE DB Provider for .{0,30} [eE]rror |error '800a01b8)'|(?:Warning: mysql_connect\(\)|PostgreSQL query failed):|You have an error in your SQL syntax(?: near '|;)|cannot take a \w+ data type as an argument\.|incorrect syntax near (?:\'|the\b|@@error\b)|microsoft jet database engine error '8|ORA-\d{5}: )|\[Microsoft\]\[ODBC )" \
"phase:4,t:none,ctl:auditLogParts=+E,deny,log,auditlog,status:500,msg:'SQL Information Leakage',id:'970003',tag:'LEAKAGE/ERRORS',severity:'4'"

Protection contre des fuites concernant des erreurs php ou un affichage de code php (source code disclosure comme on dit :p) :

SecRule RESPONSE_BODY "<b>Warning<\/b>.{0,100}?:.{0,1000}?\bon line\b" \
"phase:4,t:none,ctl:auditLogParts=+E,deny,log,auditlog,status:500,msg:'PHP Information Leakage',id:'970009',tag:'LEAKAGE/ERRORS',severity:'4'"
SecRule RESPONSE_BODY "(?:\b(?:f(?:tp_(?:nb_)?f?(?:ge|pu)t|get(?:s?s|c)|scanf|write|open|read)|gz(?:(?:encod|writ)e|compress|open|read)|s(?:ession_start|candir)|read(?:(?:gz)?file|dir)|move_uploaded_file|(?:proc_|bz)open)|\$_(?:(?:pos|ge)t|session))\b" \
"phase:4,t:none,ctl:auditLogParts=+E,log,auditlog,msg:'PHP source code leakage',id:'970015',tag:'LEAKAGE/SOURCE_CODE',severity:'4'"
SecRule RESPONSE_BODY "<\?(?!xml)" \
"phase:4,chain,t:none,ctl:auditLogParts=+E,log,auditlog,msg:'PHP source code leakage',id:'970902',tag:'LEAKAGE/SOURCE_CODE',severity:'4'"
SecRule RESPONSE_BODY "!(?:\b(?:(?:i(?:nterplay|hdr|d3)|m(?:ovi|thd)|(?:ex|jf)if|f(?:lv|ws)|varg|cws)\b|r(?:iff\b|ar!B)|gif)|B(?:%pdf|\.ra)\b)" "t:none"

Protection contre les XSS :

SecRule REQUEST_FILENAME|ARGS|ARGS_NAMES|REQUEST_HEADERS|XML:/*|!REQUEST_HEADERS:Referer "@pm jscript onsubmit copyparentfolder javascript meta onmove onkeydown onchange onkeyup activexobject expression onmouseup ecmascript onmouseover vbscript: <![cdata[ http: settimeout onabort shell: .innerhtml onmousedown onkeypress asfunction: onclick .fromcharcode background-image: .cookie ondragdrop onblur x-javascript mocha: onfocus javascript: getparentfolder lowsrc onresize @import alert onselect script onmouseout onmousemove background application .execscript livescript: getspecialfolder vbscript iframe .addimport onunload createtextrange onload <input" \
"phase:2,t:none,t:urlDecodeUni,t:htmlEntityDecode,t:compressWhiteSpace,t:lowercase,pass,nolog,skip:1"
SecAction phase:2,pass,nolog,skipAfter:959004
SecRule REQUEST_FILENAME|ARGS|ARGS_NAMES "(?:\b(?:(?:type\b\W*?\b(?:text\b\W*?\b(?:j(?:ava)?|ecma|vb)|application\b\W*?\bx-(?:java|vb))script|c(?:opyparentfolder|reatetextrange)|get(?:special|parent)folder|iframe\b.{0,100}?\bsrc)\b|on(?:(?:mo(?:use(?:o(?:ver|ut)|down|move|up)|ve)|key(?:press|down|up)|c(?:hange|lick)|s(?:elec|ubmi)t|(?:un)?load|dragdrop|resize|focus|blur)\b\W*?=|abort\b)|(?:l(?:owsrc\b\W*?\b(?:(?:java|vb)script|shell|http)|ivescript)|(?:href|url)\b\W*?\b(?:(?:java|vb)script|shell)|background-image|mocha):|s(?:(?:tyle\b\W*=.*\bexpression\b\W*|ettimeout\b\W*?)\(|rc\b\W*?\b(?:(?:java|vb)script|shell|http):)|a(?:ctivexobject\b|lert\b\W*?\(|sfunction:))|<(?:(?:body\b.*?\b(?:backgroun|onloa)d|input\b.*?\btype\b\W*?\bimage)\b| ?(?:(?:script|meta)\b|iframe)|!\[cdata\[)|(?:\.(?:(?:execscrip|addimpor)t|(?:fromcharcod|cooki)e|innerhtml)|\@import)\b)" \
"phase:2,capture,t:none,t:htmlEntityDecode,t:compressWhiteSpace,t:lowercase,ctl:auditLogParts=+E,log,auditlog,msg:'Cross-site Scripting (XSS) Attack',id:'950004',tag:'WEB_ATTACK/XSS',logdata:'%{TX.0}',severity:'2'"
SecRule REQUEST_HEADERS|XML:/*|!REQUEST_HEADERS:Referer "(?:\b(?:(?:type\b\W*?\b(?:text\b\W*?\b(?:j(?:ava)?|ecma|vb)|application\b\W*?\bx-(?:java|vb))script|c(?:opyparentfolder|reatetextrange)|get(?:special|parent)folder|iframe\b.{0,100}?\bsrc)\b|on(?:(?:mo(?:use(?:o(?:ver|ut)|down|move|up)|ve)|key(?:press|down|up)|c(?:hange|lick)|s(?:elec|ubmi)t|(?:un)?load|dragdrop|resize|focus|blur)\b\W*?=|abort\b)|(?:l(?:owsrc\b\W*?\b(?:(?:java|vb)script|shell|http)|ivescript)|(?:href|url)\b\W*?\b(?:(?:java|vb)script|shell)|background-image|mocha):|s(?:(?:tyle\b\W*=.*\bexpression\b\W*|ettimeout\b\W*?)\(|rc\b\W*?\b(?:(?:java|vb)script|shell|http):)|a(?:ctivexobject\b|lert\b\W*?\(|sfunction:))|<(?:(?:body\b.*?\b(?:backgroun|onloa)d|input\b.*?\btype\b\W*?\bimage)\b| ?(?:(?:script|meta)\b|iframe)|!\[cdata\[)|(?:\.(?:(?:execscrip|addimpor)t|(?:fromcharcod|cooki)e|innerhtml)|\@import)\b)" \
"phase:2,capture,t:none,t:urlDecodeUni,t:htmlEntityDecode,t:compressWhiteSpace,t:lowercase,ctl:auditLogParts=+E,log,auditlog,msg:'Cross-site Scripting (XSS) Attack',id:'959004',tag:'WEB_ATTACK/XSS',logdata:'%{TX.0}',severity:'2'"

Et les petits trucs que nous permettent de faire la version 2.5.7 :
(protection contre les bruteforces, il faudra bien sûr changer ARGS:login en fonction de vos champs d’authentification).

SecAction initcol:ip=%{REMOTE_ADDR},nolog
SecRule ARGS:login "!^$" \
nolog,phase:1,setvar:ip.auth_attempt=+1,deprecatevar:ip.auth_attempt=20/120
SecRule IP:AUTH_ATTEMPT "@gt 25" \
log,drop,phase:1,msg:'Possible Brute Force Attack"

Une fois que vous avez terminé votre fichier de configuration, n’oubliez pas le /etc/init.d/apache2 restart
Sinon, comme dit, ce ne sont que des exemples, … la doc est très complète : http://www.modsecurity.org/documentation/

Se monter un environnement de developpement LAMP rapidement

Bonjour à tous et bonne fêtes de fin d’années …

Rapidement, le thème du jour : se monter un environnement de développement LAMP (pour dev en PHP ou …) proprement, avec une config DNS qui claque sa race ^^, juste histoire de revoir les « basiques » des serveurs DNS et d’un serveur apache.

L’idée étant que l’on ai des sous-domaines par projet du genre :

http://projet1.monpc.lan ou http://projet2.monpc.lan

Généré de façon dynamique, sans avoir à toucher à la config de son serveur à chaque nouveau projet, histoire de développer de façon rapide et propre, au lieu de tous stocker à la barbare pour accéder à ses sites en développement via http://localhost/projet1/module2/fichier3.php ou des urls à rallonge … Quoique l’on déporte le contenu du premier / au sous-domaine, mais bon, faut avouer qu’accéder à son site via http://localhost/projet au lieu de http://projet.monsite.org c’est moins sexy!!

(L’idée étant repiqué de mon environnement de travail chez advisa, que j’ai adopté pour développer mes projets perso,et aussi histoire de faire croire que j’ai le net dans le train).

Donc voilà … sous un système debian, on installe apache2, le module PHP, une base de données mysql, le serveur de NDD Bind9, ce qui donne la commande :

apt-get install phpmyadmin mysql-server bind9

Les dépendances de phpmyadmin étant le serveur apache et … ça raccourci pas mal la commande ;).

Pour ma part, je veux accéder à mon environnement de dev sur le nom de domaine : portable.lan, je modifie donc le fichier /etc/bind/named.conf pour rajouter :

zone « portable.lan » {
type master;
file « /etc/bind/db.portable.lan »;
};

avant la ligne contenant : include « /etc/bind/named.conf.local »;

et je créer le fichier /etc/bind/db.portable.lan contenant ce qui suit :

$TTL 3h
@       IN      SOA     ns.portable.lan. hostmaster.portable.lan. (
2005090201
8H
2H
1W
1D )

@       IN      NS      ns.portable.lan.

A       127.0.0.1
ns              A       127.0.0.1
*.portable.lan. IN      A       127.0.0.1

Qui aura pour effet de rediriger toutes les requêtes DNS à destination de portable.lan (www.portable.lan, …) à l’adresse IP 127.0.0.1, mais pour utiliser ce serveur de nom, il faut tout d’abort recharger la zone DNS :

/etc/init.d/bind9 reload

et modifier le fichier /etc/resolv.conf et rajouter ce qui suit :

nameserver 127.0.0.1

et malheureusement là … ce fichier est réécrit à chaque redémarrage, il faut donc modifier le fichier /etc/dhcp3/dhclient.conf et dé-commenter la ligne (en enlevant le # devant) :

prepend domain-name-servers 127.0.0.1;

qui aura pour effet de rajouter le serveur DNS 127.0.0.1 à chaque démarrage de la machine.

Maintenant, il faut configurer le serveur apache, très rapidement, on fait un :

a2enmod vhost_alias

pour rajouter le mod vhost_alias. Puis on modifie le fichier /etc/apache2/sites-enabled/000-default en changeant la ligne :

DocumentRoot /var/www

par :

VirtualDocumentRoot /var/www/%1

qui permettra, lorsque l’on se connecte à http://projet1.portable.lan d’utiliser le répertoire /var/www/projet1comme répertoire par défaut, par contre, il ne faut pas oublier de créer le répertoire www et portable, car si l’on tente de se connecter à http://www.portable.lan, le serveur apache cherchera le dossier /var/www/www ou pour http://portable.lan de chercher le dossier /var/www/portable … logique ^^.

et enfin, on redémarre le serveur apache :

/etc/init.d/apache2 restart

Voilà … c’est terminé ;), par contre, vous remarquerez que pour se connecter à phpmyadmin, on ne doit pas faire http://phpmyadmin.portable.lan, mais bien http://portable.lan/phpmyadmin, pourquoi??

Dans la config d’apache, il on généré un <Location> lors de l’installation, à la place d’un simple dossier dans le dossier /var/www, ce qui a pour effet d’ignorer notre superbe configuration, si ça vous dérange, vous pouvez créer un lien symbolique vers le dossier de phpmyadmin (/usr/share si mes souvenirs sont bon) depuis /var/www.

Voilà … c’était votre cadeaux de noël 😉

Mon dépôt SVN de sources inutiles

Bijour à vous en ce Dimanche ensoleillé … ou pas.

J’ai pas grand chose d’intéressant à poster aujourd’hui, sinon, l’ouverture de mon dépôt SVN (sous licence MIT, car je repique du GPL et avec la baisse du prix du Gazole ^^ … sinon, la licence wtfpl m’aurait bien plu, mais google n’a pas l’air de la proposer) avec :

  • Les sources PHP du script de SMS Alert (de macsim, réécrit pour se passer de Curl) du service de google calendar (qui ne marche plus parce google l’a bloqué :-s bande de *$!#@).
  • Ma classe http (qui permet de se passer de la librairie Curl).
  • Les sources PHP du script msn.class.php de Tommy Wu pour ne plus utiliser Curl … encore ^^. (le script est compatible MSNP9 et 15, mais le 15 à encore besoin de Curl … utiliser Curl pour du SOAP parce que M$ ne fournit pas de WSDL … faut le faire !! Bande de N00b).
  • Et surement plein d’autre trucs inutile à venir.

Et ouai … j’ai pas fait grand chose d’intéressant ce week-end.

Sinon, quelques liens intéresant :

Un lien qui recense pas mal de failles qu’il est possible d’exploiter en PHP (ex : bypass du safe-mode en 5.1, …).

Un fournisseur de certificats personnels gratuit et super rapide (à cause d’un TP de système sur la sécurité des réseaux, pour lequel il nous fallait un certificat X509).