Какво е SQL инжектиране и как да се предотврати в PHP приложения?

Значи смятате, че вашата SQL база данни е ефективна и безопасна от моментално унищожаване? Е, SQL Injection не е съгласен!


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

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

Какво е SQL инжектиране?

Ключът към разбирането на SQL инжектирането е в неговото име: SQL + инжектиране. Думата „инжекция“ тук няма медицински конотации, а по-скоро е употребата на глагола „инжектирам“. Заедно тези две думи предават идеята за въвеждане на SQL в уеб приложение.

Поставяне на SQL в уеб приложение. , , Хммм . , , Така ли не правим? Да, но не искаме нападател да управлява нашата база данни. Нека да разберем това с помощта на пример.

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

Твоето име

Твоето съобщение

И нека приемем, че файлът send_message.php съхранява всичко в база данни, за да могат по-късно собствениците на магазини да четат потребителски съобщения. Може да има някакъв код като този:

<?PHP

$ name = $ _POST [‘име’];
$ message = $ _POST [‘съобщение’];

// проверете дали този потребител вече има съобщение
mysqli_query ($ вр, "ИЗБЕРЕТЕ * от съобщения, където name = $ name");

// Друг код тук

Затова първо се опитвате да видите дали този потребител вече има непрочетено съобщение. Заявката SELECT * от съобщения, където name = $ name изглежда достатъчно просто, нали?

ГРЕШЕН!

С невинността си отворихме вратите за моменталното унищожаване на нашата база данни. За да се случи това, нападателят трябва да има следните условия:

  • Приложението работи на базата данни на SQL (днес почти всяко приложение е)
  • Текущата връзка с база данни има разрешения за „редактиране“ и „изтриване“ в базата данни
  • Имената на важните таблици могат да се познаят

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

Джо; съкращават поръчки ;? Да сър! Нека да видим каква ще стане заявката, когато бъде изпълнена от PHP скрипта:

ИЗБЕРЕТЕ * ОТ съобщения, КЪДЕ име = Джо; съкращават поръчки;

Добре, първата част на заявката има грешка в синтаксиса (без кавички около „Joe“), но полу-двоеточието принуждава MySQL двигателя да започне да интерпретира нов: прерязване на поръчки. Просто така, с един единствен удар, цялата история на поръчките няма!

Сега, когато знаете как работи SQL Injection, е време да разгледате как да го спрете. Двете условия, които трябва да бъдат изпълнени за успешното инжектиране на SQL са:

  1. PHP скриптът трябва да има модифициране / изтриване на привилегии в базата данни. Мисля, че това важи за всички приложения и няма да можете да направите приложенията си само за четене. �� И познайте какво, дори ако премахнем всички права за модифициране, SQL инжектирането все още може да позволи на някого да изпълнява SELECT заявки и да прегледа цялата база данни с включени чувствителни данни. С други думи, намаляването на нивото на достъп до база данни не работи и приложението ви се нуждае от това.
  2. Потребителското въвеждане се обработва. Единственият начин да работи SQL инжектирането е, когато приемате данни от потребители. Още веднъж не е практично да спирате всички входове за приложението си, само защото се притеснявате за инжектиране на SQL.

Предотвратяване на SQL инжектиране в PHP

Сега, като се има предвид, че връзките към базата данни, заявките и потребителските входове са част от живота, как да предотвратим инжектирането на SQL? За щастие, това е доста просто и има два начина да го направите: 1) санирайте въвеждането на потребителя и 2) използвайте подготвени оператори.

Санирайте потребителското въвеждане

Ако използвате по-стара версия на PHP (5.5 или по-нова версия и това се случва много при споделен хостинг), е разумно да стартирате целия си потребителски вход чрез функция, наречена mysql_real_escape_string (). По принцип това, което прави, премахва всички специални символи в низ, така че те да загубят значението си, когато се използват от базата данни.

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

Има един недостатък при този подход: това е наистина, наистина стара техника, която върви заедно с по-старите форми на достъп до база данни в PHP. Относно PHP 7 тази функция вече дори не съществува, което ни отвежда към следващото ни решение.

Използвайте подготвени изявления

Подготвените изявления са начин да направите заявките към базата данни по-безопасно и надеждно. Идеята е, че вместо да изпращаме суровата заявка към базата данни, първо казваме на базата данни структурата на заявката, която ще изпратим. Това имаме предвид под „подготовката“ на изявление. След като декларация е подготвена, ние предаваме информацията като параметризирани входове, така че базата данни да може да „запълни пропуските“, като включи входовете към структурата на заявките, която изпратихме преди. Това отнема всяка специална мощност, която може да имат входовете, което води до това да се третират като променливи (или полезни натоварвания, ако щете) в целия процес. Ето как изглеждат подготвените изявления:

<?PHP
$ servername = "Localhost";
$ username = "потребителско име";
$ password = "парола";
$ dbname = "myDB";

// Създаване на връзка
$ conn = new mysqli ($ servername, $ username, $ password, $ dbname);

// Проверете връзката
ако ($ conn->connect_error) {
умре ("Свързването е неуспешно: " . $ вр->connect_error);
}

// подготвя се и се свързва
$ stmt = $ conn->приготви се("ВЪВЕДЕТЕ В MyGuests (име, фамилия, имейл) ЦЕННОСТИ (?,?,?)");
$ stmt->bind_param ("SSS", $ име, $ фамилия, $ имейл);

// задаване на параметри и изпълнение
$ firstname = "Джон";
$ lastname = "Сърна";
$ имейл = "[Имейл защитен]";
$ stmt->изпълни();

$ firstname = "Дева Мария";
$ lastname = "Moe";
$ имейл = "[Имейл защитен]";
$ stmt->изпълни();

$ firstname = "Джули";
$ lastname = "Дули";
$ имейл = "[Имейл защитен]";
$ stmt->изпълни();

ехо "Новите записи са създадени успешно";

$ stmt->близо();
$ вр->близо();
?>

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

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

Предупреждение: Внимавайте при настройка на ЗНП

Когато използваме PDO за достъп до база данни, можем да бъдем засмукани в невярно чувство за сигурност. „А, добре, използвам ЗНП. Сега не е нужно да мисля за нищо друго “- така по принцип мисленето ни върви. Вярно е, че PDO (или MySQLi подготвени изявления) са достатъчни, за да се предотвратят всякакви атаки на SQL инжектиране, но трябва да бъдете внимателни, когато го настройвате. Обичайно е просто да копирате и поставите код от уроци или от по-ранните си проекти и да продължите, но тази настройка може да отмени всичко:

$ dbConnection->setAttribute (PDO :: ATTR_EMULATE_PREPARES, вярно);

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

Решението е просто: уверете се, че тази емулация е зададена на false.

$ dbConnection->setAttribute (PDO :: ATTR_EMULATE_PREPARES, невярно);

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

Предотвратяване на използването на WAF

Знаете ли, че можете също да защитите уеб приложения от SQL инжектиране, като използвате WAF (защитна стена на уеб приложение)?

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

SQL инжекция и модерни PHP рамки

Инжектирането на SQL е толкова често, толкова лесно, толкова разочароващо и толкова опасно, че всички съвременни PHP уеб рамки са вградени с мерки за противодействие. В WordPress например имаме $ wpdb->Пригответе () функция, докато ако използвате MVC рамка, тя върши цялата мръсна работа за вас и дори не е нужно да мислите за предотвратяване на SQL инжектиране. Малко е досадно, че в WordPress трябва да подготвяте изрично изявления, но ей, за WordPress говорим. ��

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

заключение

SQL Injection е много гадна атака на уеб приложение, но лесно се избягва. Както видяхме в тази статия, вниманието при обработката на потребителски вход (между другото, SQL Injection не е единствената заплаха, която носи обработката на потребителски вход) и заявяването на база данни е всичко, което има за него. Това каза, че ние не винаги работим в сигурността на уеб рамка, така че е по-добре да сме наясно с този тип атака и да не си падаме за нея.

Jeffrey Wilson Administrator
Sorry! The Author has not filled his profile.
follow me
    Like this post? Please share to your friends:
    Adblock
    detector
    map