Lyhyesti: Tarkistaaksenne tietokannan haittakoodin varalta käytte viennin tai kopion läpi lukevilla kyselyillä etsien sisäänajettuja skriptejä, vieraita osoitteita ja hämärrettyä koodia sisällöistä ja asetuksista. Tarkistakaa lisäksi triggerit, ajastetut tapahtumat, tallennetut proseduurit ja tietokantakäyttäjät. Siivotkaa vasta arvioinnin jälkeen äläkä koskaan sokealla etsi ja korvaa -toiminnolla, koska serialisoitu data muuten rikkoutuu.
Monien siivousten sokea piste
Murron jälkeen useimmat ylläpitäjät tarkistavat tiedostot. He korvaavat CMS:n ytimen, poistavat epäilyttävät PHP-tiedostot ja asentavat laajennukset uudelleen. Verkkosivusto näyttää sen jälkeen puhtaalta, ja viikkoa myöhemmin se ohjaa taas vieraille sivuille. Syy on usein tietokannassa, joka otettiin siivouksessa mukaan muuttumattomana.
Hyökkääjälle tietokanta on houkutteleva piilopaikka. Widgetin skripti tarjoillaan jokaisella sivulla. Muutettu osoiteasetus ohjaa kaikki kävijät muualle. Ylimääräinen ylläpitäjätili avaa oven myöhemmäksi. Mikään näistä ei näy tiedostoskannauksessa.
PHP2Shellin, eli aukkojen CVE-2026-109618 ja CVE-2026-109619, jotka mahdollistavat koodin suorittamisen ilman kirjautumista, jälkeen tietokanta kuuluu siksi jokaiseen tarkistukseen. Joka voi suorittaa koodia palvelimella, voi yleensä lukea tietokannan tunnukset asetuksista ja kirjoittaa sinne mitä tahansa. Miten sovellus ylipäätään keskustelee tietokannan kanssa, selittää PHP ja tietokannat: PDO ja mysqli.
Missä haittakoodi piilee tietokannassa
| Löytöpaikka | Tyypillinen sisältö | Vaikutus |
|---|---|---|
| Sisällöt (artikkelit, sivut, tuotteet) | <script>-lohkoja, näkymättömiä linkkejä, <iframe> |
haittakoodi tai roska kävijöille |
| Asetukset ja valinnat | muutettu verkkosivuston osoite, vieraita skriptejä widgeteissä tai teemavalinnoissa | uudelleenohjaukset, skriptit kaikilla sivuilla |
| Käyttäjätaulut | ylimääräisiä ylläpitäjiä | pysyvä pääsy |
| Triggerit | koodi, joka muuttaa sisältöjä jokaisella tallennuksella | haittakoodi palaa siivouksen jälkeen |
| Ajastetut tapahtumat | toistuvat tehtävät tietokantapalvelimessa | muutokset ilman verkkopääsyä |
| Tietokantakäyttäjät | lisätilejä laajoilla oikeuksilla | pääsy CMS:n ohi |
Kolme viimeistä riviä jää erityisen usein huomaamatta, koska ne eivät ole CMS:n tauluissa vaan itse tietokantapalvelimessa.
Verkkokaupoissa yksi löytöpaikka ansaitsee erityishuomion: asetukset, joiden kautta kassalle ja tilauksen viimeistelyyn liitetään lisäskriptejä. Vieras skripti tässä kohdassa voi lukea asiakkaiden syötteet ennen kuin ne lähtevät salattuina maksupalvelulle. Tarkistakaa siksi kohdennetusti kaikki ylä- ja alatunnistekoodin kentät, seurantaliitokset ja ulkoasuasetukset, jotka vaikuttavat kassasivuihin.
Ajatelkaa lisäksi muita saman palvelimen tietokantoja. Testi- ja staging-kopiot, vanhat projektitilat tai muiden verkkosivustojen tietokannat ovat usein vieressä ja saavutettavissa samoilla tunnuksilla. Mitä live-tietokannasta löytyy, kannattaa tarkistaa myös niistä, ennen kuin kopiota käytetään myöhemmin uudelleen perustana.
Tietokanta haittakoodin varalta: sisällöt ja asetukset
Työskennelkää viennillä. Se on samalla todisteiden varmistus ja hakupohja. Vienti voidaan käydä läpi tekstitiedostona kuormittamatta käynnissä olevaa tietokantaa:
# Luo yhtenäinen vienti (tunnuksia kysytään)
mysqldump --single-transaction --routines --triggers --events -u BENUTZER -p DATENBANK > export.sql
sha256sum export.sql > export.sql.sha256
# Laske tyypilliset kuviot viennistä
grep -oiE '<script[^>]{0,80}' export.sql | sort | uniq -c | sort -rn | head -30
grep -oiE '(eval\(|base64_decode|fromCharCode|document\.write|atob\()' export.sql | sort | uniq -c
grep -oiE 'https?://[a-z0-9.-]+' export.sql | sort | uniq -c | sort -rn | head -50
Viimeinen kysely luettelee kaikki tietokannassa esiintyvät verkkotunnukset esiintymistiheyden mukaan. Vieraat verkkotunnukset, joita kukaan tiimissä ei tunne, ovat tärkeimmät ehdokkaat. Kohdennettuihin kyselyihin itse tietokannassa sopivat SELECT-komennot. Esimerkki käyttää WordPressin tauluja; muiden järjestelmien etuliite ja taulujen nimet löytyvät niiden dokumentaatiosta:
-- Asetukset, joissa on skriptejä tai epäilyttäviä funktioita
SELECT option_name, LENGTH(option_value) AS laenge
FROM wp_options
WHERE option_value LIKE '%<script%'
OR option_value LIKE '%eval(%'
OR option_value LIKE '%base64_decode%'
ORDER BY laenge DESC;
Merkinnät, joiden sisältö on hyvin suuri, ansaitsevat erityishuomion. Taustatietoja WordPress-kohtaisista piilopaikoista antaa opas Takaovien etsintä WordPressistä.
Triggerit, tapahtumat ja tietokantatilit
Triggerejä ja ajastettuja tapahtumia ei ole monissa verkkosovelluksissa lainkaan tarkoitettu. Jos niitä on, jonkun pitäisi osata selittää miksi. Nämä kyselyt lukevat vain MySQL:n ja MariaDB:n järjestelmätauluista:
-- Triggerit kaikissa tietokannoissa
SELECT TRIGGER_SCHEMA, TRIGGER_NAME, EVENT_OBJECT_TABLE, CREATED
FROM information_schema.TRIGGERS;
-- Ajastetut tapahtumat
SELECT EVENT_SCHEMA, EVENT_NAME, STATUS, CREATED, LAST_EXECUTED
FROM information_schema.EVENTS;
-- Tallennetut proseduurit ja funktiot
SELECT ROUTINE_SCHEMA, ROUTINE_NAME, ROUTINE_TYPE, CREATED
FROM information_schema.ROUTINES
WHERE ROUTINE_SCHEMA NOT IN ('mysql', 'sys', 'information_schema', 'performance_schema');
-- Tietokantakäyttäjät
SELECT user, host FROM mysql.user ORDER BY user;
Jos sovelluksenne käyttää PostgreSQL:ää tai muuta tietokantajärjestelmää, järjestelmätaulut ja komennot ovat erilaisia; periaate pysyy samana. Analyysiin kannattaa luoda oma tietokantakäyttäjä, jolla on vain lukuoikeus. Näin edes kyselyn kirjoitusvirhe ei voi muuttaa mitään, eikä tarkistus jätä jälkiä tietoihin.
Trigger, joka liittää koodia artikkelia tallennettaessa, selittää, miksi haittakoodi palaa jokaisen siivouksen jälkeen. Tuntemattomat tietokantakäyttäjät kuuluvat tilien tarkistukseen siinä missä CMS:n ylläpitäjätilitkin; lisää aiheesta kohdassa Vieraiden ylläpitäjätilien etsintä CMS:stä ja palvelimelta.
Siivous tuhoamatta tietoja
Siivous on arkaluonteisin vaihe. Tämä järjestys on osoittautunut toimivaksi:
- Löytöjen arviointi: Jokainen osuma luokitellaan tunnetuksi, harmittomana selitettäväksi tai vieraaksi. Seuranta- ja karttakoodit ovat usein oikeutettuja.
- Sisäänpääsyn sulkeminen: Päivittäkää PHP korjattuun versioon (8.5.12, 8.4.27, 8.3.36, 8.2.35 tai vahvistettu backport), käynnistäkää kaikki workerit uudelleen, päivittäkää sovellus.
- Kohdennettu poisto: Siivotkaa vieras sisältö sovelluksen kautta tai työkaluilla, jotka käsittelevät serialisoitua dataa oikein. Poistakaa vieraat triggerit, tapahtumat ja tilit.
- Tunnusten vaihto: Uusi tietokannan salasana, kirjattuna sovelluksen asetuksiin, sovelluskäyttäjän oikeudet rajattu omaan tietokantaan.
- Jälkitarkistus: Toistakaa hakukyselyt muutaman päivän kuluttua.
Älkää korvatko mitään etsi ja korvaa -toiminnolla SQL-viennistä. Serialisoitu PHP-data tallentaa jokaisen merkkijonon pituuden mukana. Jos pituus muuttuu, asetus muuttuu lukukelvottomaksi ja verkkosivusto voi kaatua.
Uudelleenohjaukset, joita esiintyy puhtaasta tietokannasta huolimatta, johtuvat toisesta kerroksesta. Kirjoitus Verkkosivusto ohjaa kävijät vieraille sivuille auttaa rajaamaan sen.
Miten PHP SOS auttaa konkreettisesti?
- Varmistamme tietokannan tarkistussummalla ja käymme viennin läpi skriptien, vieraiden verkkotunnusten ja hämärretyn koodin varalta.
- Tarkistamme triggerit, tapahtumat, proseduurit ja tietokantakäyttäjät, jotka ovat CMS:n ulkopuolella.
- Siivoamme löydökset haittaohjelmien poiston yhteydessä vahingoittamatta serialisoitua dataa.
- Rajaamme sovelluskäyttäjän oikeudet ja toistamme tarkistuksen siivouksen jälkeen.
Usein kysytyt kysymykset
Voiko haittakoodi piillä tietokannassa?
Kyllä. Hyökkääjät kirjoittavat JavaScriptiä artikkeleihin, tuotekuvauksiin tai widgeteihin, muuttavat osoiteasetuksia uudelleenohjauksia varten tai luovat ylläpitäjätilejä. MySQL:ssä ja MariaDB:ssä myös triggerit ja ajastetut tapahtumat voivat muuttaa tietoja. Tiedostoskannaus ei löydä mitään näistä.
Miten käyn tietokannan läpi rikkomatta mitään?
Työskennelkää viennillä tai kopiolla ja käyttäkää vain SELECT-kyselyjä. Viennin voi lisäksi käydä läpi tekstitiedostona grepillä. Muutokset tehdään vasta, kun jokainen löytö on arvioitu ja varmuuskopio on olemassa.
Miksi löytöjä ei pidä siivota etsi ja korvaa -toiminnolla viennistä?
Monet CMS:t tallentavat asetukset serialisoituna PHP-tietona, jossa jokaisen merkkijonon pituus tallennetaan mukana. Korvaus muuttaa pituuden mutta ei sen ilmoitusta, ja asetus muuttuu lukukelvottomaksi. Siivotkaa sovelluksen kautta tai työkaluilla, jotka ymmärtävät serialisoidun datan.
Onko jokainen tietokannan skripti epäilyttävä?
Ei. Seurantakoodit, kartat, videot tai chat-widgetit tallennetaan myös skripteinä. Ratkaisevaa on, tunteeko joku tiimissä merkinnän ja kohdeosoitteen.