Un administrator care a avut acces la server ar fi putut vedea conținutul fișierului wp-config.php, inclusiv secretele folosite de WordPress pentru autentificare. După încheierea colaborării, schimbarea parolei contului său nu rezolvă singură această expunere: trebuie revocate metodele de acces, apoi regenerate cele opt chei și săruri WordPress fără a le afișa în terminal sau în loguri.
La finalul procedurii, fostul cont este eliminat cu articolele realocate, parolele de aplicație sunt revocate, iar wp config shuffle-salts înlocuiește secretele din wp-config.php. Cookie-urile de autentificare existente devin nevalide, toți utilizatorii trebuie să se conecteze din nou, iar site-ul rămâne funcțional. Scenariul acoperă un site WordPress individual, nu o rețea Multisite.
Fixăm intervenția la un site administrat prin WP-CLI
Exemplul folosește Ubuntu Server 24.04 LTS, PHP 8.3 și WP-CLI 2.12.0. Site-ul se află în /var/www/example.com/public, iar fișierele sale sunt deținute de utilizatorul dedicat wp-example. Domeniul example.com este rezervat documentației; înlocuiește-l cu domeniul propriu.
Ai nevoie de acces sudo, de un cont WordPress administrator care rămâne în firmă și de aproximativ 30 de minute. Operațiunea nu cere oprirea PHP-FPM sau a serverului web, dar îi va deconecta pe toți utilizatorii autentificați. Anunță echipa și evită intervalele în care editorii lucrează la formulare nesalvate.
Verifică mediul fără să citești conținutul wp-config.php:
cat /etc/os-release
php --version | head -n 1
wp --info
sudo -u wp-example -- wp --path=/var/www/example.com/public core version
sudo -u wp-example -- wp --path=/var/www/example.com/public core is-installed
sudo stat -c 'proprietar=%U grup=%G permisiuni=%a fișier=%n'
/var/www/example.com/public/wp-config.php
Un rezultat compatibil arată astfel; versiunile patch și calea executabilului pot diferi:
PRETTY_NAME="Ubuntu 24.04 LTS"
PHP 8.3.x (cli)
WP-CLI version: 2.12.0
6.x sau o versiune ulterioară instalată
proprietar=wp-example grup=www-data permisiuni=640 fișier=/var/www/example.com/public/wp-config.php
Mesajul Success: WordPress is installed. confirmă că --path indică instalarea corectă. Permisiunea 640 este potrivită numai dacă proprietarul poate scrie fișierul, iar grupul serverului web are nevoie să-l citească. Documentația WordPress recomandă ca wp-config.php să poată fi citit doar de proprietar și, dacă arhitectura o cere, de serverul web.
Pachetele locale folosite de procedură se instalează într-un singur pas:
sudo apt update
sudo apt install --yes ca-certificates php-cli
ca-certificates permite validarea conexiunii HTTPS către serviciul oficial care furnizează valori aleatoare, iar php-cli verifică sintaxa configurației. WP-CLI trebuie instalat conform instrucțiunilor oficiale și disponibil prin comanda wp; nu descărca executabile din surse neoficiale.
Dacă serverul găzduiește mai multe instalări, separarea utilizatorilor și a pool-urilor PHP-FPM reduce accesul transversal la configurații. Procedura este explicată în ghidul despre izolarea site-urilor WordPress cu PHP-FPM.
Păstrăm doar trei artefacte și nu copiem secretele în consolă
Intervenția folosește următoarea structură:
/var/www/example.com/public/wp-config.php
Configurația activă a site-ului; valorile secrete nu sunt afișate.
/usr/local/sbin/rotate-wordpress-salts
Scriptul executat de root, care verifică, salvează și rotește valorile.
/var/backups/wordpress/example.com/
Director accesibil doar root, în care se păstrează copia anterioară.
Copia nu trebuie salvată în directorul public al site-ului și nici într-un ticket, e-mail sau repository Git. Ea conține credențialele bazei de date și vechile chei, chiar dacă tutorialul nu le afișează.
Pasul 1 — Identificăm contul plecat și administratorul care preia conținutul
De ce: înaintea oricărei ștergeri trebuie să confirmi că lucrezi pe site-ul corect și că există un administrator nominal care va primi articolele fostului coleg.
În exemplu, contul plecat este fost-admin, iar cel rămas este admin-operational. Înlocuiește aceste două valori cu numele reale de autentificare:
SITE_PATH='/var/www/example.com/public'
FORMER_LOGIN='fost-admin'
SUCCESSOR_LOGIN='admin-operational'
sudo -u wp-example -- wp --path="$SITE_PATH" option get siteurl
sudo -u wp-example -- wp --path="$SITE_PATH" user list
--role=administrator
--fields=ID,user_login,display_name
--format=table
FORMER_ID="$(
sudo -u wp-example -- wp --path="$SITE_PATH" user get "$FORMER_LOGIN" --field=ID
)"
SUCCESSOR_ID="$(
sudo -u wp-example -- wp --path="$SITE_PATH" user get "$SUCCESSOR_LOGIN" --field=ID
)"
printf 'Cont retras: ID %snCont succesor: ID %sn'
"$FORMER_ID" "$SUCCESSOR_ID"
option get siteurl previne intervenția pe alt site. --fields limitează tabelul la datele necesare, iar --field=ID furnizează identificatorul pe care îl cer comenzile următoare.
Exemplu de rezultat:
https://example.com
+----+-------------------+----------------------+
| ID | user_login | display_name |
+----+-------------------+----------------------+
| 7 | fost-admin | Administrator extern |
| 12 | admin-operational | Echipa operațională |
+----+-------------------+----------------------+
Cont retras: ID 7
Cont succesor: ID 12
Punct de control: dacă domeniul, numele sau rolurile nu corespund, oprește-te și verifică valoarea SITE_PATH; nu presupune identitatea unei persoane doar după numele afișat.
Pasul 2 — Revocăm parolele de aplicație și sesiunile fostului administrator
De ce: rotirea sărurilor invalidează cookie-urile WordPress, dar nu trebuie tratată ca înlocuitor pentru revocarea celorlalte credențiale. Application Passwords sunt credențiale distincte folosite, de exemplu, de integrări prin REST API.
Listează întâi parolele de aplicație fără a afișa secretul inițial, apoi revocă-le și distruge sesiunile contului:
SITE_PATH='/var/www/example.com/public'
FORMER_LOGIN='fost-admin'
FORMER_ID="$(
sudo -u wp-example -- wp --path="$SITE_PATH" user get "$FORMER_LOGIN" --field=ID
)"
sudo -u wp-example -- wp --path="$SITE_PATH"
user application-password list "$FORMER_ID"
--fields=uuid,name,created,last_used
--format=table
sudo -u wp-example -- wp --path="$SITE_PATH"
user application-password delete "$FORMER_ID" --all
sudo -u wp-example -- wp --path="$SITE_PATH"
user session destroy "$FORMER_ID" --all
Câmpurile name, created și last_used ajută la identificarea integrărilor care trebuie mutate pe un cont tehnic controlat de firmă. Opțiunea --all revocă toate parolele de aplicație, respectiv toate sesiunile asociate utilizatorului indicat.
Exemplu de confirmare:
Success: All application passwords deleted.
Success: Destroyed all sessions for user 7.
Formularea exactă poate varia între versiunile WP-CLI, dar fiecare comandă trebuie să se încheie cu Success și un cod de ieșire zero.
Punct de control: dacă o integrare legitimă se oprește după revocare, creează ulterior o credențială nouă pentru un cont dedicat; nu reactiva parola fostului administrator.
Pasul 3 — Ștergem contul fără să ștergem articolele publicate
De ce: păstrarea unui cont inactiv cu rol de administrator creează o cale inutilă de revenire. WordPress poate realoca articolele către administratorul care rămâne.
Avertisment: comanda următoare șterge utilizatorul. Confirmă încă o dată cele două ID-uri și existența unui backup al bazei de date înainte de execuție.
SITE_PATH='/var/www/example.com/public'
FORMER_LOGIN='fost-admin'
SUCCESSOR_LOGIN='admin-operational'
FORMER_ID="$(
sudo -u wp-example -- wp --path="$SITE_PATH" user get "$FORMER_LOGIN" --field=ID
)"
SUCCESSOR_ID="$(
sudo -u wp-example -- wp --path="$SITE_PATH" user get "$SUCCESSOR_LOGIN" --field=ID
)"
printf 'Va fi șters ID %s; conținutul ajunge la ID %s.n'
"$FORMER_ID" "$SUCCESSOR_ID"
sudo -u wp-example -- wp --path="$SITE_PATH"
user delete "$FORMER_ID"
--reassign="$SUCCESSOR_ID"
--yes
if sudo -u wp-example -- wp --path="$SITE_PATH"
user get "$FORMER_LOGIN" >/dev/null 2>&1; then
printf 'EROARE: contul există încă.n' >&2
exit 1
fi
printf 'OK: contul retras nu mai există.n'
--reassign mută conținutul către ID-ul succesorului, iar --yes confirmă operațiunea fără un prompt interactiv. Acțiunea nu înlocuiește verificarea accesului SSH, a panoului de hosting, a registrarului, a CDN-ului, a copiilor de siguranță și a conturilor de e-mail.
Rezultatul așteptat este:
Success: Removed user 7 from https://example.com.
OK: contul retras nu mai există.
Punct de control: dacă WP-CLI raportează că utilizatorul nu poate fi șters sau că ID-ul de realocare nu există, nu relansa comanda cu alte valori până nu verifici tabelul de administratori.
Pasul 4 — Scriem un script care rotește opt secrete fără să le afișeze
De ce: editarea manuală poate lăsa o cheie veche, poate introduce o eroare PHP sau poate copia secretele în istoricul terminalului. Scriptul verifică toate cele opt constante, creează o copie protejată și restaurează configurația dacă rotația ori validarea eșuează.
Fișierul /usr/local/sbin/rotate-wordpress-salts trebuie creat integral:
sudo tee /usr/local/sbin/rotate-wordpress-salts >/dev/null <<'BASH'
#!/usr/bin/env bash
set -euo pipefail
SITE_PATH='/var/www/example.com/public'
SITE_USER='wp-example'
CONFIG="${SITE_PATH}/wp-config.php"
BACKUP_DIR='/var/backups/wordpress/example.com'
WP_BIN="$(command -v wp)"
STAMP="$(date -u +%Y%m%dT%H%M%SZ)"
BACKUP="${BACKUP_DIR}/wp-config.php.${STAMP}"
KEYS=(
AUTH_KEY
SECURE_AUTH_KEY
LOGGED_IN_KEY
NONCE_KEY
AUTH_SALT
SECURE_AUTH_SALT
LOGGED_IN_SALT
NONCE_SALT
)
fail() {
printf 'EROARE: %sn' "$1" >&2
exit 1
}
restore_backup() {
cp --archive -- "$BACKUP" "$CONFIG"
printf 'EROARE: rotația a eșuat; copia %s a fost restaurată.n'
"$BACKUP" >&2
}
[[ "${EUID}" -eq 0 ]] || fail 'rulează scriptul cu sudo.'
[[ -f "$CONFIG" ]] || fail "lipsește ${CONFIG}."
id "$SITE_USER" >/dev/null 2>&1 || fail "lipsește utilizatorul ${SITE_USER}."
[[ "$(stat -c '%U' "$CONFIG")" == "$SITE_USER" ]] ||
fail "wp-config.php nu este deținut de ${SITE_USER}."
sudo -u "$SITE_USER" -- test -w "$CONFIG" ||
fail "wp-config.php nu poate fi scris de ${SITE_USER}."
for key in "${KEYS[@]}"; do
if ! sudo -u "$SITE_USER" -- "$WP_BIN" --path="$SITE_PATH"
config has "$key"; then
fail "lipsește constanta ${key}."
fi
done
install -d -o root -g root -m 0700 "$BACKUP_DIR"
cp --archive -- "$CONFIG" "$BACKUP"
if ! php -l "$CONFIG"; then
fail 'configurația inițială nu trece verificarea PHP.'
fi
BEFORE_HASH="$(sha256sum "$CONFIG" | cut -d' ' -f1)"
if ! sudo -u "$SITE_USER" -- "$WP_BIN" --path="$SITE_PATH"
config shuffle-salts; then
restore_backup
exit 1
fi
if ! php -l "$CONFIG"; then
restore_backup
exit 1
fi
for key in "${KEYS[@]}"; do
if ! sudo -u "$SITE_USER" -- "$WP_BIN" --path="$SITE_PATH"
config has "$key"; then
restore_backup
exit 1
fi
done
AFTER_HASH="$(sha256sum "$CONFIG" | cut -d' ' -f1)"
[[ "$BEFORE_HASH" != "$AFTER_HASH" ]] || {
restore_backup
fail 'fișierul nu s-a modificat.'
}
printf 'OK: cele opt chei și săruri au fost rotite.n'
printf 'Backup protejat: %sn' "$BACKUP"
BASH
sudo chown root:root /usr/local/sbin/rotate-wordpress-salts
sudo chmod 0750 /usr/local/sbin/rotate-wordpress-salts
sudo bash -n /usr/local/sbin/rotate-wordpress-salts
set -euo pipefail oprește scriptul la o comandă eșuată, la o variabilă nedefinită sau la o eroare ascunsă într-un pipeline. config has confirmă existența constantelor fără să le imprime valorile. Hash-urile sunt comparate în memorie și nu sunt afișate.
wp config shuffle-salts rotește implicit cheile și sărurile standard WordPress. Nu utiliza opțiunea --insecure: aceasta ar dezactiva verificarea TLS, mascând o problemă de certificate.
Comanda bash -n nu modifică site-ul; validează sintaxa scriptului. Lipsa oricărui mesaj indică succes.
Punct de control: dacă bash -n afișează o linie cu eroare, nu executa scriptul și compară fișierul cu blocul complet de mai sus.
Pasul 5 — Executăm rotația și acceptăm deconectarea globală
De ce: numai acum, după revocarea accesului individual și validarea scriptului, înlocuim secretele care protejează cookie-urile și nonce-urile WordPress.
Salvează orice formular deschis în WordPress înainte de comandă:
sudo /usr/local/sbin/rotate-wordpress-salts
Exemplu de rezultat:
No syntax errors detected in /var/www/example.com/public/wp-config.php
Success: Shuffled the salt keys.
No syntax errors detected in /var/www/example.com/public/wp-config.php
OK: cele opt chei și săruri au fost rotite.
Backup protejat: /var/backups/wordpress/example.com/wp-config.php.20261002T090000Z
Momentul din numele copiei va fi diferit. În urma schimbării, sesiunile autentificate anterior nu mai trebuie acceptate. Utilizatorii vor vedea din nou formularul de login, iar formularele deschise înaintea rotației pot cere reîncărcarea paginii.
Această măsură completează, nu înlocuiește, controalele descrise în ghidul despre securizarea unui site WordPress în prima zi, precum conturile nominale, actualizările și backupul verificat.
Punct de control: dacă WP-CLI nu poate contacta serviciul de generare, rezolvă DNS-ul, ora sistemului sau certificatele CA și repetă procedura; nu copia săruri dintr-un generator neoficial.
Confirmăm site-ul, loginul nou și respingerea cookie-ului vechi
Deschide înaintea rotației o sesiune autentificată într-un browser separat. După execuție, reîncarcă acea pagină: WordPress trebuie să ceară din nou autentificarea.
Apoi rulează testul de capăt:
SITE_PATH='/var/www/example.com/public'
sudo -u wp-example -- wp --path="$SITE_PATH" core is-installed
sudo -u wp-example -- wp --path="$SITE_PATH" option get siteurl
sudo -u wp-example -- wp --path="$SITE_PATH" user list
--role=administrator
--fields=ID,user_login
--format=table
curl --silent --show-error --output /dev/null
--write-out 'HTTP %{http_code}n'
https://example.com/
Rezultatul așteptat pentru scenariul nostru este:
Success: WordPress is installed.
https://example.com
+----+-------------------+
| ID | user_login |
+----+-------------------+
| 12 | admin-operational |
+----+-------------------+
HTTP 200
Un răspuns 301 sau 302 poate fi legitim dacă domeniul redirecționează către adresa canonică. Verifică destinația cu curl --location și confirmă că răspunsul final este cel configurat de site.
Autentifică-te cu administratorul rămas, deschide o pagină de administrare și salvează un draft de test. Nu verifica rotația prin afișarea constantelor: faptul că valorile există, hash-ul fișierului s-a schimbat și vechiul cookie a fost respins este suficient.
Cinci mesaje care localizează problema
EROARE: rulează scriptul cu sudo. apare când scriptul nu are dreptul de a crea backupul protejat. Rulează sudo /usr/local/sbin/rotate-wordpress-salts.
EROARE: lipsește /var/www/example.com/public/wp-config.php. indică o cale greșită. Localizează instalarea prin configurația serverului web și corectează SITE_PATH; nu căuta global afișând conținutul fișierelor.
EROARE: wp-config.php nu este deținut de wp-example. arată că modelul de proprietate diferă. Verifică stat și identifică utilizatorul real de deployment. Nu aplica automat chmod 777 și nu schimba proprietarul fără să înțelegi configurația PHP-FPM.
EROARE: lipsește constanta AUTH_KEY. — sau alt nume din listă — înseamnă că fișierul nu conține setul standard complet. Oprește intervenția și verifică dacă secretele sunt încărcate din variabile de mediu ori din alt fișier; shuffle-salts nu trebuie forțat peste o arhitectură necunoscută.
EROARE: rotația a eșuat; copia ... a fost restaurată. apare dacă WP-CLI sau verificarea PHP eșuează după backup. Rulează din nou php -l și verifică accesul HTTPS către api.wordpress.org. Nu folosi --insecure pentru a ocoli o eroare de certificat.
Restaurăm numai dacă configurația nu mai poate fi încărcată
Deconectarea utilizatorilor nu este motiv de rollback; acesta este rezultatul urmărit. Restaurarea vechilor săruri poate face din nou acceptabile cookie-uri vechi, de aceea copia se folosește doar temporar dacă site-ul nu mai poate încărca configurația.
Pentru a identifica cea mai recentă copie fără a-i afișa conținutul:
BACKUP="$(
sudo find /var/backups/wordpress/example.com
-maxdepth 1 -type f -name 'wp-config.php.*'
-printf '%T@ %pn' |
sort -nr |
head -n 1 |
cut -d' ' -f2-
)"
printf 'Copia selectată: %sn' "$BACKUP"
Avertisment: restaurarea reactivează vechile valori. Fă operațiunea doar cât repari problema, apoi rulează din nou rotația înainte de a considera intervenția închisă.
sudo cp --archive -- "$BACKUP"
/var/www/example.com/public/wp-config.php
sudo php -l /var/www/example.com/public/wp-config.php
sudo /usr/local/sbin/rotate-wordpress-salts
După ce site-ul a funcționat stabil și backupul general al firmei a rulat, scriptul și copia punctuală pot fi eliminate.
Avertisment: comenzile următoare șterg artefactele create în tutorial, nu configurația activă:
sudo rm -- /usr/local/sbin/rotate-wordpress-salts
sudo rm -- "$BACKUP"
sudo rmdir /var/backups/wordpress/example.com 2>/dev/null || true
Nu dezinstala php-cli sau ca-certificates de pe un server WordPress de producție doar pentru că intervenția s-a încheiat; pot fi folosite de mentenanță și de alte componente.
Lista de control pentru închiderea accesului
- ☐ Domeniul returnat de
wp option get siteurleste cel vizat. - ☐ Există un administrator nominal care rămâne în firmă.
- ☐ Application Passwords ale fostului administrator au fost revocate.
- ☐ Sesiunile fostului administrator au fost distruse.
- ☐ Contul plecat a fost șters, iar conținutul a fost realocat.
- ☐ Cele opt constante există fără ca valorile lor să fi fost afișate.
- ☐
php -lconfirmă sintaxa fișieruluiwp-config.php. - ☐ O sesiune deschisă înaintea rotației este trimisă la login.
- ☐ Administratorul rămas se poate autentifica și salva un draft.
- ☐ Accesul SSH, hostingul, registrarul, CDN-ul și backupurile au fost verificate separat.
Următorul proiect logic este mutarea automatizărilor de pe conturile personale pe conturi tehnice cu drepturi minime. Pentru echipele care administrează mai multe site-uri, aceeași rotație poate fi inclusă într-un runbook de offboarding, cu inventarul domeniilor și o confirmare separată pentru fiecare instalare.
Întrebări frecvente
Rotirea sărurilor îi deconectează și pe administratorii care rămân?
Da. Cookie-urile autentificate anterior nu mai sunt acceptate, astfel că toți utilizatorii trebuie să se conecteze din nou.
Trebuie să copiez noile valori din generatorul WordPress?
Nu. wp config shuffle-salts le generează și le scrie fără să fie nevoie să le copiezi sau să le afișezi în terminal.
Rotirea sărurilor revocă și Application Passwords?
Nu trebuie presupus acest lucru. Tutorialul le listează și le șterge explicit înainte de rotație, deoarece sunt credențiale distincte de cookie-urile browserului.
Pot restaura copia dacă utilizatorii au fost deconectați?
Nu doar din acest motiv. Deconectarea este efectul urmărit, iar revenirea la vechile valori poate face din nou utilizabile cookie-uri anterioare.
Surse
- wp config shuffle-salts — WP-CLI Command — <>
- Editing wp-config.php — WordPress Advanced Administration Handbook — <>
- Hardening WordPress — WordPress Advanced Administration Handbook — <>
- wp_salt() — WordPress Developer Resources — <>
- wp user session destroy — WP-CLI Command — <>
- wp user application-password delete — WP-CLI Command — <>

















































