Skip to content

Latest commit

 

History

29 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 

Repository files navigation

Sumary

The Forminator Forms – Contact Form, Payment Form & Custom Form Builder plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the form_name parameter in all versions up to, and including, 1.50.2 due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with administrator-level access, to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page. The plugin allows admins to give form management permissions to lower level users, which could make this exploitable by users such as subscribers.

Root cause

The Root cause is something that need a finesse of logic bug awareness: (This function in file /fields/html.php)

public function markup( $field, $views_obj ) {
        $settings = $views_obj->model->settings;

        $html    = '';
        $label   = esc_html( self::get_property( 'field_label', $field ) );
        $id      = self::get_property( 'element_id', $field );
        $form_id = false;

        $html .= '<div class="forminator-field forminator-merge-tags" data-field="' . $id . '">';

        if ( $label ) {

            $html .= sprintf(
                '<label class="forminator-label">%s</label>',
                self::convert_markdown( $label )
            );
        }

            // Check if form_id exist.
        if ( isset( $settings['form_id'] ) ) {
            $form_id = $settings['form_id'];
        }

        // To allow iframes in content.
        add_filter( 'wp_kses_allowed_html', array( 'Forminator_Core', 'add_iframe_to_kses_allowed_html' ) );
        $content = wp_kses_post( self::get_property( 'variations', $field ) );  // root cause here
        remove_filter( 'wp_kses_allowed_html', array( 'Forminator_Core', 'add_iframe_to_kses_allowed_html' ) );

        $html .= forminator_replace_variables(
            $content,
            $form_id
        );

        $html .= '</div>';

        return $html;
    }

This code right here use a sanitize function (wp_kses_post) to protect XSS from lower privilege user, but the problem is, it sanitized before replacing variables. As the result, the attacker with appropriate privilege can use a valid HTML tags to bypass wp_kses_post and inject the JavaScript payload into the variables in order to trigger XSS.

Proof-of-concept

Attacker with Edit Form privilege can insert a HTML in HTML field look like this

<iframe src="{form_name}"></iframe>

And then change the form_name to

javascript:alert(1) or javascript:<Payload>

Severity

Score Severity Version Vector String
4.4 MEDIUM 3.1 CVSS:3.1/AV:N/AC:H/PR:H/UI:N/S:C/C:L/I:L/A:N

In my opinion, this bug here although doesn’t have great serverity, but it requires finesse of awareness in logic and code review, as you can see with just a small mistake between two lines of code and it create a vulnerability. poc

Note

If you vibe with this kind of research and want to support more digging, you can donate and support me. I appreciate with your contributing.

╰(°▽°)╯

About

CVE-2026-2002 writeup and Proof-of-concept

Topics

Resources

Stars

11 stars

Watchers

1 watching

Forks

Releases

Sponsor this project

Packages

Contributors