Как да предпазим сайта си от имейл инжекция?

Почти неизменна част от всеки модерен сайт е контактна страница, в която уебмастера дава възможност на посетителите на сайта за обратна връзка, мнения, препоръки и въпроси лично към него.

Има два начина тази информация да достигне уебмастера – или като се запази в база данни, или да се изпрати като писмо на личния имейл.

И в двата случая се използват уеб форми, в които посетителите въвеждат необходимата информация, която след въвеждането се обработва от различни скриптове.

Има обаче категория посетители на сайтовете, които не се интересуват от това да изпратят съобщение на уебмастера, а да използват тези форми за собствени цели – да изпратят нежелана поща (СПАМ) от името на уебмастера до голям брой имейл адреси, или да придобият достъп до базата данни като се възплзват от липсата на защита на тези форми.

Двата случая на пробив в сигурността на сайта са придобили публичност под имената имейл и MySQL инжекция.

Имел инжекцията представлява буквално инжектиране на допълнителни имейл адреси в контактна форма, така че съдържанието да бъде изпратено както на уебмастера, така и на всички добавени имейл адреси като спам.

Две думи относно 'великите' хакери и спамъри

Сигурен съм, че ще останете изключително изненадани като разберете колко малко е необходимо да се направи за да се елиминира напълно възможността за имейл инжекция.

Също така ще разберете, че онези велики хакери от филмите, дето разбиват кодове на тайните служби за нула време и пренасочват сървъри и сателити толкова лесно, колкото ние превключваме каналите на телевизията, са единствено плод на фантазията на неграмотни сценаристи или са предназначени за неграмотна аудитория.

Запомнете това – няма гениални хакери, има неграмотни и немърливи програмисти, както и твърде много уебмастери, които дават пари без да са наясно колко некачествен код получават срещу парите си.

Как да защитим контактната форма на сайта

Така изглежда нашата имейл форма, когато се зареди в браузер – като повечето контактни форми. mail-form-ready Въвеждате съответните данни във всяко поле, натискате бутона Изпрати и в идеалния случай уебмастера получава вашите възторжени отзиви за поредната полезна информация на сайта.

Какво обаче прави споменатия по-горе индивид спамър на подобна страница.

Най-напред натиска бутона Изпрати без да е въвел никаква информация в полетата за да провери дали ще задейства някаква защита, дали ще се появи някакъв надпис или предупреждение.

Ако не получи такъв сигнал, т.е. ако в скрипта на страницата няма активна защита, спамъра най-вероятно ще пусне една малка инжекция към свой тестов мейл, при успех ще инжектира предварително приготвен списък със стотици, дори хиляди спам имейл адреси.

Въпреки, че Reply-To адреса в хедърите на писмото се взима от мейл формата и в 100% от случаите на спам този адрес е недействителен, писмото реално се изпраща от Return-Path адрес user@server.hosting.tld, т.е. oт името на уебмастера.

Като допълнителни параметри X-Source-Args и X-Source-Dir в хедърите се изписва абсолютния път до изпълнимия файл в акаунта на уебмастера.

В повечето случаи историята завършва така:

Получателите на писмата ги маркират като спам, оплакването стига до нас или мониторинг системата засича самото изпращане и следва спиране на хостинга заради изпращане на спам до отстраняване на причината за пробива в сигурността – единствения потърпевш си остава уебмастера за сметка на спамъра и липсата на защита (а не за сметка на хостинг компанията!).

Реших да не публикувам примерни спамърски практики на инжектиране защото целта на тази статия е как да се предпазим от тях, а не да обучаваме нови спамъри.

Какво представлява филтрирането и как работят отделните филтри

И така, какво ще открие един спамър на нашата страница? Информацията във всяко едно поле се филтрира и приема от обработващия скрипт само ако отговаря на предварително определени от уебмастера условия.

1. В полето Име не може да има други символи освен малки и главни букви на латиница и кирилица, арабски цифри, интервал, тире, долна черта и точка – нулев шанс за добавяне на код. Само интервал също не може да се въвежда и задейства грешката (чрез функцията trim), която от своя страна спира изпълнението на кода. function valnm($yname) {return pregmatch('/^[абвгдежзийклмнопрстуфхцчшщъьюя АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЬЮЯ a-z A-Z 0-9 -_+. ]+$/i', $yname);} 2. В полето Имейл не може да се въведе повече от един символ @ - т.е. не може да има два или повече имейл адреса. function valem($yemail) {return pregmatch('/^[A-Za-z0-9._+-]+@[a-z0-9.-]+.[a-z]{2,6}$/i',$yemail);} 3. В полето Съобщение може да се въведат същите символи като в полето Име, като са добавени още няколко знака за да може посетителя да напише нормални изречения на латиница и кирилица. function valmess($ymessage) {return pregmatch('/^[абвгдежзийклмнопрстуфхцчшщъьюя АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЬЮЯ a-z A-Z 0-9 -_+.,?! + r n]+$/i', $ymessage);} 4. Най-успешната защита срещу автоматични регистрации е т.нар. CAPTCHA или генериран код в изображение, който е уникален за всяко ново зареждане на страницата.

След като се филтрира информацията от формите, логически оператор if-else взима решение дали да се изпрати писмото или да се генерира грешка: if (($ynameval == '1') && ($yemailval == '1') && ($ymessageval == '1') && ($ysecode == $SESSION['sec_code'])) { изпрати писмото} else {покажи съобщение за грешка} т.е. ако са изпълнени всичките четири условия: информацията в текстовите полета Име и Съобщение е коректна, ако в полето Имейл е въведен само един валиден имейл адрес и ако въведеният защитен код съвпада с автоматично генерирания за тази сесия код, само в такъв случай писмото се изпраща.

Ако има грешка само в някое от полетата, само то генерира грешка.

Относно полето Съобщение, може да се приложи и друг вариант на филтриране: $ymessage = trim(htmlentities($POST['message'], ENTQUOTES, "UTF-8")); Всички специални символи в съдържанието, които имат съответни ASCII заместители, ще бъдат заменени, РНР парсера на сървъра няма да разпознае ASCII символите и в крайна сметка скрипта няма да бъде изпълнен.

Освен това филтъра ENT_QUOTES добавя наклонена черта пред единичните и двойните кавички в текста като по този начин напълно елиминира възможността за mysql инжекция, която ще разгледаме в друга статия.

В този случай полето ще генерира грешка единствено ако е оставено празно и няма въведен никакъв текст.

Нека проверим как ще отговори скрипта ако въведем два мейл адреса, разделени със запетая: Проверяващия скрипт не позволява въвеждане на повече от един имейл адрес в това поле – моят плах опит опит за вътрешно фирмен спам не успя да достигне колегите от ICN.bg. Нека добавя, че имейл адреса на уебмастера е записан директно в обработващия PHP скрипт и не може да се види в сорс кода на страницата, така че тази мейл форма е защитена и срещу друга спамърска практика - harvesting, която представлява следното: сканиращи скриптове (ботове) търсят символа за електронна поща @ и като го намерят го добавят целия низ от символи (т.е. имейл адреса) към спамърски бази данни.

Затова не е препоръчително да се изписват имейл адреси на самата уеб страница, а да се ползват защитени контактни форми, в които имейл адреса е записан директно в обработващия скрипт.

Различни подходи към сигурността в интернет

Накрая искам да направя едно малко уточнение: има различни начини за предотвратяване на имейл инжекция, както има различни подходи към интернет защитата като философия.

Аз лично съм превърженик на установените правила – т.е. ние определяме какво е разрешено и всичко останало се филтрира.

Има и друг подход, при който се забраняват определени символи, команди или функции, и онези, които не са забранени, системата ги пропуска. Но при този подход ако пропуснеш само една опция от десетки възможни, цялата система се срутва.

В конкретния случай разликата в двата подхода се изразява в следното:

При първия подход нашият скрипт разрешава само един знак @ в полето Имейл без да се интересува по колко начина може да се инжектират повече адреси – втората маумунка @ спира изпълнението на скрипта.

При втория подход трябва да забраним всички възможни методи на инжектиране и логично само въвеждането на един единствен валиден имейл остава като разрешена опция – има ли обаче гаранция, че ние сме запознати с всички възможни спамърски техники така че филтрирането да осигури 100% защита от инжекция?

Дори в конкретния случай вариантите да са малък краен брой и да е възможно да се постигне 100% успеваемост на защитата, при решаване на по-сложни казуси от защита на имейл форма този подход ще доведе до грандиозни усложнения и многократно увеличаване на риска от грешка.

Заради тази разлика в подходите към идеята за сигурност хипер усложнените CMS-и като Joomla, Wordpress, Drupal и десетки други през няколко месеца се ъпдейтват и все има какво да им се коригира, въпреки че се състоят от по няколко хиляди файла и по тях работят стотици програмисти.

Тази статия е предназначена за уебмастери, привърженици на стила 'направи си сам' (какъвто съм и аз).

Ако вие сте собственик на сайт и сте решили да наемете програмист за изграждането на вашия сайт, вече знаете каква защита на контактната страница да си поръчате и да проверите дали е създадена, за да не си пишете със съпорта на хостинг компанията по-късно на тема спам.

За професионално написан мейл клас препоръчам ползването на PHPMailer , който е софтуер с отворен код, безплатен, и може да бъде изтеглен от тук:

http://sourceforge.net/projects/phpmailer/files/phpmailer%20for%20php5_6/PHPMailer%20v5.1/

Архива с тестовите файлове от примерната форма може да изтеглите от тук. Дизайна е само CSS така че формата може да се асоциира и по размер, и по цветова гама с всеки сайт с минимални корекции.

Моля ви, при тестване на формата ползвайте само ваши собствени мейл адреси!