Kort sagt: För att kontrollera databasen efter skadlig kod söker ni igenom en export eller en kopia med läsande frågor efter inplanterade skript, främmande adresser och förvrängd kod i innehåll och inställningar. Kontrollera dessutom trigger, schemalagda händelser, lagrade procedurer och databasanvändarna. Sanera först efter bedömningen och aldrig med blint sök och ersätt, eftersom serialiserade data annars går sönder.
Den blinda fläcken i många saneringar
Efter ett intrång kontrollerar de flesta driftansvariga filerna. De ersätter CMS-kärnan, raderar misstänkta PHP-filer och installerar tilläggen på nytt. Webbplatsen ser därefter ren ut, och en vecka senare omdirigerar den till främmande sidor igen. Orsaken ligger ofta i databasen, som övertogs oförändrad vid saneringen.
För angripare är databasen ett attraktivt gömställe. Ett skript i en widget levereras på varje sida. En ändrad adressinställning styr om alla besökare. Ett extra adminkonto öppnar dörren för senare. Inget av det märks vid en filskanning.
Efter PHP2Shell, sårbarheterna CVE-2026-109618 och CVE-2026-109619 med kodkörning utan inloggning, hör databasen därför till varje kontroll. Den som kan köra kod på servern kan i regel läsa databasens åtkomstuppgifter ur konfigurationen och skriva vad som helst där. Hur applikationen överhuvudtaget talar med databasen förklarar PHP och databaser: PDO och mysqli.
Var skadlig kod gömmer sig i databasen
| Fyndplats | Typiskt innehåll | Verkan |
|---|---|---|
| Innehåll (inlägg, sidor, produkter) | <script>-block, osynliga länkar, <iframe> |
Skadlig kod eller spam för besökare |
| Inställningar och alternativ | ändrad webbplatsadress, främmande skript i widgets eller temaalternativ | Omdirigeringar, skript på alla sidor |
| Användartabeller | extra administratörer | permanent åtkomst |
| Trigger | kod som ändrar innehåll vid varje sparande | Skadlig kod återvänder efter sanering |
| Schemalagda händelser | återkommande uppgifter i databasservern | Förändringar utan webbåtkomst |
| Databasanvändare | extra konton med omfattande rättigheter | Åtkomst förbi CMS:et |
De tre sista raderna förbises särskilt ofta eftersom de inte ligger i CMS:ets tabeller utan i själva databasservern.
I webbutiker förtjänar en fyndplats särskild uppmärksamhet: inställningar via vilka extra skript läggs in i kassan och vid orderavslut. Ett främmande skript på det stället kan läsa med kundernas inmatningar innan de skickas krypterade till betaltjänsten. Kontrollera därför riktat alla fält för kod i huvud och sidfot, spårningsinbäddningar och designinställningar som verkar på kassasidor.
Tänk dessutom på andra databaser på samma server. Test- och stagingkopior, gamla projektversioner eller databaser för andra webbplatser ligger ofta bredvid och är nåbara med samma åtkomstuppgifter. Det som hittas i livedatabasen bör kontrolleras även där, innan en kopia senare åter används som underlag.
Kontrollera databasen efter skadlig kod: innehåll och inställningar
Arbeta på en export. Den är samtidigt bevissäkring och sökunderlag. Exporten går att söka igenom som textfil utan att belasta den pågående databasen:
# Skapa en konsekvent export (åtkomstuppgifter efterfrågas)
mysqldump --single-transaction --routines --triggers --events -u BENUTZER -p DATENBANK > export.sql
sha256sum export.sql > export.sql.sha256
# Räkna typiska mönster i exporten
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
Den sista frågan listar alla domäner som förekommer i databasen, efter frekvens. Främmande domäner som ingen i teamet känner till är de viktigaste kandidaterna. För riktade frågor i själva databasen passar SELECT-kommandon. Exemplet använder WordPress-tabeller; prefix och tabellnamn i andra system står i deras dokumentation:
-- Inställningar med skript eller misstänkta funktioner
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;
Poster med mycket stort innehåll förtjänar särskild uppmärksamhet. Bakgrund om WordPress-specifika gömställen finns i guiden Hitta bakdörrar i WordPress.
Trigger, händelser och databaskonton
Trigger och schemalagda händelser är i många webbapplikationer inte alls avsedda. Om de finns bör någon kunna förklara varför. Dessa frågor läser bara ur MySQL:s och MariaDB:s systemtabeller:
-- Trigger i alla databaser
SELECT TRIGGER_SCHEMA, TRIGGER_NAME, EVENT_OBJECT_TABLE, CREATED
FROM information_schema.TRIGGERS;
-- Schemalagda händelser
SELECT EVENT_SCHEMA, EVENT_NAME, STATUS, CREATED, LAST_EXECUTED
FROM information_schema.EVENTS;
-- Lagrade procedurer och funktioner
SELECT ROUTINE_SCHEMA, ROUTINE_NAME, ROUTINE_TYPE, CREATED
FROM information_schema.ROUTINES
WHERE ROUTINE_SCHEMA NOT IN ('mysql', 'sys', 'information_schema', 'performance_schema');
-- Databasanvändare
SELECT user, host FROM mysql.user ORDER BY user;
Använder er applikation PostgreSQL eller ett annat databassystem heter systemtabeller och kommandon annorlunda; principen är densamma. För analysen rekommenderas en egen databasanvändare som bara får läsa. Då kan inte ens ett skrivfel i en fråga ändra något, och kontrollen lämnar inga spår i data.
En trigger som lägger till kod när ett inlägg sparas förklarar varför skadlig kod återvänder efter varje sanering. Okända databasanvändare hör lika mycket till kontokontrollen som adminkonton i CMS:et; mer om det under Hitta främmande adminkonton i CMS och server.
Sanera rent utan att förstöra data
Saneringen är den känsligaste delen. Den här ordningen har visat sig fungera:
- Bedöm fynden: Varje träff klassas som känd, ofarlig och förklarlig eller främmande. Spårnings- och kartkoder är ofta legitima.
- Stäng ingången: Ta PHP till en rättad version (8.5.12, 8.4.27, 8.3.36, 8.2.35 eller bekräftad backport), starta om alla workers och uppdatera applikationen.
- Ta bort riktat: Sanera främmande innehåll via applikationen eller med verktyg som hanterar serialiserade data korrekt. Radera främmande trigger, händelser och konton.
- Byt åtkomstuppgifter: Nytt databaslösenord, lägg in det i applikationens konfiguration och begränsa applikationsanvändarens rättigheter till den egna databasen.
- Kontrollera igen: Upprepa sökfrågorna efter några dagar.
Ersätt ingenting med sök och ersätt i SQL-exporten. Serialiserade PHP-data sparar längden på varje teckensträng med. Ändras längden blir inställningen oläsbar och webbplatsen kan sluta fungera.
Omdirigeringar som uppträder trots en ren databas har sin orsak i ett annat lager. Inlägget Webbplatsen omdirigerar till främmande sidor hjälper till vid avgränsningen.
Hur hjälper PHP SOS konkret?
- Vi säkrar databasen med kontrollsumma och söker igenom exporten efter skript, främmande domäner och förvrängd kod.
- Vi kontrollerar trigger, händelser, procedurer och databasanvändare som ligger utanför CMS:et.
- Vi sanerar fynd inom ramen för borttagning av skadlig kod utan att skada serialiserade data.
- Vi begränsar applikationsanvändarens rättigheter och upprepar kontrollen efter saneringen.
Vanliga frågor
Kan skadlig kod finnas i databasen?
Ja. Angripare skriver JavaScript i inlägg, produktbeskrivningar eller widgets, ändrar adressinställningar för omdirigeringar eller skapar adminkonton. I MySQL och MariaDB kan dessutom trigger och schemalagda händelser ändra data. En filskanning hittar inget av detta.
Hur söker jag igenom databasen utan att förstöra något?
Arbeta på en export eller en kopia och använd bara SELECT-frågor. En export går dessutom att söka igenom som textfil med grep. Ändringar görs först när varje fynd har bedömts och en säkerhetskopia finns.
Varför bör jag inte sanera fynd med sök och ersätt i exporten?
Många CMS sparar inställningar som serialiserade PHP-data där längden på varje teckensträng sparas med. Ett ersättande ändrar längden men inte uppgiften, och inställningen blir oläsbar. Sanera via applikationen eller med verktyg som förstår serialiserade data.
Är varje skript i databasen misstänkt?
Nej. Spårningskoder, kartor, videor eller chattwidgets lagras också som skript. Avgörande är om någon i teamet känner till posten och måladressen.