SQL ін'єкція — один з поширених способів злому сайтів та програм, що працюють з базами даних, заснований на впровадженні в запит довільного SQL-коду.
Впровадження SQL, залежно від типу СКБД та умов впровадження, може дати можливість тій людині, що атакує, виконати довільний запит до бази даних (наприклад, прочитати вміст будь-яких таблиць, видалити, змінити або додати дані), отримати можливість читання та/або запису локальних файлів та виконання довільних команд на сервері.
Атака типу впровадження SQL може бути можлива за некоректної обробки вхідних даних, що використовуються в SQL-запитах.
Розробник застосунків, що працюють з базами даних, повинен знати про таку уразливість і вживати заходів протидії впровадженню SQL.
Принцип атаки
Припустимо, серверне ПЗ, отримавши вхідний параметр id, використовує його для створення SQL-запиту. Розглянемо такий PHP-скрипт:
... $id = $_REQUEST['id']; $res = mysql_query("SELECT * FROM news WHERE id_news = $id"); ...
Якщо на сервер переданий параметр id, що дорівнює 5 (наприклад так: http://example.org/script.php?id=5[недоступне посилання з лютого 2019]), то виконається такий SQL-запит:
SELECT * FROM news WHERE id_news = 5
Але якщо зловмисник передасть як параметр id рядок -1 OR 1=1 (наприклад, так: http://example.org/script.php?id=-1+OR+1=1[недоступне посилання з лютого 2019]), то виконається запит:
SELECT * FROM news WHERE id_news =-1 OR 1=1
Таким чином, зміна вхідних параметрів шляхом додавання в них конструкцій мови SQL викликає зміну в логіці виконання SQL-запиту (в цьому прикладі замість новини із заданим ідентифікатором будуть вибрані всі наявні в базі новини, оскільки вираз 1=1 завжди істинний).
Впровадження в рядкові параметри
Припустимо, серверне ПЗ, отримавши запит на пошук даних у новинах, бере параметр search_text і використовує його в наступному SQL-запиті (тут параметри екрануються лапками) :
... $search_text = $_REQUEST['search_text']; $res = mysql_query("SELECT id_news, news_date, news_caption, news_text, news_id_author FROM news WHERE news_caption LIKE('%$search_text%') ");
Зробивши запит виду http://example.org/script.php?search_text=Test[недоступне посилання з лютого 2019] ми отримаємо виконання такого SQL-запиту:
SELECT id_news, news_date, news_caption, news_text, news_id_author FROM news WHERE news_caption LIKE('%Test%')
Але, запровадивши в параметр search_text символ лапки (який використовується в запиті), ми можемо кардинально змінити поведінку SQL-запиту. Наприклад, передавши як параметр search_text значення ') +and+ (news_id_author='1, ми змусимо виконати запит:
SELECT id_news, news_date, news_caption, news_text, news_id_author FROM news WHERE news_caption LIKE('%') and (news_id_author='1%')
Використання UNION
Мова SQL дозволяє об'єднувати результати декількох запитів за допомогою оператора UNION [ 9 лютого 2010 у Wayback Machine.]. Це надає зловмисникові можливість отримати несанкціонований доступ до даних.
Розглянемо скрипт відображення новини (ідентифікатор новини, яку необхідно відобразити, передається в параметрі id) :
$res = mysql_query("SELECT id_news, header, body, author FROM news WHERE id_news = ". $_REQUEST['id']);
Якщо зловмисник передасть як параметр id конструкцію -1 UNION SELECT 1,username, password,1 FROM admin, це викличе виконання SQL-запиту
SELECT id_news, header, body, author FROM news WHERE id_news =-1 UNION SELECT 1,username,password,1 FROM admin
Оскільки новини з ідентифікатором -1 завідомо не існує, з таблиці news не буде вибрано жодного запису, проте в результат потраплять записи, несанкціоновано відібрані з таблиці admin внаслідок ін'єкції SQL.
Використання UNION + group_concat()
У деяких випадках хакер може провести атаку, але не може бачити більше однієї колонки. У разі MySQL зломщик може скористатися функцією:
group_concat(col, symbol, col)
яка об'єднує кілька колонок в одну. Наприклад, для прикладу цього вище виклик функції буде таким:
-1 UNION SELECT group_concat(username, 0x3a, password) FROM admin
Екранування хвоста запиту
Скрипт
$res = mysql_query("SELECT author FROM news WHERE id=". $_REQUEST['id']." AND author LIKE ('a%') ");
відображає ім'я автора новини згідно ідентифікатора id лише за умови, що ім'я починається з літери а, і впровадження коду з використанням оператора UNION складне.
У таких випадках, зловмисниками використовується метод екранування частини запиту за допомогою символів коментаря (/*або--в залежності від типу СКБД).
У цьому прикладі, зловмисник може передати в скрипт параметр id зі значенням-1 UNION SELECT password FROM admin/*, виконавши таким чином запит
SELECT author FROM news WHERE id=-1 UNION SELECT password FROM admin/* AND author LIKE ('a%')
в якому частина запиту ( AND author LIKE ('a%') ) позначена як коментар і не впливає на виконання.
Розщеплення SQL-запиту
Для розділення команд в мові SQL використовується символ ; (крапка з комою), впроваджуючи цей символ до запиту, зловмисник отримує можливість виконати декілька команд в одному запиті, однак не всі діалекти SQL підтримують таку можливість.
Наприклад, якщо в параметри скрипту
$id = $_REQUEST['id']; $res = mysql_query("SELECT * FROM news WHERE id_news = $id");
зловмисником передається конструкція, що містить крапку з комою, наприклад 12;INSERT INTO admin (username, password) VALUES ('HaCkEr', 'foo'); то в одному запиті будуть виконані 2 команди
SELECT * FROM news WHERE id_news = 12; INSERT INTO admin (username, password) VALUES ('HaCkEr', 'foo');
і в таблицю admin буде несанкціоновано доданий запис HaCkEr.
Методика атак типу впровадження SQL-коду
Пошук скриптів, уразливих для атаки
На цьому етапі зловмисник вивчає поведінку скриптів сервера при маніпуляції вхідними параметрами з метою виявлення їх аномальної поведінки. Маніпуляція відбувається всіма можливими параметрами:
- Даними, переданими через методи POST і GET
- Значеннями [HTTP-Cookie]
- HTTP_REFERER (для скриптів)
- AUTH_USER та AUTH_PASSWORD (при використанні аутентифікації)
Як правило, маніпуляція зводиться до підстановки в параметри символу одинарної (рідше подвійний або зворотної) лапки.
Аномальною поведінкою вважається будь-яка поведінка, при якому сторінки, одержувані до і після підстановки лапок, розрізняються (і при цьому немає повідомлення неправильний форматі параметрів).
Найчастіші приклади аномальної поведінки:
- виводиться повідомлення про різні помилки;
- при запиті даних (наприклад, новини або списку продукції) запитувані дані не виводяться взагалі, хоча сторінка відображається
і т. д.
Слід враховувати, що відомі випадки, коли повідомлення про помилки, в силу специфіки розмітки сторінки, не видно в браузері, хоча і присутні в її HTML-коді.
Захист від атак типу впровадження SQL-коду
Для захисту від цього типу атак необхідно ретельно фільтрувати вхідні параметри, значення яких будуть використані для побудови SQL-запиту.
Фільтрація рядкових параметрів
Припустимо, що код, який генерує запит (на мові програмування Паскаль), виглядає так:
statement:= 'SELECT * FROM users WHERE name = "' + userName + '";';
Щоб впровадження коду було неможливо, для деяких СКБД, в тому числі, для MySQL, потрібно брати в лапки всі рядкові параметри. У самому параметрі замінюють лапки на \", апостроф на \', зворотну косу риску на \\ (це називається ). Це можна робити таким кодом:
statement:= 'SELECT * FROM users WHERE name = ' + QuoteParam(userName) + ';';
function QuoteParam(s: string) : string; { на вході — рядок; на виході — рядок в лапках та із заміненими спецсимволами } var i: integer; Dest: string; begin Dest:= '"'; for i:=1 to length(s) do case s[i] of '''': Dest:= Dest +'\'''; '"': Dest:= Dest + '\"'; '\': Dest:= Dest + '\\'; else Dest:= Dest + s[i]; end; QuoteParam:= Dest + '"'; end;
для PHP фільтрація може бути такою:
<?php $query = "SELECT * FROM users WHERE user='".mysql_real_escape_string($user)."';"; ?>
Фільтрація цілочисельних параметрів
Візьмемо інший запит:
statement:= 'SELECT * FROM users WHERE id = ' + id + ';';
У цьому випадку поле id
має числовий тип, і його найчастіше не беруть в лапки. У такому випадку допомагає перевірка - якщо зміннаid
не є числом, запит взагалі не повинен виконуватися.
Наприклад, на Delphi для протидії таким ін'єкціям допомагає код:
id_int:= StrToInt(id); statement:= 'SELECT * FROM users WHERE id = ' + IntToStr(id_int) + ';';
у випадку помилки функція StrToInt
викличе виняток EConvertError
, і в його обробнику можна буде вивести повідомлення про помилку. Подвійне перетворення забезпечує коректну реакцію на числа у форматі $132AB
(шістнадцяткова система числення). На стандартному Паскалі, який не вміє обробляти виняток, код дещо складніший.
Для PHP цей метод буде виглядати так:
$query = 'SELECT * FROM users WHERE id = '. intval($id);
Усікання вхідних параметрів
Для внесення змін в логіку виконання SQL-запиту потрібно впровадження достатньо довгих рядків. Так, мінімальна довжина такого рядка у наведених вище прикладах становить 8 символів («1 OR 1=1»). Якщо максимальна довжина коректного значення параметра невелика, то одним з методів захисту може бути максимальне усікання значень вхідних параметрів.
Наприклад, якщо відомо, що полеid
у вищенаведених прикладах може приймати значення не більше 9999, можна «відрізати зайві» символи, залишивши не більше чотирьох:
statement:= 'SELECT * FROM users WHERE id = ' + LeftStr(id, 4) + ';';
Використання параметризованих запитів
Багато серверів баз даних підтримують можливість відправки параметризованих запитів (підготовлені вирази). При цьому параметри зовнішнього походження відправляються на сервер окремо від самого запиту або автоматично екрануються клієнтською бібліотекою. Для цього використовують
- на Delphi — властивість
TQuery.Params
;
Наприклад
var sql, param: string; begin sql:= 'select:text as value from dual'; param:= 'alpha'; Query1.Sql.Text:= sql; Query1.ParamByName('text').AsString:= param; Query1.Open; ShowMessage(Query1['value']); end;
Див. також
- Міжсайтовий скриптінг
- PHP-ін'єкція
- Підказкова ін'єкція, подібне поняття в застосуванні до штучного інтелекту
Посилання
- OWASP Security Cheat Sheets, by OWASP
- Blind Sql injection with Regular Expression[недоступне посилання з лютого 2019]
- WASC Threat Classification — SQL Injection Entry [ 25 вересня 2010 у Wayback Machine.], by the Web Application Security Consortium.
- , by Stuart Thomas.
- SQL Injection Attacks by Example [ 7 листопада 2015 у Wayback Machine.], by Steve Friedl
- SQL Injection Prevention Cheat Sheet [ 16 листопада 2015 у Wayback Machine.], by OWASP.
- SQL Injection Tutorial [ 11 грудня 2014 у Wayback Machine.], by BTS.
- sqlmap: automatic SQL injection and database takeover tool [ 28 травня 2019 у Wayback Machine.]
- SDL Quick security references on SQL injection by Bala Neerumalla.
- By Yuli Stremovsky
- SQL ін'єкція в MySQL сервері [ 30 липня 2013 у Wayback Machine.]
- «SQL Injection від А до Я» [ 11 січня 2012 у Wayback Machine.]
- MySQL3 Error Based SQL injection [ 31 липня 2013 у Wayback Machine.]
- SQL-Injection в PostgreSQL [ 31 липня 2013 у Wayback Machine.]
- Захист від SQL injection та XSS (функція secureInnerData) [ 25 вересня 2013 у Wayback Machine.]
Це незавершена стаття про програмне забезпечення. Ви можете проєкту, виправивши або дописавши її. |
Вікіпедія, Українська, Україна, книга, книги, бібліотека, стаття, читати, завантажити, безкоштовно, безкоштовно завантажити, mp3, відео, mp4, 3gp, jpg, jpeg, gif, png, малюнок, музика, пісня, фільм, книга, гра, ігри, мобільний, телефон, android, ios, apple, мобільний телефон, samsung, iphone, xiomi, xiaomi, redmi, honor, oppo, nokia, sonya, mi, ПК, web, Інтернет
SQL in yekciya odin z poshirenih sposobiv zlomu sajtiv ta program sho pracyuyut z bazami danih zasnovanij na vprovadzhenni v zapit dovilnogo SQL kodu Vprovadzhennya SQL zalezhno vid tipu SKBD ta umov vprovadzhennya mozhe dati mozhlivist tij lyudini sho atakuye vikonati dovilnij zapit do bazi danih napriklad prochitati vmist bud yakih tablic vidaliti zminiti abo dodati dani otrimati mozhlivist chitannya ta abo zapisu lokalnih fajliv ta vikonannya dovilnih komand na serveri Ataka tipu vprovadzhennya SQL mozhe buti mozhliva za nekorektnoyi obrobki vhidnih danih sho vikoristovuyutsya v SQL zapitah Rozrobnik zastosunkiv sho pracyuyut z bazami danih povinen znati pro taku urazlivist i vzhivati zahodiv protidiyi vprovadzhennyu SQL Princip atakiPripustimo serverne PZ otrimavshi vhidnij parametr id vikoristovuye jogo dlya stvorennya SQL zapitu Rozglyanemo takij PHP skript id REQUEST id res mysql query SELECT FROM news WHERE id news id Yaksho na server peredanij parametr id sho dorivnyuye 5 napriklad tak http example org script php id 5 nedostupne posilannya z lyutogo 2019 to vikonayetsya takij SQL zapit SELECT FROM news WHERE id news 5 Ale yaksho zlovmisnik peredast yak parametr id ryadok 1 OR 1 1 napriklad tak http example org script php id 1 OR 1 1 nedostupne posilannya z lyutogo 2019 to vikonayetsya zapit SELECT FROM news WHERE id news 1 OR 1 1 Takim chinom zmina vhidnih parametriv shlyahom dodavannya v nih konstrukcij movi SQL viklikaye zminu v logici vikonannya SQL zapitu v comu prikladi zamist novini iz zadanim identifikatorom budut vibrani vsi nayavni v bazi novini oskilki viraz 1 1 zavzhdi istinnij Vprovadzhennya v ryadkovi parametri Pripustimo serverne PZ otrimavshi zapit na poshuk danih u novinah bere parametr search text i vikoristovuye jogo v nastupnomu SQL zapiti tut parametri ekranuyutsya lapkami search text REQUEST search text res mysql query SELECT id news news date news caption news text news id author FROM news WHERE news caption LIKE search text Zrobivshi zapit vidu http example org script php search text Test nedostupne posilannya z lyutogo 2019 mi otrimayemo vikonannya takogo SQL zapitu SELECT id news news date news caption news text news id author FROM news WHERE news caption LIKE Test Ale zaprovadivshi v parametr search text simvol lapki yakij vikoristovuyetsya v zapiti mi mozhemo kardinalno zminiti povedinku SQL zapitu Napriklad peredavshi yak parametr search text znachennya and news id author 1 mi zmusimo vikonati zapit SELECT id news news date news caption news text news id author FROM news WHERE news caption LIKE and news id author 1 Vikoristannya UNION Mova SQL dozvolyaye ob yednuvati rezultati dekilkoh zapitiv za dopomogoyu operatora UNION 9 lyutogo 2010 u Wayback Machine Ce nadaye zlovmisnikovi mozhlivist otrimati nesankcionovanij dostup do danih Rozglyanemo skript vidobrazhennya novini identifikator novini yaku neobhidno vidobraziti peredayetsya v parametri id res mysql query SELECT id news header body author FROM news WHERE id news REQUEST id Yaksho zlovmisnik peredast yak parametr id konstrukciyu 1 UNION SELECT 1 username password 1 FROM admin ce vikliche vikonannya SQL zapitu SELECT id news header body author FROM news WHERE id news 1 UNION SELECT 1 username password 1 FROM admin Oskilki novini z identifikatorom 1 zavidomo ne isnuye z tablici news ne bude vibrano zhodnogo zapisu prote v rezultat potraplyat zapisi nesankcionovano vidibrani z tablici admin vnaslidok in yekciyi SQL Vikoristannya UNION group concat U deyakih vipadkah haker mozhe provesti ataku ale ne mozhe bachiti bilshe odniyeyi kolonki U razi MySQL zlomshik mozhe skoristatisya funkciyeyu group concat col symbol col yaka ob yednuye kilka kolonok v odnu Napriklad dlya prikladu cogo vishe viklik funkciyi bude takim 1 UNION SELECT group concat username 0 x3a password FROM admin Ekranuvannya hvosta zapitu Skript res mysql query SELECT author FROM news WHERE id REQUEST id AND author LIKE a vidobrazhaye im ya avtora novini zgidno identifikatora id lishe za umovi sho im ya pochinayetsya z literi a i vprovadzhennya kodu z vikoristannyam operatora UNION skladne U takih vipadkah zlovmisnikami vikoristovuyetsya metod ekranuvannya chastini zapitu za dopomogoyu simvoliv komentarya abo v zalezhnosti vid tipu SKBD U comu prikladi zlovmisnik mozhe peredati v skript parametr id zi znachennyam 1 UNION SELECT password FROM admin vikonavshi takim chinom zapit SELECT author FROM news WHERE id 1 UNION SELECT password FROM admin AND author LIKE a v yakomu chastina zapitu AND author LIKE a poznachena yak komentar i ne vplivaye na vikonannya Rozsheplennya SQL zapitu Dlya rozdilennya komand v movi SQL vikoristovuyetsya simvol krapka z komoyu vprovadzhuyuchi cej simvol do zapitu zlovmisnik otrimuye mozhlivist vikonati dekilka komand v odnomu zapiti odnak ne vsi dialekti SQL pidtrimuyut taku mozhlivist Napriklad yaksho v parametri skriptu id REQUEST id res mysql query SELECT FROM news WHERE id news id zlovmisnikom peredayetsya konstrukciya sho mistit krapku z komoyu napriklad 12 INSERT INTO admin username password VALUES HaCkEr foo to v odnomu zapiti budut vikonani 2 komandi SELECT FROM news WHERE id news 12 INSERT INTO admin username password VALUES HaCkEr foo i v tablicyu admin bude nesankcionovano dodanij zapis HaCkEr Metodika atak tipu vprovadzhennya SQL koduPoshuk skriptiv urazlivih dlya ataki Na comu etapi zlovmisnik vivchaye povedinku skriptiv servera pri manipulyaciyi vhidnimi parametrami z metoyu viyavlennya yih anomalnoyi povedinki Manipulyaciya vidbuvayetsya vsima mozhlivimi parametrami Danimi peredanimi cherez metodi POST i GET Znachennyami HTTP Cookie HTTP REFERER dlya skriptiv AUTH USER ta AUTH PASSWORD pri vikoristanni autentifikaciyi Yak pravilo manipulyaciya zvoditsya do pidstanovki v parametri simvolu odinarnoyi ridshe podvijnij abo zvorotnoyi lapki Anomalnoyu povedinkoyu vvazhayetsya bud yaka povedinka pri yakomu storinki oderzhuvani do i pislya pidstanovki lapok rozriznyayutsya i pri comu nemaye povidomlennya nepravilnij formati parametriv Najchastishi prikladi anomalnoyi povedinki vivoditsya povidomlennya pro rizni pomilki pri zapiti danih napriklad novini abo spisku produkciyi zapituvani dani ne vivodyatsya vzagali hocha storinka vidobrazhayetsya i t d Slid vrahovuvati sho vidomi vipadki koli povidomlennya pro pomilki v silu specifiki rozmitki storinki ne vidno v brauzeri hocha i prisutni v yiyi HTML kodi Zahist vid atak tipu vprovadzhennya SQL koduDlya zahistu vid cogo tipu atak neobhidno retelno filtruvati vhidni parametri znachennya yakih budut vikoristani dlya pobudovi SQL zapitu Filtraciya ryadkovih parametriv Pripustimo sho kod yakij generuye zapit na movi programuvannya Paskal viglyadaye tak statement SELECT FROM users WHERE name userName Shob vprovadzhennya kodu bulo nemozhlivo dlya deyakih SKBD v tomu chisli dlya MySQL potribno brati v lapki vsi ryadkovi parametri U samomu parametri zaminyuyut lapki na apostrof na zvorotnu kosu risku na ce nazivayetsya Ce mozhna robiti takim kodom statement SELECT FROM users WHERE name QuoteParam userName function QuoteParam s string string na vhodi ryadok na vihodi ryadok v lapkah ta iz zaminenimi specsimvolami var i integer Dest string begin Dest for i 1 to length s do case s i of Dest Dest Dest Dest Dest Dest else Dest Dest s i end QuoteParam Dest end dlya PHP filtraciya mozhe buti takoyu lt php query SELECT FROM users WHERE user mysql real escape string user gt Filtraciya cilochiselnih parametriv Vizmemo inshij zapit statement SELECT FROM users WHERE id id U comu vipadku pole id maye chislovij tip i jogo najchastishe ne berut v lapki U takomu vipadku dopomagaye perevirka yaksho zminnaid ne ye chislom zapit vzagali ne povinen vikonuvatisya Napriklad na Delphi dlya protidiyi takim in yekciyam dopomagaye kod id int StrToInt id statement SELECT FROM users WHERE id IntToStr id int u vipadku pomilki funkciya StrToInt vikliche vinyatok EConvertError i v jogo obrobniku mozhna bude vivesti povidomlennya pro pomilku Podvijne peretvorennya zabezpechuye korektnu reakciyu na chisla u formati 132AB shistnadcyatkova sistema chislennya Na standartnomu Paskali yakij ne vmiye obroblyati vinyatok kod desho skladnishij Dlya PHP cej metod bude viglyadati tak query SELECT FROM users WHERE id intval id Usikannya vhidnih parametriv Dlya vnesennya zmin v logiku vikonannya SQL zapitu potribno vprovadzhennya dostatno dovgih ryadkiv Tak minimalna dovzhina takogo ryadka u navedenih vishe prikladah stanovit 8 simvoliv 1 OR 1 1 Yaksho maksimalna dovzhina korektnogo znachennya parametra nevelika to odnim z metodiv zahistu mozhe buti maksimalne usikannya znachen vhidnih parametriv Napriklad yaksho vidomo sho poleid u vishenavedenih prikladah mozhe prijmati znachennya ne bilshe 9999 mozhna vidrizati zajvi simvoli zalishivshi ne bilshe chotiroh statement SELECT FROM users WHERE id LeftStr id 4 Vikoristannya parametrizovanih zapitiv Bagato serveriv baz danih pidtrimuyut mozhlivist vidpravki parametrizovanih zapitiv pidgotovleni virazi Pri comu parametri zovnishnogo pohodzhennya vidpravlyayutsya na server okremo vid samogo zapitu abo avtomatichno ekranuyutsya kliyentskoyu bibliotekoyu Dlya cogo vikoristovuyut na Delphi vlastivist TQuery Params Naprikladvar sql param string begin sql select text as value from dual param alpha Query1 Sql Text sql Query1 ParamByName text AsString param Query1 Open ShowMessage Query1 value end na Perl cherez DBI quoteaboDBI prepare na Java cherez klasPreparedStatement na C vlastivist SqlCommand Parameters na PHP MySQLi pri roboti z MySQL b PDO b Div takozhMizhsajtovij skripting PHP in yekciya Pidkazkova in yekciya podibne ponyattya v zastosuvanni do shtuchnogo intelektuPosilannyaOWASP Security Cheat Sheets by OWASP Blind Sql injection with Regular Expression nedostupne posilannya z lyutogo 2019 WASC Threat Classification SQL Injection Entry 25 veresnya 2010 u Wayback Machine by the Web Application Security Consortium by Stuart Thomas SQL Injection Attacks by Example 7 listopada 2015 u Wayback Machine by Steve Friedl SQL Injection Prevention Cheat Sheet 16 listopada 2015 u Wayback Machine by OWASP SQL Injection Tutorial 11 grudnya 2014 u Wayback Machine by BTS sqlmap automatic SQL injection and database takeover tool 28 travnya 2019 u Wayback Machine SDL Quick security references on SQL injection by Bala Neerumalla By Yuli Stremovsky SQL in yekciya v MySQL serveri 30 lipnya 2013 u Wayback Machine SQL Injection vid A do Ya 11 sichnya 2012 u Wayback Machine MySQL3 Error Based SQL injection 31 lipnya 2013 u Wayback Machine SQL Injection v PostgreSQL 31 lipnya 2013 u Wayback Machine Zahist vid SQL injection ta XSS funkciya secureInnerData 25 veresnya 2013 u Wayback Machine Ce nezavershena stattya pro programne zabezpechennya Vi mozhete dopomogti proyektu vipravivshi abo dopisavshi yiyi