Ïðàêòè÷åñêèå ñîâåòû ïî ïðåäîòâðàùåíèþ óÿçâèìîñòåé âèäà sql-injection
Àâòîð: | Èâàí Êîðæàâèí |
email: | korjavin@yandex.ru |
Îáùàÿ èäåÿ.
 ïðîöåññå ðàáîòû íàøåãî âåá ïðèëîæåíèÿ ìû ðàáîòàåì ñ äàííûìè, êîòîðûå ïîëó÷àåì îò íàøèõ ïîëüçîâàòåëåé.
Ýòî ìîãóò áûòü html ôîðìû, http get/post çàïðîñû, ajax çàïðîñû, è ïðî÷åå.
Ïðè íåäîñòàòî÷íîé ïðîâåðêå âíåøíèõ äàííûõ, çëîóìûøëåííèê ìîæåò ïîäîáðàòü òàêîé íàáîð, êîòîðûé çàñòàâèò íàø êîä âûïîëíèòü íå ïëàíèðóåìîå äåéñòâèå.
Àòàê òàêîãî òèïà ìíîãî, ýòî è ïåðåïîëíåíèå ñòåêà, è ïåðåãðóçêà ñèñòåìû âåäóùàÿ ê îòêàçàì â îáñëóæèâàíèè, è äðóãèå.
Ìû ðàññìîòðèì óçêèé êëàññ òàêèõ àòàê sql injection èëè "âíåäðåíèå sql" êàê ñàìûé ðàñïðîñòðàíåííûé.
Ïðîñòåéøèé ïðèìåð
 ñàìîì ïðîñòåéøåì âèäå, àòàêà âûãëÿäèò òàê:
- Ó íàñ åñòü html ôîðìà, êîòîðàÿ ïðèíèìàåò äàííûå îò ïîëüçîâàòåëÿ, íàïðèìåð åãî e-mail
- Êîä êîòîðûé îáðàáàòûâàåò ýòó ôîðìó, äåëàåò çàïðîñ ê íàøåé áàçå äàííûõ, äîáàâëÿÿ çàïèñü ñ e-mail ïîëüçîâàòåëÿ â òàáëèöó.
- Çëîóìûøëåííèê ïåðåäàåò íàì â html ôîðìå ñòðîêó
1'); drop table users; /*
Òîãäà íàø êîä îòïðàâèò â áàçó äàííûõ òàêîé çàïðîñinsert into sometable (email) values ('1'); drop users; /* ')
Êîòîðûé ïîìèìî âñòàâêè çàïèñè åùå è óäàëèò íàì òàáëèöó users.
Îñíîâíûå ìîìåíòû: çëîóìûøëåííèê èñïîëüçîâàë òî÷êó ñ çàïÿòîé äëÿ ðàçäåëåíèÿ çàïðîñîâ, è çíàê êîììåíòàðèÿ äëÿ îòáðàñûâàíèÿ õâîñòà çàïðîñà.
Ïðèìåð ïîñëîæíåå
Ïóñòü ó íàñ åñòü îòäåëüíàÿ ÷àñòü ñàéòà äëÿ àäìèíèñòðàòîðîâ. Ïðè ïîïûòêå âîéòè â íåå ìû çàïðàøèâàåì îñîáûé ëîãèí è ïàðîëü.
Èñïîëüçóåìûé çàïðîñ:
Âìåñòî ïåðåáîðà ëîãèí ïàðîëü, çëîóìûøëåííèê ïåðåäàñò âìåñòî login ñòðî÷êó
Admin' --
Ïîëó÷èâ çàïðîñ:
select * from admins where login='Admin' -- ' and pass=''
Òàê êàê, äâîéíîé äåôèñ ýòî íà÷àëî îäíîñòðî÷íîãî êîììåíòàðèÿ, íåâàæíî êàêîé ïàðîëü ó ïîëüçîâàòåëÿ Admin, çàïðîñ áóäåò óñïåøíûì.
Ïðèìåð ïîñëîæíåå ñ êîäèðîâêîé
Ôîðìà àíàëîãè÷íàÿ ïðåäûäóùåé, íî êàêèì ëèáî îáðàçîì â ôîðìó çàïðåùåíî ââîäèòü ïðîáåëû è êàâû÷êè.
Çëîóìûøëåííèê ïåðåäàåò ñòðîêó:
Admin%27/*test*/--+
 ýòîé ñòðîêå, %27 ñïîñîá ïåðåäàòü êàâû÷êó, è äâà ñïîñîáà ïåðåäàòü ïðîáåë. Ïåðâûé ñ ïîìîùüþ êîììåíòàðèÿ, à äëÿ ÑÓÁÄ mysql ëþáîé êîììåíòàðèé ðàçäåëèòåëü. Âòîðîé ñ ïîìîùüþ ñèìâîëà +
Ðóáåæè îáîðîíû
Ðàçáåðåì îñíîâíûå ðóáåæè, ãäå ìû ìîæåì ôèëüòðîâàòü ýòè àòàêè:
- Ïðîâåðêà äàííûõ íà ñòîðîíå áðàóçåðà êëèåíòà ñ ïîìîùüþ javascript.
- Ïðîâåðêà ââåäåííûõ ïîëüçîâàòåëåì äàííûõ íà ñòîðîíå ñåðâåðà - web ñåðâåðà.
- Ïðîâåðêè ââåäåííûõ ïîëüçîâàòåëåì äàííûõ íà ñòîðîíå ñêðèïòà - èíòåðïðåòàòîðà php.
- Èçìåíåíèå ñïîñîáà ôîðìèðîâàíèÿ ñòðîêè çàïðîñà
Ïåðâûé ïóíêò - âàëèäàöèÿ äàííûõ ñ ïîìîùüþ áðàóçåðíûõ ñêðèïòîâ, ìîæåò áûòü îòáðîøåí ñðàçó, êëèåíò âñåãäà ìîæåò îòêëþ÷èòü ëþáîé javascript â ñâîåì áðàóçåðå, èëè ñîâñåì íå èñïîëüçîâàòü áðàóçåð äëÿ ïîñûëêè çàïðîñà, à èñïîëüçîâàòü áèáëèîòåêè òèïà curl.
Âòîðîé ïóíêò - web ñåðâåð, ñêîðåå âñåãî, ïåðâûì ïðèíèìàåò äàííûå ïîëüçîâàòåëÿ, è óæå çäåñü ìû ìîæåì ïðîèçâåñòè íåêîòîðûå, ïðîñòåéøèå ôèëüòðàöèè: îáðåçàòü query string ïî ñòîï-ñëîâàì.
- Ïðèìåð äëÿ apache:
- Ïðèìåð äëÿ nginx:
Ïî ìîåìó ìíåíèþ, ýòî î÷åíü ñëàáûé ñïîñîá. Ìû íèêîãäà íå ñìîæåì ïðåäóñìîòðåòü âñå âàðèàíòû ïåðåäàâàåìûõ äàííûõ, è áîëåå òîãî ìíîãèå èç íèõ, áóäóò àáñîëþòíî ëåãàëüíû è íå ñâÿçàíû ñ àòàêàìè â îïðåäåëåííûõ êîíòåêñòàõ.
Ê òîìó æå äàííûå ìîãóò ïåðåäàâàòüñÿ çàêîäèðîâàíî-èñêàæåííûì ñïîñîáîì è ðàçëè÷íûìè ìåòîäàìè post/put.
Ýòîò ñïîñîá èìååò ñìûñë òîëüêî â î÷åíü îãðàíè÷åííûõ ñöåíàðèÿõ. Íàïðèìåð, â ðåçóëüòàòå àíàëèçà ëîã-ôàéëîâ ñâîåãî âåáñåðâåðà âû óâèäåëè äîñòàòî÷íî äëèííóþ ïîâòîðÿþùóþñÿ ñòðîêó, ÷òî òî âðîäå
%27+having+1%3D1--+
òî ìîæíî åå çàáëîêèðîâàòü, òîëüêî äëÿ òîãî ÷òî áû íå íàãðóæàòü áåñïîëåçíîé ðàáîòîé îñòàëüíûå ÷àñòè âàøåãî ïðèëîæåíèÿ. Íî íàäåÿòüñÿ íà ýòîò ñïîñîá íå ñëåäóåò.
Òðåòèé ïóíêò - ñêðèïò php.  êîäå php ìû ñìåëî âñòàâëÿåì ïîëó÷åííûå îò ïîëüçîâàòåëÿ äàííûå â çàïðîñ, ÷òî êàòåãîðè÷åñêè íåëüçÿ äåëàòü. Ìû îáÿçàíû ïðîâåðèòü ïåðåäàííûå íàì ïàðàìåòðû ñ ïîìîùüþ ðåãóëÿðíûõ âûðàæåíèé, èëè ïðîïóñòèòü èõ ÷åðåç ôóíêöèè óäàëÿþùèå ýêðàíèðîâàíèå, è ïðî÷åå, íàïðèìåð mysql_real_escape_string.
Ýòîò ñïîñîá óæå äàåò êîå-êàêóþ ãàðàíòèþ, è ÿ âñåãäà ðåêîìåíäóþ ïðîâåðÿòü äàííûå îò ïîëüçîâàòåëåé. Ïðîäóìàéòå çàðàíåå, êàêèå èìåííî äàííûå äîïóñòèìû, è ïðîâåðÿéòå èõ â ñàìîì íà÷àëå, äî ïåðåäà÷è â êàêèå ëèáî ôóíêöèè.
×åòâåðòûé ñïîñîá - èçìåíåíèå ñïîñîáà ôîðìèðîâàíèÿ çàïðîñà. Íàïðèìåð:
 ýòîì ïðèìåðå ìû èñïîëüçóåì íåêèé øàáëîí äëÿ sql, êîòîðûé çàïîëíÿåì äàííûìè ñ ïîìîùüþ ôóíêöèè sprintf, à îíà ïðîâåäåò äëÿ íàñ ïðîâåðêó òèïîâ.
Íî åñòü ñïîñîá åùå ëó÷øå. Èñïîëüçîâàòü ïàðàìåòðû sql. Ïðèìåð:
 ýòîì ïðèìåðå ìíîãî ïëþñîâ ïî ñðàâíåíèþ ñ ïðåäûäóùèìè ïóíêòàìè. Âî ïåðâûõ, ìû ïî ïðåæíåìó ïðîâåðÿåì òèï ïàðàìåòðà, ôóíêöèåé bind_param, âî âòîðûõ ìû ñòðîèì çàïðîñ ñ ïîìîùüþ ÑÓÁÄ áåç ïîëüçîâàòåëüñêèõ äàííûõ.
Ýòî îçíà÷àåò ÷òî çàïðîñ êîòîðûé ìû ïåðåäàëè ñ ïîìîùüþ ôóíêöèè prepare, áóäåò ðàçîáðàí íà ñòîðîíå mysql çàðàíåå. Áóäåò ñîñòàâëåí åãî ïëàí, è çàïðîñ ïðåîáðàçîâàí â ñòðóêòóðû mysql. Ïîýòîìó, åñëè ïîëüçîâàòåëüñêèå äàííûå êàêèì òî îáðàçîì ïîïðîáóþò "ñëîìàòü" ëîãèêó çàïðîñà, îí íå áóäåò âûïîëíåí, è ïîýòîìó æå ïîëüçîâàòåëüñêèå äàííûå íå áóäóò ðàññìàòðèâàòüñÿ êàê óïðàâëÿþùèå êîìàíäû sql.
Äîïîëíèòåëüíûì ïëþñîì ýòîãî ìåòîäà áóäåò òî, ÷òî åñëè çàïðîñ íóæíî âûïîëíèòü íåñêîëüêî ðàç ñ ðàçíûìè äàííûìè, âàì íå íóæíî áóäåò êîíñòðóèðîâàòü è ïåðåäàâàòü åãî â ÑÓÁÄ, âû ïðîñòî ïåðåäàäèòå ñëåäóþùèé íàáîð ïàðàìåòðîâ, è ñýêîíîìèòå âðåìÿ íà ïðîöåäóðàõ ãåíåðàöèè çàïðîñà â âàøåì ñêðèïòå, è íà ðàçáîðå çàïðîñà ñî ñòîðîíû ÑÓÁÄ.
Î÷åíü ðåêîìåíäóþ èñïîëüçîâàòü ýòîò ñïîñîá - sql çàïðîñû ñ ïàðàìåòðàìè.