Back to site

SQL-ін'екцыя Напады на прыкладзе

Кліент папрасіў нас праверыць свой інтранэт-сайт, які быў выкарыстаны супрацоўнікамі кампаніі і кліентамі. Гэта было часткай больш шырокага агляду бяспекі, і хоць мы фактычна не выкарыстоўваецца SQL-ін'екцыі, каб пранікнуць сеткі і раней, мы былі вельмі знаёмыя з агульнымі паняццямі. Мы былі цалкам паспяховымі ў гэтым баі, і хацеў расказаць мерах, прынятых у якасці ілюстрацыі.

SQL-ін'екцыя "з'яўляецца падмноствам неправераную / unsanitized уразлівасці карыстацкі ўвод (" перапаўненне буфера "з'яўляюцца розныя падмноства), і ідэя, каб пераканаць прыкладанні для запуску SQL кода, які не быў прызначаны. Калі дадатак стварае SQL радкоў наіўна "на лета", а затым запускаць іх, гэта проста стварыць некалькі сюрпрызаў.

Мы адзначаем, што гэта было некалькі звілістай дарозе з больш чым адным няправільны паварот, і іншыя з вялікім вопытам, безумоўна, маюць розныя - і лепш - падыходы. Але тое, што мы былі паспяховымі дазваляе выказаць здагадку, што мы не былі цалкам памылковымі.

Там былі і іншыя дакументы па ін'екцыі SQL, у тым ліку тыя, якія з'яўляюцца значна больш падрабязнымі, але гэта паказвае, абгрунтаванне адкрыцця столькі, колькі працэсе эксплуатацыі.


Мэтавая Інтранэт

Гэта апынулася зусім карыстальніцкае дадатак, і ў нас не было папярэдніх ведаў аб прыкладання, ні доступу да зыходнага коду: гэта быў "сляпы" атакі. Трохі тыкаць паказалі, што гэты сервер IIS бег ад Microsoft 6 разам з ASP.NET, і гэта сведчыць, што база дадзеных SQL Server Microsoft: мы лічым, што гэтыя метады могуць прымяняцца да практычна любой вэб-прыкладанняў пры падтрымцы любых SQL Server.

Увайсці Старонка традыцыйных імя карыстальніка і пароля-форме, але і электроннай пошце мне мой пароль-спасылку; апошняе апынулася падзенне ўсёй сістэмы.

Пры ўводзе адрасы электроннай пошты, сістэмы меркавана паглядзеў у базу дадзеных карыстальнікаў для гэтага адрасу электроннай пошты, і што-то па пошце на гэты адрас. Так як мой электронны адрас не знойдзены, ён не збіраецца паслаць мне што-небудзь.

Такім чынам, першы тэст у любы SQL-иш форма для ўводу адной выняткай, як частка дадзеных: намер, каб убачыць, калі яны пабудаваць радок SQL літаральна без дэзінфекцыі. Пры падачы формы з цытатай ў адрас электроннай пошты, мы атрымліваем памылку 500 (збой сервера), і гэта сведчыць аб тым, што "зламаны" уваход фактычна разабраны літаральна. Бінга.

Мы лічым, што зыходны код SQL выглядае прыкладна так:

SELECT fieldlist
 FROM table
 WHERE field = '$EMAIL';

Тут $ электроннай пошты адрас прадстаўленых на форме карыстальніка, і больш запытаў забяспечвае двукоссі, якія ўсталёўваюць гэта як знакавая радок. Мы не ведаем канкрэтныя імёны палёў або табліц удзел, але мы ведаем іх характар, і мы зробім добры здагадкі пазней.

Калі мы ўваходзім steve@unixwiz.net "- зьвярніце ўвагу на двукоссі закрыцця - гэта дае пабудаваныя SQL:

SELECT fieldlist
 FROM table
 WHERE field = 'steve@unixwiz.net'';

пры гэтым выконваецца, парсер SQL знайсці дадатковыя двукоссі і перапыняе з сінтаксічная памылку. Як гэта праяўляецца для карыстальніка залежыць ад унутранай памылкі аднаўлення прыкладання працэдур, але гэта, як правіла, адрозніваецца ад "адрас электроннай пошты, невядома". Гэтая памылка адказ мёртвых паддаўкі, што ўводзяцца карыстальнікам дадзеныя не прадэзінфікаваць правільна і што прыкладанне гатова для эксплуатацыі.

Так як дадзеныя мы запаўненне ўяўляецца, у ИНЕКЕ, давайце зменім характар, што агаворка ў SQL законным шляхам і паглядзець, што адбываецца. Пры ўводзе 'нічога' ці х '=' х, у выніку SQL з'яўляецца:

SELECT fieldlist
 FROM table
 WHERE field = 'anything' OR 'x'='x';

Так як дадатак на самай справе не думаў пра запыту - проста пабудовы радкі - наша выкарыстанне цытат ператварыўся аднакампанентная ИНЕКЕ ў двухкампанентны адзін, і 'х' = х 'прапанову' гарантавана, каб быць праўдай незалежна ад таго, што першы пункт з'яўляецца (ёсць лепшы падыход для гэтага "заўсёды так" частка, мы пагаворым пазней).

Але ў адрозненне ад "рэальнай" запыт, які павінен вяртаць толькі адзін элемент кожны раз, гэтая версія будзе істотна вярнецеся кожны элемент у базе даных членаў. Адзіны спосаб даведацца, якія прыкладання будуць рабіць у гэтую акалічнасць, каб паспрабаваць. Такім чынам, мы былі сустрэтыя з:


Ваш Лагін інфармацыя была почте@example.com random.person.

Нашы лепшыя думаю, што гэта першая запіс, вяртаюцца запытам, эфектыўна ўступлення узятых наўздагад. Гэты чалавек сапраўды атрымаць гэта забыліся пароль-спасылку па электроннай пошце, якая, верагодна, стала сюрпрызам для яго і можа паставіць папераджальныя сцягі где-то.

Мы цяпер ведаем, што мы можам маніпуляваць на запыт нашых мэтаў, хоць мы яшчэ не ведаем многае пра яго часткі мы не бачым. Але мы назіралі тры розных адказаў на нашы розныя ўваходы:

Першыя дзве ўяўляюць сабой рэакцыю на правільна сфармаваны SQL, у той час як апошняя з'яўляецца для дрэнных SQL: гэта адрозненне будзе вельмі карысна, калі спрабуе адгадаць структуру запыту.

Схема палі адлюстравання

Першыя крокі да мяркую, што некаторыя імёны палёў: мы дастаткова ўпэўненыя, што запыт утрымлівае "электронны адрас" і "Пароль", і там могуць быць рэчы, як "ЗША ліст" або "ідэнтыфікатар карыстальніка" ці "нумар тэлефона". Мы б вельмі люблю выконваць SHOW TABLE, але ў дадатак да не ведаючы імя табліцы, не існуе відавочных транспартнага сродку, каб атрымаць выснову гэтай каманды накіроўваюцца да нас.

Такім чынам, мы зробім гэта па крокаў. У кожным выпадку, мы будзем паказваць увесь запыт як мы яго ведаем, з нашай уласнай фрагменты паказалі адмыслова. Мы ведаем, што хвост запыт параўнанні з адрасу электроннай пошты, так што давайце думаю электроннай пошты ў якасці імя поля:

SELECT fieldlist
 FROM table
 WHERE field = 'x' AND email IS NULL; --';

Мэта заключаецца ў выкарыстанні прапанаванага наймення поля (электроннай пошце) у пабудаваным запыт і высветліць, калі SQL з'яўляецца сапраўдным ці не. Мы не клапоцімся аб адпаведнасці адрас электроннай пошты (менавіта таму мы выкарыстоўваем манекена "х"), і - адзначае пачатак каментара SQL. Гэта эфектыўны спосаб "спажываць" канчатковага цытатай забяспечваецца шляхам прымянення і не турбавацца аб адпаведнасці іх.

Калі мы атрымаем памылка сервера, гэта азначае, што нашы SQL будзе няслушным і сінтаксічныя памылкі быў кінуты: ён, хутчэй за ўсё, з-за дрэннай імя поля. Калі мы атрымаем любы правільны адказ, мы здагадаліся, імя правільна. Гэта тычыцца ці мы атрымаць "электронны невядома" ці "Пароль быў адпраўлены" адказ.

Аднак варта адзначыць, што мы выкарыстоўваем разам і замест OR: гэта наўмысна. У адлюстраванне фазы SQL схему, мы сапраўды не звязаных з адгадаць якой-небудзь канкрэтнай адрасы электроннай пошты, і мы не хочам выпадковых карыстальнікаў заваленыя "Вось ваш пароль" лісты з дадатку - гэта, безумоўна, выклікаць падазрэнні ні да чаго добрага мэты. Пры выкарыстанні сумесна з І адрас электроннай пошты, які не мог быць сапраўдным, мы ўпэўненыя, што запыт будзе заўсёды вяртаць нуль радкоў і ніколі не генерыраваць пароль-напамін па электроннай пошце.

Адпраўка вышэй фрагмент сапраўды даў нам "адрас электроннай пошты невядомыя" адказ, так што зараз мы ведаем, што адрас электроннай пошты захоўваецца ў полі электроннай пошце. Калі б гэтага не працавалі, мы б пастараліся email_address або па пошце ці як. Гэты працэс будзе ўключаць даволі шмат гадаць.

Далей мы мяркую, што некаторыя іншыя відавочныя назвы: пароль, ідэнтыфікатар карыстальніка, імя і таму падобнае. Гэта ўсё робіцца па аднаму, і нічога, акрамя "адмовы сервера" азначае, што мы адгадалі назву правільна.

SELECT fieldlist
 FROM table
 WHERE email = 'x' AND userid IS NULL; --';

У выніку гэтага працэсу, мы знайшлі некалькі дапушчальных імёнаў поля:

Ёсць, безумоўна, больш (і добрая крыніца ключы, гэта імёны палёў на формах), але трохі капаць не выявілі. Але мы яшчэ не ведаем, імя табліцы, што гэтыя палі знаходзяцца у - як пазнаць?

Пошук імя табліцы

Ужыванне убудаваных у запыт ўжо ёсць імя табліцы убудаваныя ў яе, але мы не ведаем, што гэта імя: Ёсць некалькі падыходаў, што для знаходжання (і іншыя) імёны табліц. Той, які мы прынялі быў спадзявацца на подзапросов.

Аўтаномны запыт

SELECT COUNT(*) FROM tabname

Вяртае колькасць запісаў у гэтай табліцы, і, вядома, не выконваецца, калі імя табліцы, невядома. Мы можам пабудаваць гэта ў нашым радок зонд для імя табліцы:

SELECT email, passwd, login_id, full_name
 FROM table
 WHERE email = 'x' AND 1=(SELECT COUNT(*) FROM tabname); --';

Нам усё роўна, колькі запісаў ёсць, вядома, ці толькі імя табліцы з'яўляецца сапраўдным ці не. Паўтараючы за некалькі здагадак, мы ў канчатковым выніку вызначаецца, што члены былі сапраўдныя табліцы ў базе дадзеных. Але гэта табліца, выкарыстоўваная ў гэтым запыце? Для гэтага нам спатрэбіцца яшчэ адно выпрабаванне з выкарыстаннем табліцы. Поля абазначэння ён працуе толькі для табліц, якія з'яўляюцца фактычна часткай гэтага запыту, а не толькі тое, што табліца існуе.

SELECT email, passwd, login_id, full_name
 FROM members
 WHERE email = 'x' AND members.email IS NULL; --';

Пры гэтым вяртаецца "Email невядома", ён пацвердзіў, што наша SQL быў добра сфарміраваны і што мы правільна здагадаліся, імя табліцы. Гэта будзе важна пазней, але замест гэтага мы ўзялі іншы падыход у прамежкавы перыяд.

Пошук некаторых карыстальнікаў

На дадзены момант мы маем частковае ўяўленне аб структуры табліцы членаў, але мы ведаем толькі аднаго імя карыстальніка: выпадковых членаў, якія атрымалі нашы першапачатковыя "Вось ваш пароль" па электроннай пошце. Нагадаем, што мы ніколі не атрымалі паведамленне, а толькі адрас было адпраўлена ліст. Мы хацелі б атрымаць яшчэ некалькі імёнаў для працы, пажадана тых, верагодна, маюць доступ да больш дадзеных.

Першае месца, каб пачаць, вядома, вэб-сайт кампаніі, каб высветліць, хто ёсць хто: "Аб нас" ці "Кантакт" Старонкі з спісу, які часта працуе месцы. Многія з іх утрымоўваюць адрасы электроннай пошты, але нават тыя, якія не пералічыць іх можа даць нам некаторыя падказкі, якія дазваляюць нам знайсці іх з дапамогай нашага інструмента.

Ідэя прадставіць запыт, які выкарыстоўвае падабаецца прапанова, што дазваляе нам рабіць частковыя супадзення імёнаў ці адрасоў электроннай пошты ў базу дадзеных, кожны раз выклікаючы "Мы накіравалі свой ??пароль" паведамленняў і электроннай пошце:. Папярэджанне хоць гэта паказвае, адрас электроннай пошты Кожны раз, калі мы запускаем яго, ён таксама фактычна адпраўляе гэта паведамленне, якое можа выклікаць падазрэнні. Гэта дазваляе выказаць здагадку, што мы прымаем гэта лёгка.

Мы можам зрабіць запыт па электроннай пошце імя або прозвішча, імя (або як мяркуецца, іншую інфармацыю), кожны раз, пакласці ў% маскі, што, як падтрымлівае:

SELECT email, passwd, login_id, full_name
 FROM members
 WHERE email = 'x' OR full_name LIKE '%Bob%';

Майце на ўвазе, што, хоць можа быць і больш, чым адзін "Боб", мы толькі атрымліваем, каб убачыць адзін з іх: гэта прадугледжвае перапрацоўку нашых падабаецца прапанова вузка.

У канчатковым рахунку, мы можа спатрэбіцца толькі адзін сапраўдны адрас электроннай пошты, каб выкарыстаць нашы шляхі цалі

Лабавая атака тыпу падбору пароля

Вядома, можна спрабаваць грубай сілай угадвання пароля на галоўнай старонцы Лагін, але шматлікія сістэмы робяць намаганні па выяўленні або нават прадухіліць гэта. Там можа быць логах, блакіроўкі уліковых запісаў, або іншыя прылады, якія б істотна перашкаджаць нашым намаганням, але з-за не-санітарнай апрацоўцы ўваходу, у нас ёсць іншы шлях, які значна менш верагодна, так абаронены.

Мы замест гэтага фактычнага тэсціравання пароль у нашай фрагмент па электроннай пошце ў тым ліку імя і пароль непасрэдна. У нашым прыкладзе мы будзем выкарыстоўваць нашы ахвяры, bob@example.com і паспрабуйце некалькі пароляў.

SELECT email, passwd, login_id, full_name
 FROM members
 WHERE email = 'bob@example.com' AND passwd = 'hello123';

Гэта добра добра сфармаваныя SQL, таму мы не чакаем убачыць любыя памылкі сервера, і мы будзем ведаць, мы выявілі, пароль, калі мы атрымаем "Ваш пароль быў высланы Вам" паведамленні. Нашы маркі ў цяперашні час шапнулі, але ў нас ёсць свой пароль.

Гэтая працэдура можа быць аўтаматызаваны з дапамогай сцэнарыяў на Perl, і хоць мы знаходзіліся ў працэсе стварэння гэтага сцэнарыя, мы ў канчатковым выніку адбываецца па іншай дарозе, перш чым на самай справе спрабуе яго.

База дадзеных не толькі для чытання

Да гэтага часу мы нічога не зрабілі, але запыт да базы дадзеных, і, хоць SELECT толькi для чытання, гэта не азначае, што SQL з'яўляецца. SQL выкарыстоўвае кропку з коскай для спынення заяву, і, калі ўвод не прадэзінфікаваць належным чынам, не можа быць нічога, што перашкаджае нам струн нашай каманды звязаны ў канцы запыту.

Найбольш рэзкае прыклад:

SELECT email, passwd, login_id, full_name
 FROM members
 WHERE email = 'x'; DROP TABLE members; --'; -- Boom!

Першая частка забяспечвае фіктыўны адрас электроннай пошты - "х" - і мы не хвалюе, што гэты запыт вяртае: мы толькі што з дарогі, каб мы маглі ўвесці звязаных каманду SQL. Гэта адзін спрабуе выдаліць (выдаліць) усю табліцу членаў, якія сапраўды не здаецца занадта спартовым.

Гэта паказвае, што не толькі мы можам запускаць асобныя каманды SQL, але мы можам таксама змяніць базу дадзеных. Гэта абнадзейвае.

Даданне новага члена

Улічваючы, што мы ведаем частковае структура табліцы членаў, здаецца праўдападобным падыход да спробе дадаць новую запіс у гэтай табліцы: Калі гэта працуе, мы проста быць у стане Увайсці непасрэдна з нашымі зноў ўстаўляецца паўнамоцтвы.

Гэта не дзіўна, што займае крыху больш SQL, і мы загарнулі яго на працягу некалькіх ліній для прастаты выкладу, але са свайго боку яшчэ адзін бесперапынны радкі:

SELECT email, passwd, login_id, full_name
 FROM members
 WHERE email = 'x';
    INSERT INTO members ('email','passwd','login_id','full_name') 
    VALUES ('steve@unixwiz.net','hello','steve','Steve Friedl');--';

Нават калі мы фактычна атрымалі нашы палі і імёны табліц права, некалькі рэчаў, мог трапіць у наш спосаб паспяховай атакі:

  1. Мы, магчыма, не хапае месца ў вэб-форму для ўводу гэта шмат тэксту прама (хоць гэта можна абыйсці з дапамогай сцэнарыяў, гэта значна менш зручна).
  2. Прыкладання карыстальнік Сеткі можа не мець дазвол INSERT на стол членаў.
  3. Ёсць, несумненна, іншых палёў у табліцы членаў, а некаторыя могуць запатрабаваць пачатковых значэнняў, у выніку чаго INSERT на правал.
  4. Нават калі нам атрымаецца, каб ўставіць новую запіс, само дадатак не можа паводзіць сябе добра ў сувязі з аўтаматычнай ўстаўляецца NULL палёў, што мы не прадставілі значэння.
  5. Сапраўдны "член" можа запатрабаваць не толькі запіс у табліцы членаў, але звязанай з імі інфармацыі ў іншых табліцах (напрыклад, "AccessRights"), так што даданне ў адну табліцу ў адзіночку не можа быць дастатковым.

У нашым выпадку, мы трапілі на кантрольна-прапускным пункце або № 4 або № 5 - мы не можам быць упэўненыя, - таму што, калі збіраецца асноўны Лагін старонку і увёўшы ў вышэй імя карыстальніка + пароль, памылка сервера быў вернуты. Гэта кажа аб тым, што палі, мы не запоўніць маюць жыццёва важнае значэнне, але ўсё ж не правільна.

Адзін з магчымых падыходаў тут спрабуе адгадаць іншых галінах, але гэта абяцае быць доўгім і працаёмкім працэсам: хоць мы можам здагадацца, іншыя "відавочна" палёў, гэта вельмі цяжка ўявіць сабе большы малюнку арганізацыі гэтага дадатку.

Мы скончылі спускаючыся па іншаму шляху.

Пішыце мне пароль

Мы потым зразумелі, што хоць мы не ў стане дадаць новую запіс у базу дадзеных членаў, мы можам змяніць існуючы, і гэта апынулася падыход, які атрымаў нас запіс.

З папярэдняга кроку, мы ведалі, што bob@example.com быў рахунак у сістэме, і мы выкарыстоўвалі SQL-ін'екцыі, каб абнавіць свае запісы базы дадзеных з наш адрас электроннай пошты:

SELECT email, passwd, login_id, full_name
 FROM members
 WHERE email = 'x';
   UPDATE members
   SET email = 'steve@unixwiz.net'
   WHERE email = 'bob@example.com';

Пасля выканання гэтага, мы, вядома, атрымаў "мы не ведалі, Ваш адрас электроннай пошты", але гэта было чакаць у сувязі з фіктыўны адрас электроннай пошты пры ўмове. Абнаўленне не будзе зарэгістраваны ў дадатку, таму яно выконваецца ціха.

Затым мы выкарыстоўвалі звычайныя "Я страціў свой пароль" спасылку - з абноўленым адрас электроннай пошты - і праз хвіліну атрымаў гэты ліст:

Зараз ён быў зараз усяго толькі пытанне наступны стандарт Увайсці працэсу для доступу да сістэмы, як высокапастаўлены супрацоўнік МДП, і гэта было значна вышэй, магчыма, карыстальнік з абмежаванымі правамі, што мы маглі б стварылі з нашым падыходам INSERT.

Мы выявілі, інтранэт-сайт, каб быць дастаткова усёабдымнай, і ён уключаны - сярод іншага - спіс усіх карыстальнікаў. Гэта справядлівае заклад, што многія сайты Інтранэт таксама мець рахункі ў карпаратыўнай сеткі Windows, і, магчыма, некаторыя з іх выкарыстоўвалі той жа пароль ў абодвух месцах. Паколькі ясна, што ў нас ёсць просты спосаб для атрымання любой пароль Інтранэт, і так як мы былі размешчаны адкрытыя PPTP VPN порт на карпаратыўны брандмауэр, яно павінна быць проста спроба такога доступу.

Мы зрабілі выбарачнай праверкі на некалькі рахункаў без поспеху, і мы не можам ведаць, што гэта "няправільны пароль" ці "імя Інтранэт рахунку адрозніваецца ад імя ўліковага запісу Windows". Але мы лічым, што аўтаматызаваныя сродкі маглі б зрабіць некаторыя гэтага лягчэй.

Іншыя падыходы

У дадзеным канкрэтным удзел, мы атрымалі досыць доступу, што мы не зразумелі, трэба зрабіць значна больш, але і іншыя крокі маглі б быць прынятыя. Мы пагаворым аб тым, што мы можам думаць цяпер, хоць мы цалкам упэўнены, што гэта не з'яўляецца вычарпальным.

Мы таксама разумеем, што не ўсе падыходы працаваць з усімі базамі дадзеных, і мы можам спыніцца на некаторых з іх.

Выкарыстоўвайце xp_cmdshell
Microsoft, SQL Server падтрымлівае захоўваемыя працэдуры xp_cmdshell, які дазваляе, што складае Выкананне адвольных каманд, і, калі гэта дазволена ў вэб-карыстальнікаў, поўны кампраміс вэб-сервер з'яўляецца непазбежным.
Тое, што мы зрабілі да гэтага часу быў абмежаваны вэб-прыкладанні і асноўнай базе дадзеных, але калі мы зможам выконваць каманды, вэб-сервер сам па сабе не можа не быць парушаная. Доступ да xp_cmdshell, як правіла, абмяжоўваецца адміністратарскі уліковых запісаў, але гэта можна даць яго ў меншай карыстальнікаў.
Карта Больш падрабязная структура базы дадзеных
Хоць дадзенае прыкладанне ўмове, што такія багатыя пасля Увайсці сераду, што ён сапраўды не ўяўляецца неабходным, каб капаць далей, у іншыя, больш абмежаванай асяроддзі гэта магчыма, не былі дастатковымі.
Будучы ў стане сістэматычна карту з наяўных схем, у тым ліку табліц і іх структуры поля, не можа не даць больш магчымасцяў для кампрамісу дадатку.
Можна было б, верагодна, сабраць больш намёкамі аб структуры ад іншых аспектаў вэб-сайта (напрыклад, ёсць "пакінуць каментар" старонку? Ці існуюць "Форум"?). Ясна, што гэта моцна залежыць ад прыкладання і абапіраецца на вельмі добрых рашэнняў здагадкі.

Змякчэнне

Мы лічым, што распрацоўнікі вэб-прыкладанняў, часта проста не думаюць пра "сюрпрыз ўваходу", але бяспеку людзей (у тым ліку дрэнных хлопцаў), так Ёсць тры асноўныя падыходы, якія могуць быць ужытыя тут.

Sanitize ўваход
Гэта абсалютна неабходна для санітарнай апрацоўкі ўводзяцца карыстальнікам каб гарантаваць, што яны не ўтрымліваюць небяспечныя коды, незалежна ад таго, каб сервер SQL або HTML сябе. Першая ідэя Адзін заключаецца ў палоску з "дрэннага", такія як двукоссі або кропку з коскай або ўцёкі, але гэта хібную спробу. Хоць гэта лёгка паказаць на некаторыя небяспечныя сімвалы, гэта цяжэй, якія паказваюць на ўсе з іх.
Мова вэб-досыць адмысловых знакаў і дзіўных разметкі (у тым ліку альтэрнатыўных спосабаў прадстаўлення той жа знакаў), і намаганні па аўтарытэтна выявіць усе "дрэнныя рэчы", наўрад ці будуць паспяховымі.
Замест гэтага, а не "выдаліць вядома дрэнныя дадзеныя", то лепш, каб "выдаліць усе, акрамя вядомых добрых дадзеных": гэта адрозненне мае вырашальнае значэнне. Так - у нашым прыкладзе - адрас электроннай пошты можа ўтрымліваць толькі гэтыя сімвалы:
abcdefghijklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ
0123456789
@.-_+
Існуе сапраўды няма выгады, які дазваляе сімвалы, якія не могуць быць сапраўднымі, і адмова ад іх рана - мабыць, з паведамленнем пра памылку - не толькі дапамагае прадухіліць SQL-ін'екцыі, але і ловіць проста памылкі друку рана, а не захоўвае іх у базе дадзеных.
Бакавая панэль на адрасы электроннай пошты

Важна адзначыць, што адрасы электроннай пошты, у прыватнасці, клапотна для праверкі праграмна, таму што ўсё, падобна, яго ўласнае ўяўленне аб тым, што прымушае "сапраўдны", і гэта ганьба, каб выключыць добры адрас электроннай пошты, паколькі яна ўтрымлівае сымбаль Вам не ' T думаць.

Адзіная рэальная ўлада RFC 2822 (які ўключае ў сябе больш знаёмым RFC822), і ўключае ў сябе дастаткова шырокага вызначэння таго, што дазволена. Сапраўды педантычны можа таксама пажадаць прыняць адрасы электроннай пошты з амперсанда і зорачкі (паміж іншым), як у сіле, але іншыя - у тым ліку гэтага аўтара - задаволеныя разумнае падмноства, што ўключае ў сябе "самы" адрасоў электроннай пошты.

Тыя, якія бяруць больш абмежавальны падыход павінен быць цалкам дасведчаныя аб наступствах выключэння гэтых адрасоў, асабліва ўлічваючы, што лепшыя метады (падрыхтоўка і выкананне, захоўваемых працэдур) ліквідаваць праблемы бяспекі якіх гэтыя "няцотны" знакаў цяперашні час.


Памятайце, што "ачыстка уваходнага" азначае не проста "выдаліць двукоссі, таму што нават" звычайныя "знакі могуць быць клапотна. У прыкладзе, дзе цэлы лік ID параўноўваецца супраць уводу карыстальніка (напрыклад, лічбавы ПІН-код):
SELECT fieldlist
 FROM table
 WHERE id = 23 OR 1=1; -- Boom! Always matches!
На практыцы, аднак, такі падыход з'яўляецца вельмі абмежаваным, паколькі Ёсць так некалькі палёў, для якіх гэта магчыма, каб выключыць прамое шматлікія небяспечныя сімвалы. Для "даты" або "адрасы электроннай пошты" ці "цэлых" гэта, магчыма, заслуга, але і для любых рэальных прыкладаннях, чалавек проста не можа пазбегнуць іншых змякчэнне.
Уцёкі / Quotesafe ўваход
Нават калі можна было б мець магчымасць дэзінфікаваць нумар тэлефона або адрас электроннай пошты, ніхто не можа прыняць гэты падыход з "імем" поле каб хочацца, каб выключыць падобныя Біл О'Рейли са свайго дадатку: цытата проста дапушчальным для гэтай галіне.
Адзін ўключае фактычнае адзінарнай двукоссі ў радок SQL, паклаўшы два з іх разам, так што гэта кажа аб тым відавочныя - але не так! - Методыка папярэдняй апрацоўкі кожнай радка для рэплікацыі адзіночныя двукоссі:
SELECT fieldlist
 FROM customers
 WHERE name = 'Bill O''Reilly'; -- works OK
Аднак, гэта наіўны падыход можа быць збіты, таму што большасць СКБД падтрымліваюць іншыя механізмы выхаду радка. MySQL, напрыклад, таксама дазваляе \ ", каб пазбегнуць цытаты, так што пасля ўводу \"; DROP TABLE карыстальнікаў; - "абараняюць", падвоіўшы двукоссі, мы атрымаем:
SELECT fieldlist
 FROM customers
 WHERE name = '\''; DROP TABLE users; --'; -- Boom!
Выраз '\''з'яўляецца поўнай радкі (якія змяшчаюць толькі адно двукоссі), і звычайна махінацыямі SQL прытрымлівацца. Ён не спыняецца на слэш альбо: ёсць Unicode, іншыя кадыроўкі, і разбор дзівацтвы усё хаваецца ў пустазелля на паездку да канструктар прыкладанняў.
Пачатак цытаты права, як вядома, цяжка, таму шматлікія мовы інтэрфейсу базы дадзеных забяспечвае функцыю, якая зробіць гэта за вас. Калі ж ўнутраны код выкарыстоўваецца для "радок са спасылкай на" і "апрацоўка радкоў", гэта значна больш верагодна, што працэс будзе зроблена правільна і бяспечна.
Некаторыя прыклады функцыі mysql_real_escape_string MySQL () і Perl DBD метад $ DBH-> цытаты ($ неадназначнасьць).
Гэтыя метады павінны быць выкарыстаны.
Выкарыстоўвайце звязаныя параметры (заява падрыхтаваць)
Хоць quotesafing з'яўляецца добрым механізмам, мы ўсё яшчэ ў вобласці "з улікам уведзеных карыстальнікам дадзеных, як SQL", і значна лепш падыход існуе: звязаныя параметры, якія падтрымліваюцца практычна ўсе інтэрфейсы праграмавання баз дадзеных. У гэтай тэхніцы, радок SQL заяву ствараецца з запаўняльнікамі - знак пытання для кожнага параметра - і гэта скампіляваны ("падрыхтаваныя", на мове SQL) у вочнай форме.
Пазней, гэта падрыхтавала запыт "выкананы" са спісам параметраў:
Прыклад у Perl
$sth = $dbh->prepare("SELECT email, userid FROM members WHERE email = ?;");

$sth->execute($email);
Дзякуючы Штэфан Вагнер, гэта паказвае, звязаныя параметры ў Java:
Небяспечную версію
Statement s = connection.createStatement();
ResultSet rs = s.executeQuery("SELECT email FROM member WHERE name = "
               + formField); // *boom*
Бяспечная версія
PreparedStatement ps = connection.prepareStatement(
  "SELECT email FROM member WHERE name = ?");
ps.setString(1, formField);
ResultSet rs = ps.executeQuery();
Тут $ электроннай пошце дадзеныя, атрыманыя ад карыстальніка форме, і ён перадаецца як пазіцыйны параметр # 1 (першы знак пытання), і ні ў адной кропцы зрабіць змесціва гэтай зменнай мае нічога агульнага з разбору заяву SQL. Каціроўкі, кропка з коскай, слэш, SQL каментар абазначэння - усё гэта не мае ніякага ўплыву, таму што гэта "толькі дадзеныя". Там проста нічога не падарваць, так што прыкладанне будзе ў значнай ступені абаронена ад нападаў SQL ін'екцыі.
Там жа могуць быць некаторыя перавагі прадукцыйнасці, калі гэта падрыхтавала запыт паўторна некалькі разоў (ён толькі павінен быць прааналізаваны адзін раз), але гэта дробязі ў параўнанні з вялізнымі перавагамі бяспекі. Гэта, верагодна, адзіны найбольш важны крок можна зрабіць для абароны вэб-прыкладанняў.
Гранічныя дазволу базы дадзеных і падзел карыстальнікаў
У нашым выпадку, мы назіралі толькі два ўзаемадзеяння, якія зробленыя не ў кантэксце які ўвайшоў у сістэму карыстальніка: "ўвайдзіце" і "Выслаць мне пароль". Вэб-прыкладання павінны выкарыстоўваць падключэнне да базы дадзеных з самымі абмежаванымі правамі магчымыя толькі запыты доступу да табліцы членаў, і няма доступу да любой іншай табліцы.
Эфект тут з'яўляецца тое, што нават "паспяховага" SQL-ін'екцыя напад будзе мець значна больш абмежаваны поспех. Тут, мы б не змаглі зрабіць запыт абнаўлення, што ў канчатковым рахунку, даў нам доступ, таму мы былі вымушаныя звяртацца да іншых каналах.
Як толькі вэб-дадатак ўстаноўлена, што мноства сапраўдных паўнамоцтвы былі перададзеныя праз Увайсці форме, было б тое, што пераключальнік сесіі злучэння з базай дадзеных з больш шырокімі правамі.
Гэта павінна пайсці амаль сабой зразумела, што С. А. правоў ніколі не павінны выкарыстоўвацца для любога вэб-прыкладанні.
Выкарыстаньне захоўваемых працэдур для доступу да базы дадзеных
Калі сервер базы дадзеных падтрымлівае іх, выкарыстоўваць захоўваемыя працэдуры для выканання доступу ад імя прыкладання, якія могуць ліквідаваць SQL цалкам (пры ўмове, захоўваемыя працэдуры самі пішуцца правільна).
Па інкапсуляцыі правілы для пэўных дзеянняў - запыт, абнаўленне, выдаленне і г.д. - у адзіную працэдуру, ён можа быць правераны і дакументальна на аснове аўтаномных і бізнес-правілаў гвалтоўных (напрыклад, "дадаць новы парадак" працэдура можа адхіліць што парадку, калі кліент быў за яго крэдытны ліміт).
Для простых запытаў гэта можа быць толькі нязначнае перавага, але, як аперацыі становяцца ўсё больш складанымі (або выкарыстоўваюцца ў больш чым у адным месцы), якія маюць адзінае вызначэнне для аперацыі азначае, што ён будзе больш надзейнай і просты ў абслугоўванні.
Звярніце ўвагу: гэта заўсёды можна напісаць захоўваемую працэдуру, якая сама будуе запыт дынамічна: гэта не дае ніякай абароны ад SQL-ін'екцыя - гэта адзіна правільны звязвання з падрыхтоўкі / выканання або прамыя заявы SQL са звязанымі зменнымі, якія забяспечваюць гэтую абарону.
Ізаляваць вэб-сервер
Нават нягледзячы на ??прыняцце ўсіх гэтых крокаў змякчэння, гэта ўсё-такі яшчэ можна нешта страціць і пакінуць на серверы адкрыты для кампрамісу. Трэба б дызайн сеткавай інфраструктуры выказаць здагадку, што дрэнны хлопец будзе мець поўны доступ адміністратара да машыны, а затым спрабуюць абмежаваць, якія могуць быць выкарыстаны для кампрамісу іншых рэчаў.
Напрыклад, паклаўшы машыну ў DMZ з вельмі абмежаваным праколы "ўнутры" сеткі азначае, што нават атрыманне поўнага кантролю над вэб-сервер аўтаматычна не прадаставіць поўны доступ да ўсяго астатняму. Гэта не спыніць ўсё, вядома, але гэта робіць яго нашмат складаней.
Настройка справаздач аб памылках
Справаздач аб памылках па змаўчанні для некаторых платформаў ўключае ў сябе распрацоўшчыкаў адладкавай інфармацыі, і гэта не можа быць паказана для знешніх карыстальнікаў. Уявіце, наколькі лягчэй час ён робіць для зламысніка, калі поўны запыт паказана, паказваючы на ??сінтаксічныя памылкі ўдзел.
Гэтая інфармацыя карысная для распрацоўнікаў, але гэта павінна быць абмежавана - калі гэта магчыма - толькі унутраным карыстальнікам.

Звярніце ўвагу, што не ўсе базы дадзеных настроены такім жа чынам, і не ўсе нават падтрымку жа дыялекце SQL ("S" азначае "структураванай", не "Стандарт"). Напрыклад, большасць версій MySQL не падтрымлівае подзапросов, і яны не дазваляюць звычайна некалькі аператараў: яны значна ўскладняюць фактараў пры спробе пранікнуць у сетку.


Мы хацелі б падкрэсліць, што хоць мы абралі "Забыліся пароль", каб атака ў дадзеным выпадку, гэта было не зусім, таму што гэта асаблівасць вэб-прыкладанняў з'яўляецца небяспечным. Ён быў проста адным з некалькіх даступных функцый, якія маглі быць уразлівым, і было б памылкай канцэнтравацца на "Забыліся пароль" аспект прэзентацыі.

Гэта Тэхналогія Савет не быў прызначаны для забеспячэння поўнага ахопу на ін'екцыі SQL, ці нават падручнік: яна проста дакументы працэсу, развіваліся на працягу некалькіх гадзін у час удзелу кантракце. Мы бачылі іншых работ па ін'екцыі SQL абмеркаваць тэхнічную падрыхтоўку, але ўсё ж толькі забяспечыць "грошы стрэл", што ў канчатковым рахунку атрымала ім доступ.

Але, што канчатковы справаздачу неабходных базавых ведаў, каб зняць, і працэс збору інфармацыі, што мае свае плюсы таксама. Не заўсёды ёсць доступ да зыходнага коду дадатку, і магчымасць для нападу карыстальніцкае дадатак слепа мае некаторы значэнне.

Дзякуючы Дэвід Личфилд і Рэндал Шварц за тэхнічны ўклад у гэтай паперы, і на вялікі Крыс Mospaw для графічнага дызайну (© 2005 Крыс Mospaw, з дазволу аўтара).

Іншыя рэсурсы

Зменены: пар 10 Кастрычнік 6:28:06 PDT 2007

Popular Links
Published (Last edited): May 15 , source: http://unixwiz.net/techtips/sql-injection.html