Tai jau kelių mėnesių, kai mano blogas nepateikia naujų pranešimų.
Tiesą sakant, ramiai valgiau ledų žiūrėdamas Simpsonus, kai gavau el. laišką iš WordPress:
|
Quelqu’un a demandé la réinitialisation du mot de passe pour le compte suivant : |
|
Titre du site : Stunivers |
|
Identifiant : [nom du compte admin ici] |
|
Si ceci est une erreur, ignorez cet e-mail et rien ne se passera. |
|
Pour renouveler votre mot de passe, cliquez sur le lien suivant : |
|
> lien de réinitialisation ici |
|
Cette demande de réinitialisation de mot de passe provient de l’adresse IP xxx.xxx.xxx.xxx . |
|
1. Pirmosios informacijos
Ištirta, kad nulaužimo autoriui tikriausiai nepabūtų reikalingas paslėptis ir kad jis būtų dalyviais automatinio interneto skenavimo proceso.
Pateiktos IP adresai buvo paminėti daug kartų mano blogo žurnalais, visai 17 karta.
Pradžia yra Indija, o miestas – Delhi.
Manau, kad pagal šią informaciją neturėtume būti įsitikinę, jog tai tikrai nėra pastovus lokacinis rodymas, nors jis nepakankamas mums padėti.
Skubiausiai, įkrautojas naudojo seną versiją Google Chrome, kurios neturėta atnaujintos Windows 10 sistema ir veikė iš VPS.
Kaip teigti, aš visiškai nesu pasitikėjęs šia situacija.
2. Pasekmės
Ateikti į produkcijos aplanką su mano identifikacine informacija buvo beveiki nepasiekiamas. Iš visų logų ir mūsų paslaugų teikėjo ataskaitų, neseniai vykdytose veiksmuose blogoje, nėra pateikta jokios svarbios informacijos išleidimo.
3. Ką buvo padaryta siekiant saugumo
Mano blogas neturi didelės reikšmės internete, tik trys apsilankymai per metus, labai gerai!
Tačiau tai nereiškia, kad automatinių nulaužimo kampanijų nebus jokių pasekmės, tai tikrai yra tas atvejis.
Todėl, nors buvo minimaliųjų apsaugų, mano internetinės svetainės paslaugos tarnyba jau turėjo įgyvendintas kelias saugumo priemones, tokius kaip susirūpinimo veiklos detekcija ir kt. Tai suteikė galimybę iškraipti daugelio automatinių botų (ir jų yra didžiulis kiekis, jei naudojate WordPress).
Aš taip pat užtikrino, kad WP-admin prisijungimo nuoroda būtų keičiama, siekiant sumažinti nusikalstamą veiklą.
Mano blogas buvo atnaujintas rankiniu būdu, nes aš turiu atnaujinimo srautą!
Tačiau matyti, kad šis srautas ... veikė tik kai kuriose versijose, o kitose – ne.
Bet jis irgi nepasiekė klaidų, todėl aš neturėjau blogų apie įvykius, nes nieko negavau el. pašte.
Ir tai yra viskas mano faulio, aš galiu atsakomybę už tai imtis tik savimi.
4. Ką naudojo įsilaužėlis
Įkrautas naudojo šią CVE:
CVE-2026-19632 — TranslatePress
Ir tai yra mano pluginas, kurį aš naudoju norėdami išversti svetainę, ir jis užkelia problemų iki versijos 3.3.1.
Ši klaida leido neautorizuotojams gauti administratoriaus slaptažodžio atstatymo nuorodą, o tada naudoti ji naujai nustatytame slaptažodžiu ir užėmę administratoriaus paskyrą.
Mekanizmas yra labai neįtikėtas: nulaužimas pradėjo atstatymo procesą, o TranslatePress galėjo išsaugoti šią nuorodą savo vertimo duomenų bazėje.
Per viešai prieinamą AJAX užklausą jis gali gauti šį URL, įskaitant atstatymo klavišą.
Atakuoja ir tada gali keisti administratoriaus slaptažodį arba kaip gerai padaryti ...
5. Pilna pakeitimas vertimų sistema
Tiesa, žinau, kaip greita WordPress gali sukelti problemas, todėl aš užkoduju visus savo papildinius.
Visus, išskyrus TranslatePress, didelis darbas ...
TranslatePress papildinys yra labai įdomus dėl jo funkcijų, ir pritariu, kad aš buvau lenčiavimas.
Dėl to, pasirinkau šį papildinį, kad būtų nepakanka užkoduoti.
Taip pat sukurtą savo vertimo papildinį.
Ir tai užtruko laiko, nes detalės yra sunkios.
Pirma, norėjau perskaityti TranslatePress kodą, o vėliau suprasti dalykus, kurie man svarbūs ir interesavę.
Mano kodas nebaigtas joje, jis tik įspūdingas.
Viskas tai padaryta, kad būtų privatus.
6. Pakeitimas atnaujinimo grandinėje
Pirmą kartą blogą pradedant, aš to darydavau naudojantis savo interneto paslaugos įrankiais.
Tada turėjau tik el. pašto pranešimus.
Vėliau nusiinstalojo WordPress, kad išeitų iš sunkumų, kurie neturėtų blokoti jokią, bet mano blokavo man dalyką, apie kurį aš ir neprisimenu.
Tada nusprendžiau nepasiklysti naujinimo postrukse, o sukurti savo atnaujinimo tinklą.
Tai visai nėra tik git pull projekte.
Atnaudavau Cron ir WP-CLI su plugin update --all, be to, core update, bet ne theme update. Aš taip pat greitai sukurtą savo tema koduojau.
Nepamirškite patikrinti checksums naudojant wp core verify-checksums, ir bus gerai.
Dėl to, kad turėjau tik vieną išorinį pluginą, tai man atrodo puiku.
Tačiau, mano tinklas konkrečiai sugadino dėl nežymios klaidos, kuri sukūrė TranslatePress, kuris nesukurė naujinimų.
Ir čia aš viskas praradau.
Aš gerai planavojo gauti WP-CLI atsakymą, bet mano apdorojimo postrukse buvo pilksniai.
Visais atvejais, aš tinkamai traktuojau tik žinomą klaidą, kuria susidūrė jame testuose. Bet jeigu kitoks klaidos tipas įvyko, aš tik ji užfiksuojau ir tęsiau.
Taigi, kokia nors štai:
|
output=$(wp plugin update --all 2>&1) |
exit_code=$? |
|
if [[ $exit_code -ne 0 ]]; then |
if [[ "$output" == *"Error: Download failedd."* ]]; then |
echo "An error occured" |
log-mail "$output" |
exit 1 |
else |
log "$output" |
exit 2 |
fi |
fi |
|
# Vamzdyno tęsinys |
|
Geras.
Pirmiausia, kodas yra puiku.
Bet daugiau, problema čia: aš traktuojau žinomą klaidą, o ne visų klaidų.
Todėl mano tinklas gali susidurti su problemomis pluginų atnaujinimo metu, užfiksuoti jas ir tada laiku, kad viskas gerai.
Ir nesukurė jokio pranešimo šiuo atveju, aš tikrai neturiu jokių el. pašto pranešimų.
Aš tikėjosi, kad mano atnaujinimai veikia.
Jie neveikė.
Taip, WordPress taip pat nepasiekė atnaujinimo, viskas liko užsiblokuota dėl mano kodinio netinkamo valdymo.
Būtinas trakumas yra tas, kad ši klaida iškilo iš mano testavimo.
Apskaičiau specialią sąlygą, kurios mane interesavo tuo metu, ir jis veikė. Aš buvau patenkintas ir įvedžiau tos funkcijos produktyva be pakankamo kitų atvejų testavimo, nepastebėję viso skripto.
Aš tikrai buvau per daug užsiilęs, kad būčiau gana pažangus ir išleistum čia.
Ir kelių mėnesių vėliau aš susidūrė su trukdingu pluginu, kuris neturėjo atnaujinimo, nors aš pats parašiau visą pipeline'ą, kad būtų išvengta tokių situacijų.
Puiku.
6.1. Ką aš pakeitėjau
Visų pirma, aš paaiškinau savo klaidą.
Bet aš nesukurė trijų eilučių, kad būtų įtrauktas kasdienis TestPress.
Atnaujiniau, kaip mano pipeline'as valdo klaidas ir kokią operacijų tvarką jame atliekama.
Žr. šią paprastą ir pilnai pakeistą versiją, kad galėtumėte matyti, kaip aš tai suprantu:
#!/bin/bash |
|
set -o pipefail |
|
SITE_DIR="/home/USER/www" |
LOG_DIR="/home/USER/logs" |
LOG_FILE="$LOG_DIR/update-$(date '+%Y-%m-%d').log" |
|
MAIL_TO="admin@example.com" |
SITE_NAME="Mon WordPress" |
|
mkdir -p "$LOG_DIR" |
|
# ============================================================ |
# LOG + MAIL |
# ============================================================ |
|
log-mail() { |
local text="$1" |
local exit_code="$2" |
local date |
date="$(date '+%Y-%m-%d %H:%M:%S')" |
|
echo "[$date] $text" >> "$LOG_FILE" |
|
if [ "$exit_code" -eq 0 ]; then |
printf '[%s] SUCCESS : %s\n' "$date" "$text" |
printf '%s\n' "$text" | mail \ |
-s "[OK] $SITE_NAME - Pipeline" \ |
"$MAIL_TO" |
else |
printf '[%s] ERROR : %s\n' "$date" "$text" |
printf '%s\n' "$text" | mail \ |
-s "[ERREUR] $SITE_NAME - Pipeline" \ |
"$MAIL_TO" |
fi |
} |
|
|
# ============================================================ |
# EXECUTE A COMMAND |
# ============================================================ |
|
run_step() { |
local name="$1" |
shift |
|
echo "" |
echo "==========================================" |
echo "$name" |
echo "==========================================" |
|
local output |
output=$("$@" 2>&1) |
local exit_code=$? |
|
echo "$output" >> "$LOG_FILE" |
|
if [ "$exit_code" -ne 0 ]; then |
log-mail "$name as failled : |
|
$output" "$exit_code" |
|
exit "$exit_code" |
fi |
|
log-mail "$name completed successfully : |
|
$output" 0 |
} |
|
|
# ============================================================ |
# INITIALISATION |
# ============================================================ |
|
cd "$SITE_DIR" || { |
log-mail "Unable to accesss to $SITE_DIR" 1 |
exit 1 |
} |
|
log-mail "Start the updating pipeline" 0 |
|
|
# ============================================================ |
# WORDPRESS - CORE |
# ============================================================ |
|
run_step \ |
"Updating WordPress Core" \ |
wp core update |
|
|
# ============================================================ |
# WORDPRESS - PLUGINS |
# ============================================================ |
|
run_step \ |
"Updating WordPress Plugins" \ |
wp plugin update --all |
|
|
# ============================================================ |
# WORDPRESS - THEMES |
# ============================================================ |
|
run_step \ |
"Updating THEMES (i'm not using that but ..)" \ |
wp theme update --all |
|
|
# ============================================================ |
# PHP - COMPOSER |
# ============================================================ |
|
run_step \ |
"Updating Composer Dependencies" \ |
composer update --no-interaction --prefer-dist |
|
|
# ============================================================ |
# NODE / REACT |
# ============================================================ |
|
run_step \ |
"Updating Node Dependencies" \ |
npm ci |
|
|
# ============================================================ |
# REACT - BUILD |
# ============================================================ |
|
run_step \ |
"Build React" \ |
npm run build |
|
|
# ============================================================ |
# FIN |
# ============================================================ |
|
log-mail "Pipeline completed with success." 0 |
|
exit 0 |
Vis dėlto, reikia prisiminti, kad klaida nėra kas nors, ką galiu tik įrašyti ir pamiršti.
Ir svarbiausia, jis turi būti galima testuoti ir patikrinti.
Aš aiškiai nepasinaudavau laiku šiuo atlikti ir netgi pamiršta apie tai grįžti, sujungdamas, kad jis yra žinomas, tačiau ignoruojant, kad esu per mažas, kad tokių problemų gali įvykti.
Taip pat aš išbandau savo kodą, o ne tik pasakyjau:
« Dabar tai veikia, ir visada bus. »
Jeigu kritinė etapa nepavyksta, pipeline turi žinoti apie tai, tinkamai sustabdyti ir pranešti man.
Ir svarbiausia, aš jau nesuvoku kaip pakankamą tik testavimą tiesiog klausinių klaidų.
Tai yra tas pats būdas, kaip aš gautas su pipeline, kuris veikė puiku... kol niekada neveikė.
Šį kartą aš taip pat atnaujinau mano blogo priklausomumus.
Ir aš turėsiu tik WordPress kodą ir savo kodą.
Tokiais būdoje, mes grįžti į testavimą, net ir paprastam pipeline skriptui.
7. Pagrindinis produkcinis etapas
Aš rašau šį straipsnį savo kūrimo aplinkoje, kurioje jau nebus kai tu galėsi jį skaityti.
Jau žinote, viskas kas aš daryti yra atviras kodas.
Mano naujo plugino kodas dar nėra laisvas.
Aš noriu užtikrinti, kad įvyktų jokios klaidos, kurias galiu netapti pamirštas.
Jums pranešsiu kai bus man patogiau dėl šio klausimo.
Komentarai
Kol kas nėra patvirtintų komentarų.
Prisijunkite su komentuotojo paskyra, kad galėtumėte komentuoti. Prisijungti.