# SQL injekcijas novēršana PHP

> SQL injekcijas novēršana PHP: sagatavotie pieprasījumi ar PDO un mysqli, kolonnu baltie saraksti, šauras datubāzes tiesības. Ar koda piemēriem.

Avots: https://phpsos.de/lv/ratgeber/sql-injection-php/  
Aktuāls uz: 25.10.2026  
Pakalpojuma sniedzējs: PHP SOS, PHP ārkārtas palīdzība un serveru drošība. Tūlītēja palīdzība pa WhatsApp: https://wa.me/491736494914?text=Sveiki%2C%20PHP%20SOS%2C%20mums%20nepiecie%C5%A1ama%20pal%C4%ABdz%C4%ABba%20ar%20m%C5%ABsu%20PHP%20serveri.%20Uz%C5%86%C4%93mums%3A%20%E2%80%A6%20Vietne%3A%20%E2%80%A6

**Īsi:** SQL injekciju PHP uzticami novērš, vērtības nekad neiebūvējot SQL tekstā, bet vienmēr nododot ar sagatavotiem pieprasījumiem un vietturiem. Kolonnu un tabulu nosaukumiem, ko nevar nodot kā vietturus, ir spēkā fiksēts baltais saraksts. Papildus datubāzes lietotājs ar minimālām tiesībām ierobežo zaudējumus, ja tomēr paliek robs.

## Kāpēc SQL injekciju pēc PHP2Shell nedrīkst izlaist no redzesloka

2026. gada oktobrī liela daļa uzmanības ir pievērsta PHP2Shell, divām kritiskām ievainojamībām PHP interpretatorā, kas izlabotas kopš 21.10.2026 versijās PHP 8.5.12, 8.4.27, 8.3.36 un 8.2.35. Daudzas komandas šajās dienās atjaunināja serverus un pārstartēja procesus. Tas ir pareizi un steidzami.

Aktuāls PHP stāvoklis tomēr neko neizsaka par paša kodu. SQL injekcija jau gadiem ir viena no biežākajām tīmekļa lietojumprogrammu ievainojamībām, un OWASP Top 10 to min kategorijā Injection. Kas tāpat plāno drošības pārbaudes, tam jāskata arī savas lietojumprogrammas piekļuves datubāzei.

Labā ziņa: SQL injekcija ir viena no retajām ievainojamībām, ko ar vienkāršu, konsekventi piemērotu noteikumu var gandrīz pilnībā izslēgt.

## Kā PHP rodas SQL injekcija?

SQL injekcija rodas, kad lietojumprogramma lietotāja ievadi apstrādā kā SQL komandas daļu, nevis kā tīrus datus. Tipiski ir pieprasījuma salikšana no teksta fragmentiem un mainīgajiem. Ja apmeklētājs var noteikt šāda mainīgā saturu, viņš zināmos apstākļos var mainīt komandas nozīmi.

Sekas sniedzas no svešu klientu datu nolasīšanas līdz cenu vai tiesību mainīšanai un veselu tabulu dzēšanai. Atkarībā no datubāzes un tiesībām ievainojamība var dot piekļuvi arī ārpus datubāzes. Ja skarti personas dati, var rasties ziņošanas pienākums saskaņā ar VDAR.

Ievade tur nav tikai veidlapu lauki. Arī URL parametri, sīkdatnes, HTTP galvenes, augšupielādēti faili, svešu saskarņu atbildes un jau saglabāti dati no paša datubāzes ir uzskatāmi par neuzticamiem.

## Sagatavotie pieprasījumi ar PDO un mysqli

Sagatavotie pieprasījumi SQL komandu un vērtības datubāzei sūta atsevišķi. Vērtības nekad netiek interpretētas kā komandas daļa. Ar PDO drošs pieprasījums izskatās šādi:

```php
<?php
$pdo = new PDO($dsn, $benutzer, $passwort, [
    PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_EMULATE_PREPARES   => false,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);

$stmt = $pdo->prepare('SELECT id, name, email FROM kunden WHERE id = :id AND status = :status');
$stmt->execute([
    'id'     => (int) $_GET['id'],
    'status' => 'aktiv',
]);
$kunde = $stmt->fetch();
```

Opcija `PDO::ATTR_EMULATE_PREPARES => false` nodrošina, ka datubāze izmanto īstus sagatavotos pieprasījumus, ciktāl draiveris to atbalsta. Ar mysqli darbojas tas pats princips:

```php
<?php
$stmt = $mysqli->prepare('SELECT id, name FROM produkte WHERE kategorie = ? AND preis <= ?');
$stmt->bind_param('sd', $kategorie, $maxPreis);
$stmt->execute();
$ergebnis = $stmt->get_result();
```

Arī sarakstus priekš `IN (...)` var attēlot droši, katrai vērtībai izveidojot savu vietturi un nododot vērtības atsevišķi.

```php
<?php
$ids = array_map('intval', $ausgewaehlteIds);
$platzhalter = implode(',', array_fill(0, count($ids), '?'));
$stmt = $pdo->prepare("SELECT id, name FROM produkte WHERE id IN ($platzhalter)");
$stmt->execute($ids);
```

## Īpaši gadījumi: kolonnu nosaukumi, kārtošana un neapstrādāts SQL

Vietturi darbojas tikai vērtībām, nevis tabulu nosaukumiem, kolonnu nosaukumiem vai kārtošanas virzieniem. Tieši šeit praksē rodas daudzas ievainojamības, piemēram, kārtojamās tabulās vai filtros. Risinājums ir fiksēts atļauto vērtību saraksts:

```php
<?php
$erlaubteSpalten = ['name' => 'name', 'preis' => 'preis', 'datum' => 'erstellt_am'];
$spalte   = $erlaubteSpalten[$_GET['sort'] ?? ''] ?? 'name';
$richtung = (($_GET['dir'] ?? '') === 'desc') ? 'DESC' : 'ASC';

$stmt = $pdo->query("SELECT id, name, preis FROM produkte ORDER BY $spalte $richtung");
```

Ietvari un CMS nes līdzi savus rīkus. WordPress šo uzdevumu pilda `$wpdb->prepare()`, Laravel un Symfony vaicājumu veidotāji un ORM. Tiklīdz tur lietojat neapstrādātu SQL, piemēram, ar funkcijām ar „raw“ nosaukumā, atkal ir spēkā šīs sadaļas noteikumi. Norādes par Laravel atradīsiet rakstā [Laravel lietojumprogrammu nostiprināšana](https://phpsos.de/lv/plattformen/laravel/).

> **Padoms:**
> Kodā mērķtiecīgi meklējiet SQL tekstus, kuros tiek ievietoti mainīgie. Vienkāršs sākums ir meklēšana pēc `query(` un `->raw` kombinācijā ar `$_GET`, `$_POST` vai `$_REQUEST`.

## SQL injekcijas atklāšana esošajā kodā

Jaunā programmatūrā noteikumu var ievērot no paša sākuma. Grūtāk tas ir lietojumprogrammās, kas augušas gadiem. Tur ir vērts sistemātiski meklēt vietas, kur SQL teksti tiek salikti ar mainīgajiem:

```bash
# SQL komandas, kurās tiek ievietoti mainīgie
grep -rnE "(SELECT|INSERT|UPDATE|DELETE)[^;]*\\\$[a-zA-Z_]" src/ --include="*.php" | head -50
# Pieprasījuma datu tieša izmantošana vaicājumu funkcijās
grep -rnE "(query|exec|raw)\s*\(.*\\\$_(GET|POST|REQUEST|COOKIE)" src/ --include="*.php"
```

Ne katrs atradums ir ievainojamība, piemēram, ja mainīgais satur tikai fiksētu tabulas nosaukumu. Taču katra atrašanās vieta reizi apzināti jāpārbauda un vajadzības gadījumā jāpārslēdz uz sagatavotiem pieprasījumiem. Statiskās koda analīzes rīki palīdz šādus paraugus pastāvīgi atpazīt būvēšanas konveijerā, lai jaunas kļūdas vispār nenonāktu darbībā.

## Zaudējumu ierobežošana: tiesības, kļūdu paziņojumi, pārbaude

Drošs kods ir pirmā aizsardzības līnija. Citi slāņi ierobežo zaudējumus, ja tomēr kāds robs tiek palaists garām:

- **Minimālas tiesības:** Vietnes datubāzes lietotājam parasti vajag tikai `SELECT`, `INSERT`, `UPDATE` un `DELETE` savā datubāzē, nevis tiesības veidot lietotājus vai piekļūt citām datubāzēm.
- **Nekādu kļūdu paziņojumu uz āru:** `display_errors = Off` failā php.ini. Datubāzes kļūdām jāiet žurnālā, nevis pārlūkā.
- **Nodalīšana pa lietojumprogrammām:** Katra vietne saņem savu datubāzes lietotāju.
- **Atkarības uzturēt aktuālas:** Ievainojamības ir arī bibliotēkās, kā rāda ceļvedis [composer audit](https://phpsos.de/lv/ratgeber/composer-abhaengigkeiten-pruefen/).
- **Ļaut pārbaudīt:** Koda pārskats un automatizēta analīze atrod daudzas vietas, penetrācijas tests parāda, kas no ārpuses patiešām ir sasniedzams.

```sql
-- Piemērs: datubāzes lietotājs tikai ar nepieciešamajām tiesībām
CREATE USER 'shop_app'@'localhost' IDENTIFIED BY '<starkes Passwort>';
GRANT SELECT, INSERT, UPDATE, DELETE ON shop.* TO 'shop_app'@'localhost';
```

Radniecīga ievainojamība skar datu izvadi pārlūkā. Kā to nodrošināt, skaidro ceļvedis [Cross-Site Scripting novēršana PHP](https://phpsos.de/lv/ratgeber/xss-php/).

## Kā PHP SOS palīdz konkrēti?

- Sistemātiski pārbaudām jūsu lietojumprogrammas piekļuves datubāzei, vai nav nedrošu pieprasījumu.
- Atradumus prioritizējam pēc sasniedzamības un skartajiem datiem un parādām konkrētus labojumus.
- Datubāzes tiesības un kļūdu apstrādi iestatām drošā līmenī.
- Pēc labošanas pārbaudām vēlreiz un dokumentējam rezultātu.

Neatkarīgu pārbaudi apraksta pakalpojums [Drošības audits un penetrācijas tests](https://phpsos.de/lv/leistungen/sicherheitsaudit-penetrationstest/).


## Biežāk uzdotie jautājumi

**Vai pietiek ar ievades apstrādi ar addslashes vai real_escape_string?**  
Nē, tas ir kļūdaini. Eskēpēšana ir atkarīga no rakstzīmju kopas un konteksta, un vienā vietā to viegli aizmirst. Sagatavotie pieprasījumi principā nošķir komandu un datus, tāpēc ir ieteicamais ceļš.

**Vai ORM automātiski pasargā no SQL injekcijas?**  
Lielā mērā, kamēr izmantojat ORM pieprasījumu funkcijas. Tiklīdz rakstāt neapstrādātu SQL vai ievietojat vērtības kārtošanā un kolonnu nosaukumos, spēkā ir tie paši noteikumi kā bez ORM.

**Vai Web Application Firewall palīdz pret SQL injekciju?**  
WAF var noķert zināmus paraugus un iegūt laiku. Taču tā neaizstāj drošu kodu, jo noteikumus, kas balstās uz pieprasījuma datiem, var apiet, un dažkārt tie skar likumīgu ievadi.

**Vai PHP atjauninājums pret PHP2Shell aizver arī SQL injekcijas ievainojamības?**  
Nē. PHP2Shell skar PHP interpretatoru. SQL injekcija ir kļūda lietojumprogrammas kodā, un tā paliek neatkarīgi no tā, kura PHP versija darbojas.

## Avoti

- [OWASP Top 10](https://owasp.org/www-project-top-ten/)
- [OWASP Cheat Sheet Series](https://cheatsheetseries.owasp.org/)
- [php.net: drošības ziņojumi](https://www.php.net/)
