Na našom webhostingu www.nakurze.sk, ktorý dostávajú účastníci našich webových kurzoch zdarma, je zakázané používanie funkcie mail(). V tomto článku sa pokúsim vysvetliť, prečo je táto funkcia nebezpečná a prečo by sa nemala používať.
Na našom webhostingu www.nakurze.sk, ktorý dostávajú účastníci našich webových kurzoch zdarma, je zakázané používanie funkcie mail(). V tomto článku sa pokúsim vysvetliť, prečo je táto funkcia nebezpečná a prečo by sa nemala používať.
Syntax funkcie mail() podľa manuálu PHP:
bool mail (
string $to ,
, string $subject
, string $message
[, string $additional_headers
[, string $additional_parameters ]
]
)
$to – adresa príjemcu
$subject – predmet správy
$message – obsah správy
$additional_headers – ďalšie hlavičky správy
$additional_parameters – ďalšie správy pre odosielací program (často sendmail)
Väčšina PHP funkcií sa spolieha na to, že do funkcie prídu iba správne parametre. To musí samozrejme zabezpečiť vývojár, čo, povedzme si otvorene, sa často zanedbáva. Bohužiaľ, veľa vývojárov má buď chabé znalosti z bezpečnosti, alebo jednoducho sú iba leniví študovať manuál (napríklad práve k programu sendmail).
Schválne, ak ste PHP vývojár, poznáte program sendmail? Viete, aké má parametre? Viete, ako sa správa? Je jasné, že nikto nemôže vedieť všetko, ale práve zasielanie e-mailov je v dnešnej dobe často zneužívané na rôzne druhy útokov – od spamovania, cez phishing (tvárim sa, že som PayPal a nútim obeť k zmene hesla – samozrejme na mojej phishingovej – podvodnej webstránke) až po šírenie ransomware (často sa šíria práve v podobe zazipovanej fotografie ruskej krásky, ktorá sa do vás údajne zamilovala 🙂 ).
Tento typ útoku funguje tak, že do e-mailovej správy sa vložia hlavičky, ktoré následne uvidí príjemca. Jednoduchý príklad budú hlavičky From alebo Reply-To, ktoré príjemcovi zobrazia odosielateľa a adresu na odpoveď, ak príjemca stlačí v mailovom klientovi tlačidlo Odpovedať.
Je zrejmé, že tieto hlavičky sú potrebné, keďže samotná funkcia mail() neobsahuje inú možnosť, ako zadefinovať odosielateľa. Jednotlivé hlavičky sa oddeľujú znakmi CRLF (\r\n) a pokiaľ obsah hlavičiek nie je správne očistený práve od týchto znakov, útočník môže vložiť do e-mailovej správy svoje vlastné hlavičky. Môže tým napríklad spôsobiť to, že odošle správu na rôzne e-mailové adresy (pomocou hlavičiek CC alebo BCC). Tu existuje pomerne jednoduchá ochrana – očisťovať akékoľvek vstupy od užívateľa o znaky, ktoré nemajú v danom parametri čo hľadať. Je asi jasné, že e-mailová adresa neobsahuje znak \ 🙂
A sme opäť pri programe sendmail. Tento program sa používa na odosielanie e-mailov z PHP na strane servera. Funguje to tak, že vy v PHP zavoláte funkciu mail() a tá zavolá program, ktorý odošle e-mailovú správu zo servera. Práve týmto programom najčastejšie býva spomínaný sendmail.
To, aký program sa použije na odoslanie e-mailu cez funkciu mail(), sa definuje v konfiguračnom súbore php.ini, kde je možné buď zadať adresu SMTP servera alebo cestu k MTA – Mail Transfer Agentovi. Hoci PHP interne volá funkciu escapeshellcmd(), ktorá zabraňuje spúšťaniu vlastného kódu, táto funkcia sa neaplikuje na posledný – piaty parameter funkcie mail(), keďže jeho úlohou je práve predať parametre MTA. Predstavme si nasledovný kód:
mail('prijemca@example.com', 'Predmet', 'Správa', '', '-f' . $_GET['from']);
Parameter -f definuje v programe sendmail adresu odosielateľa. Na tom by nebolo nič zlé, ale problém je, že vývojár neočistil vstupný parameter from, ktorý je predávaný do funkcie mail() z URL adresy. Väčšina by očakávala, že e-mailová adresa „niekto@example.com -OQueueDirectory=/tmp -X/var/www/stranka/subor.php“ je neplatná a PHP vypíše chybu, ale nestane sa tak. Parametre pre funkciu sendmail budú nasledovné:
-fniekto@example.com -OQueueDirectory=/tmp -X/var/www/stranka/subor.php
A čo to teda znamená? Adresa odosielateľa síce bude niekto@example.com, ale do sendmailu boli navyše pridané dva parametre:
-OQueueDirectory=/tmp
spôsobí, že adresár fronty správ sa zmení na /tmp – sem môžu zapisovať v linuxových systémoch všetci užívatelia (a teda aj PHP), resp. je možné zmeniť ho na taký adresár, aby sa obišlo aj prípadné obmedzenie open_basedir.
-X/var/www/stranka/subor.php
nastaví logovací súbor na /var/www/stranka/subor.php, v tomto súbore sa bude nachádzať napríklad predmet správy.
Jednoducho! Stačí ako predmet správy napísať napríklad: <?php system($_GET['prikaz']); ?>
Tým vznikne v adresári /var/www/stranka súbor s názvom subor.php, ktorý bude obsahovať PHP kód a PHP ho pri zavolaní vykoná. V ňom sa bude nachádzať <?php system($_GET['prikaz']); ?>
– funkcia, ktorá na príkazovom riadku systému spustí to, čo zadáme do parametra „prikaz“. Teda napríklad jednoduchým URL https://www.stranka.sk/subor.php?prikaz=rm%20-rf%20~
zmažeme kompletne celú webovú stránku. Samozrejme, toto je to najmenej kreatívne riešenie, dali by sa nájsť aj ďalšie a oveľa zaujímavejšie. Čo tak napríklad získať heslo k databáze a dostať sa ku kompletným osobným údajom všetkých zákazníkov? 😉
Ak na svojich serveroch prevádzkujete aplikácie Roundcube, MediaWiki, PHPMailer, Zend Framework, SwiftMailer, SquirrelMail a podobné, odporúčam sa pozrieť na verzie a prípadne ich aktualizovať. Klikom na ich názvy sa dostanete na odkaz na zraniteľnosť, kde je uvedená aj zraniteľná verzia. Je samozrejme potrebné skontrolovať aj svoju verziu WordPressu, Joomly alebo Drupalu, nakoľko aj tieto aplikácie môžu využívať napr. PHPMailer vo verzii so zraniteľnosťou.
Funkcie escapeshellarg()
a escapeshellcmd()
sa používajú na ochranu pri vykonávaní príkazov v shelli, napríklad použitie
<?php system(escapeshellcmd('./aplikacia -x ' . escapeshellarg($_GET['parameter_x'])); ?>
chráni parameter -x
v aplikácii pred zneužitím. Problémom ale je, že nechráni ostatné prípadne zneužiteľné parametre. Ak by sme napríklad za parameter_x
dosadili reťazec nieco' -y foo
, do shellu by sa dostalo niečo takéto: ./aplikacia -x 'nieco'\\'' -y foo \'
Tu je teda vidieť, že práve parameter -y
bol podvrhnutý napriek tomu, že bola zavolaná funkcia escapeshellarg()
, resp. escapeshellcmd()
Toto tiež nie je úplne bezpečné, pretože niektoré znaky, ktoré môžu spôsobiť problémy, tento filter neodhalí. Filter umožňuje napríklad escapovať biele znaky, ktoré sú v dvojitých úvodzovkách. Tým pádom je možné prekryť jednoduché a dvojité úvodzovky, čo vo funkciách escapeshellcmd() a mail() predpokladáme, že sa nemôže stať. Príkladom je takáto e-mailová adresa:'a."'\ -OQueueDirectory=\%0D<?=eval($_GET[prikaz])?>\ -X/var/www/stranka/"@a.php
Toto by FILTER_VALIDATE_EMAIL vyhodnotil ako korektnú e-mailovú adresu a pri spustení by v adresári /var/www/stranka vznikol súbor s názvom @a.php, ktorý by vo svojom vnútri obsahoval chybu <?=eval($_GET[prikaz])?>\/): No such file or directory
a sme tam, kde sme boli 🙂
$subject
a $message
, v najhoršom prípade aj do $to
.$additional_headers
odstrániť z užívateľských vstupov znaky \r
a \n
$additional_parameters
za žiadnych okolností nepoužívať vstup od užívateľafilter_var()
alebo filter_input()
na overenie vstupov od užívateľa. Tieto funkcie na to neboli určené. E-mailové adresy by sa mali kontrolovať pomocou regulárnych výrazov – je to síce nepohodlnejšie pre vývojýra, ale zato oveľa účinnejšieOverenie e-mailovej adresy sa dá urobiť napríklad takto:
function validateEmail($email) { $regex = "/^[a-z0-9][a-z0-9_-.]*@[a-z0-9-.]+.[a-z]{2,}$/i"; return (bool)preg_match($regex, $email); }
Samozrejme, že to nie je najdokonalejšie (bolo by vhodné overiť napríklad existenciu domény za zavináčom), ale funkcia vráti true, ak e-mailová adresa začína na písmeno alebo číslo, potom obsahuje písmeno, číslo, podčiarkovník, pomlčku alebo bodku, potom zavináč, potom aspoň jedno písmeno, číslicu, pomlčku alebo bodku a na konci musí byť bodka a minimálne dve písmená.
Odporúčam prečítať/vyskúšať:
a dokumentáciu k spomenutým PHP funkciám.
Páčil sa vám článok? Pošleme vám podobné.
Aktivujte si okamžité zasielanie noviniek a článkov – už vám od nás nikdy nič neunikne. Môžeme vás okamžite informovať o aktuálnej akcii, novinke, špeciálnej kampani či zľave alebo novom článku na našom blogu. Akonáhle sa u nás v novinkách niečo zmení alebo pridá, do pár minút vám automaticky posielame email s odkazom na novinku na našu stránku. A odhlásiť sa môžete kedykoľvek. Nič neriskujete.