SQL инжектиране в MySQL сървър

SQL инжектирането е уязвимост, която възниква в резултат на недостатъчна проверка на стойностите, получени от потребителя в скрипт или програма. Ще разгледам инжектирането на MySQL база данни. Тази база данни е една от най-разпространените. Освен ако не е посочено друго, предполага се, че инжектирането на mysql е възможно в php скрипт.

Откриване на наличието на SQL инжекция.

Често наличието на SQL инжектиране може да бъде указано от грешки, които ясно показват, че е възникнала грешка в sql заявката. В същото време наличието на грешка в SQL заявката може да се прецени и по косвени признаци.

За да проверим дали даден параметър е напълно филтриран или не, ние предаваме леко модифицирани стойности на този параметър. Например вместо http://site/test.php? >

Ако последната заявка върне страница, подобна на http://site/test.php? >

Анализ на база данни чрез MySQL инжекция.

И така, да кажем, че знаем за недостатъчно филтриране на параметъра >

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

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

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

За да се открият тези незначителни функции, трябва да се съставят известни http заявки, които ще доведат до валидна (но връщаща празен изход) SQL заявка икоето ще доведе до невалидна SQL заявка. Например с нефилтриран id параметър

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

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

1) брой полета между select и where

Опитваме последователно, докато получим правилната заявка:

освен това, ако не е възможно да отделите невалидната заявка от тази, която е върнала празен резултат, можете да направите следното:

За целта е достатъчно да можем да отделим правилната заявка от неправилната, а това винаги е възможно, ако има факт на SQL инжектиране.

След като получим правилната заявка, броят на нули ще бъде равен на броя на полетата между select и where

2) номера на колоната с изхода. Ще трябва да знаем в коя колона се появява изходът към страницата.

Въпреки това, ако на страницата се показват няколко параметъра, по-добре е да намерите този, който изглежда има най-големия размер на типа данни (текстът е най-добър), като описание на продукт, текст на статия и т.н. Търся го:

И докато не видим думата тест на мястото, от което се нуждаем.

Трябва да се отбележи, че в този случай една от тези заявки задължително ще върне непразна стойност.

Тук можете да се натъкнете на подводен камък: в скрипта може би има проверка за непразност на един от параметрите (например id) тук ще трябва да използвате свойството MySQL, числовият тип може да бъде прехвърлен към всеки тип данни, без грешка и по такъв начин, че да запази своязначение.

Същият трик ще работи, когато кавичките са екранирани.

Сега можем да обикаляме имената на таблиците.

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

вече имаме достатъчно информация, за да направим такова искане.

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

Освен това можете да научите много интересни неща:

5) имената на колоните в таблицата

Те са подобни, можете да сортирате чрез: http://site/test.php? >

текстови файлове чрез MySQL инжекция.

Ако потребителят, под който се осъществява достъп до базата данни, има права на file_priv, тогава можете да получите текста на произволен файл

записване на файлове в уеб директория (php shell).

Както показа практиката, ако имаме правата file_priv, директория, която може да се записва от всички потребители, също достъпна от мрежата (понякога директории за качване, банери и т.н.), и също така знаем името на поне една таблица (mysql.user, например, ще свърши работа, ако имате достъп до базата данни mysql), тогава можете да качите произволен файл на сървъра, като използвате инжекция от този тип.

В този случай е необходима конструкцията from table1.

Ако освен това сайтът има уязвимост, която позволява изпълнението на произволни файлове на сървъра (include("/path/$file.php")), тогава във всеки случай можете да качите php shell, например, в директорията /tmp/ и след това да вземете този файл от там, като използвате уязвимостта за включване.

инжектиране следлимит.

Доста част от възможността за SQL инжектиране възниква в рамките на параметъра, предаден на limit. Може да е номер на страница и т.н., и т.н.

Практиката показва, че всичко по-горе може да се приложи в този случай.

MySQL отговаря правилно на заявки като:

изберете. ограничение 1,2 избор на съюз.

изберете. ограничение 1 избор на съюз.

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

изберете. ограничение 99999.1 избор на съюз. Или изберете . ограничение 1.0 избор на съюз.

някои клопки.

Най-честата клопка може да бъде включването на магически кавички в конфигурацията на php. В случай на низови параметри, това обикновено ще избегне възможността за SQL инжектиране, а в случай на цели (дробни) параметри ще бъде невъзможно да се използват кавички в такива заявки и следователно низове.

Отчасти функцията char, която връща низ чрез кодове на символи, ще ни помогне да разрешим този проблем. Например

Единственото ограничение. Ако искате да направите в outfile, тогава като име на файл трябва да подадете името на файла в кавички. в outfile char(. ) извежда грешка.

Изглежда, че този модул на уеб сървъра на Apache прави невъзможно използването на уязвимостта на SQL инжектиране. Въпреки това, с някои конфигурации на PHP и този модул, атаката може да се извърши прозрачно за този модул.

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

По този начин могат да се предават стойности на злонамерени променливи, абсолютно прозрачни за mod_securityкато стойности на бисквитките.

Инжектиране на DOS към MySQL.

Ако не е възможно да се използва обединение в заявка, например MySQL е версия 3.*, тогава инжектирането все още може да бъде използвано, например за да принудите сървъра на базата данни да изчерпи всичките си ресурси.

За да направим това, ще използваме функцията BENCHMARK, която повтаря изпълнението на израза expr определения брой пъти, посочени в аргумента count. Като основен израз нека вземем функция, която сама по себе си изисква известно време. Например md5(). Нека вземем текуща_дата като низ, така че низът да не съдържа кавички. Функциите BENCHMARK могат да бъдат вложени една в друга. И така, ние правим заявка:

1000000 md5 заявки се изпълняват (в зависимост от капацитета на сървъра) за около 5 секунди, 10000000 ще бъдат изпълнени за около 50 секунди. Вложеният бенчмарк ще работи много дълго време на всеки сървър. Сега остава да изпратите до няколко десетки подобни http заявки в секунда, за да поставите сървъра дълбоко в дъното.

други видове MySQL инжекции.

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

mysql_query("изберете id от потребители, където парола като '".addslashes($password)."' и потребител като '".addslashes($user)."'");

в този случай паролата % ще бъде подходяща за всеки потребител

В някои случаи SQL инжектирането е възможно дори в параметър, който е преобразуван от методите mod_rewrite на модула apache в параметър на GET скрипт.

Например скриптове като /news/127.html се превеждат в /news/news.php?

Това ще позволи предаването на злонамерени стойностипараметър на скрипта. Така например /news/128-1.html

Накратко за защитата.

За да се предпазите от всичко по-горе, е достатъчно да следвате няколко прости правила.

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

Вместо това можете да вмъкнете система за проследяване на тестване на SQL инжекция.

//запишете в дневника за опита

2) за параметри на низ, които не се използват в like, regexp и т.н., избягвайте кавички.

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