PHP opravil SQL injekci v rozšíření pro PostgreSQL, týká se všech čtyř větví
PHP vydalo 30. července opravné verze 8.2.33, 8.3.33, 8.4.24 a 8.5.9. Dvě z opravených chyb mají známku 8,1. První je SQL injekce v rozšíření pro PostgreSQL: čtyři funkce obalovaly hodnoty do řetězce, ve kterém má zpětné lomítko zvláštní význam, ale neošetřovaly ho. Druhá je zápis mimo přidělenou paměť ve funkci bccomp().

Projekt PHP vydal 30. července 2026 opravné verze všech čtyř udržovaných větví naráz: 8.2.33, 8.3.33, 8.4.24 a 8.5.9. Dvě z opravených chyb dostaly podle CVSS 4.0 shodnou známku 8,1, tedy vysokou závažnost. Jedna z nich dovoluje podstrčit vlastní SQL dotaz aplikaci, která ukládá data do PostgreSQL přes funkce vestavěné v PHP. Udržované větve jsou podle přehledu na php.net právě čtyři; nejstarší z nich, 8.2, je od konce roku 2024 jen v bezpečnostním režimu a opravy má dostávat do konce letošního roku.
Escapování, které nepočítalo se zpětným lomítkem
Čtyři funkce rozšíření pgsql – pg_insert(), pg_update(), pg_select() a pg_delete() – berou hodnoty jako pole a dotaz si z nich složí samy. Ošetření hodnot má na starosti vnitřní funkce php_pgsql_convert(). Ta zavolá knihovní PQescapeStringConn() z libpq a výsledek zabalí do řetězce ve tvaru E'…'.
Právě to zabalení je jádro chyby, kterou popisuje hlášení GHSA-7qpv-r5mr-78m4, v registru vedené jako CVE-2026-17543. Řetězec uvozený písmenem E je v PostgreSQL takzvaný escape string constant, tedy literál, ve kterém má zpětné lomítko zvláštní význam. PQescapeStringConn() ale zpětné lomítko nechá být, protože počítá s obyčejným literálem. Apostrof zdvojí, lomítko ne – a útočníkovi stačí poslat hodnotu, kde lomítko stojí těsně před apostrofem.
$result = pg_select($db, 'user', ['name' => "zzz\\' OR 1=1 --"]);
// SELECT * FROM "user" WHERE "name"='zzz\'' OR 1=1 --';
V předané hodnotě je zpětné lomítko jen jednou; dvojité je zápis v PHP. Escapování z apostrofu udělá dvojici, jenže první z nich se kvůli lomítku čte jako obyčejný znak. Druhý apostrof tedy řetězec ukončí a všechno za ním se stane součástí dotazu – ukázka v hlášení vrátila celou tabulku. Oprava mění zabalování: hodnoty teď končí v obyčejném literálu, kde lomítko žádnou zvláštní roli nemá.
Nastavení, se kterým se počítalo obráceně
Že PQescapeStringConn() zpětné lomítko neošetří, není chyba libpq. Funkce se řídí nastavením spojení a dokumentace PostgreSQL u parametru standard_conforming_strings uvádí, že od verze 9.1 je výchozí hodnota zapnuto, kdežto starší vydání ho měla vypnuté. Zapnutý parametr znamená, že obyčejný literál bere zpětné lomítko doslova, jak žádá norma SQL – a escapovací funkce se podle toho zachová.
Nesoulad vzniká až tím, že PHP hotový řetězec vloží do E'…', kde platí opačné pravidlo. Dokumentace libpq k tomu říká, že PQescapeStringConn() apostrofy kolem literálu sám negeneruje a dodat je musí volající. PHP je dodalo v podobě, se kterou se ošetření hodnot rozešlo.
Druhá díra je v bccomp() a starších větví se netýká
CVE-2026-17544 je jiného druhu: zápis mimo přidělenou paměť. Podle hlášení GHSA-x692-q9x7-8c3f vzniká v převodní funkci bc_str2num(), když zadané měřítko číslo zkrátí a z výsledku se pak ještě odstraní koncové nuly. Kód sníží počet desetinných míst, ale ukazatel na konec desetinné části nechá tam, kde byl. Následné kopírování pak přenese původní, nezkrácené číslo do vyrovnávací paměti, která je na ně malá.
BCMath drží malá čísla v malé oblasti na zásobníku a teprve větší v haldě, takže poškodit jde obojí. Oprava přidává jediný řádek: po odstranění nul se dorovná i ukazatel na konec. Záznam v registru CVE uvádí jako postižené jen větve 8.4 a 8.5 – starší 8.2 a 8.3 dostaly z tohohle vydání zbylé opravy, tuhle ne.
Kdo má spěchat
Vedle obou vysoce hodnocených chyb jsou ve vydání ještě dvě bezpečnostní opravy: pád při zpracování archivu phar s kruhovými symbolickými odkazy (CVE-2026-7260, známka 5,4) a aktualizace knihovny libgd kvůli CVE-2026-9672.
Podle nás spěchá nejvíc pgsql, i když obě chyby mají tutéž známku. Vektor CVSS u SQL injekce uvádí útok po síti, nízkou složitost a žádná potřebná oprávnění, a hlášení jmenuje jako místo, kde se vadné ošetření používá, právě ty čtyři funkce pro práci s tabulkou. Volání bccomp() s hodnotou od uživatele je proti tomu situace, kterou v běžné aplikaci potkáte spíš výjimečně. O jiných cestách k PostgreSQL, tedy o parametrizovaných dotazech přes pg_query_params() nebo přes PDO, hlášení nemluví.
Oba záznamy CVE mají ve vektoru zapsáno, že o zneužití v praxi se zatím neví. To ale platí ke dni vydání a u chyby, jejíž ukázka se vejde na jeden řádek, je to údaj s krátkou trvanlivostí. Podle nás je na téhle dvojici pozoruhodné hlavně to, že SQL injekce nevznikla v aplikaci, ale v kusu jazyka, který měl aplikaci před injekcí chránit.