SQLChop: движок по обнаружению SQL-инъекций

SQLChop — это новый механизм обнаружения SQL инжектов, построенный на выявлении определённых маркеров SQL и анализе синтаксиса. Принимаемые данные (URLадрес, body, cookie и т. д.) вначале будут декодированы и приведены к виду, наиболее близкому к виду, соответствующему выполняемой в веб-приложении функции, затем будет произведён анализ для классификации результата. SQLChop основывается на знании компилятора и теории автоматов и работает на временной сложности O(N).

Исходный код доступен здесь: https://github.com/chaitin/sqlchop

Документация:

Есть возможность проверить свои запросы онлайн, поиграться с SQLChop. По этой ссылке введите интересующие вас SQL запросы и посмотрите, будут ли они классифицированы как попытка SQL-инъекции.

01

Зависимости SQLChop

Альфа релиз SQLChop, предназначенный для тестирования, включает C++ заголовок и разделяемые объекты, библиотеку python, а также несколько примеров использования. Этот выпуск был протестирован на большинстве дистрибутивов Linux.

Если будете использовать с Python'ом, то нужно установить protobuf-python, например, так:

$ sudo pip install protobuf

Если вы используете C++, то вам нужно установить protobuf, protobuf-compiler и protobuf-devel, например так:

$ sudo yum install protobuf protobuf-compiler protobuf-devel

Собираем SQLChop

Загрузите последний выпуск с https://github.com/chaitin/sqlchop/releases

Make

Запустите python2 test.py или LD_LIBRARY_PATH=./ ./sqlchop_test

is_sqli

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

Параметр: строка

Возвращаемое значение: тип bool, возвращает True для SQLi (инжект), возвращает False для нормальных случаев.

>>> from sqlchop import SQLChop
>>> detector = SQLChop()
>>> detector.is_sqli('SELECT 1 From users')
True
>>> detector.is_sqli("' or '1'='1")
True
>>> detector.is_sqli('select the best student from classes as the student union representative')
False
>>> detector.is_sqli('''(select(0)from(select(sleep(0)))v)/*'+(select(0)from(select(sleep(12)))v)+'"+(select(0)from(select(sleep(0)))v)+"*/''')
True

classify

Получив ввод для веб-приложения, classify API декодирует этот ввод и ищут возможный SQL-инжект внутри. Если SQLi найден, то будет выведен запрос.

  • Параметр 1: объект со следующими ключами
  1. urlpath: полный адрес веб-запроса
  2. body: строка, тело http запроса POST/PUT
  3. cookie: строка, содержимое куки веб-запроса
  4. raw: строка, другое обычное поле, которое нуждается в обычном декодировании.
  • Параметр 2: детали, если возвращаемое значение True, то будут возвращены детали по запросу, если False, то будет возвращён только результат, которые выполняется быстрее.
  • Return: объект содержит результат и запрос
  1. result: int, положительная величина, показывающая содержит ли веб-запрос sql-инжект
  2. payloads: список объектов, содержащих key, score, value и source
  • key: строка, зарезервирована
  • source: строка, показывает, как рабочий запрос включён в оригинальный веб-запрос и как рабочий запрос раскодирован
  • value: раскодированный sqli запрос
  • score: источник декодированного запроса sqli

Пример:

>>> from sqlchop import SQLChop
>>> detector = SQLChop()
>>> detector.classify({'urlpath': '/tag/sr/news.asp?d=LTElMjBhbmQlMjAxPTIlMjB1bmlvbiUyMHNlbGVjdCUyMDEsMiwzLGNocigxMDYpLDUsNiw3LDgsOSwxMCwxMSwxMiUyMGZyb20lMjBhZG1pbg==' }, True)
>>> 
{
    'payloads': [{
        'key': '',
        'score': 4.070000171661377,
        'source': 'urlpath: querystring_decode b64decode url_decode ',
        'value': '-1 and 1=2 union select 1,2,3,chr(106),5,6,7,8,9,10,11,12 from admin'
    }],
    'result': 1
}

>>> detector.classify({'body': 'opt=saveedit&arrs1[]=83&arrs1[]=69&arrs1[]=76&arrs1[]=69&arrs1[]=67&arrs1[]=84&arrs1[]=32&arrs1[]=42&arrs1[]=32&arrs1[]=70&arrs1[]=114&arrs1[]=111&arrs1[]=109&arrs1[]=32&arrs1[]=84&arrs1[]=97&arrs1[]=98&arrs1[]=108&arrs1[]=101&arrs1[]=32&arrs1[]=87&arrs1[]=72&arrs1[]=69&arrs1[]=82&arrs1[]=69&arrs1[]=32&arrs1[]=78&arrs1[]=97&arrs1[]=109&arrs1[]=101&arrs1[]=61&arrs1[]=39&arrs1[]=83&arrs1[]=81&arrs1[]=76&arrs1[]=32&arrs1[]=105&arrs1[]=110&arrs1[]=106&arrs1[]=101&arrs1[]=99&arrs1[]=116&arrs1[]=39&arrs1[]=32&arrs1[]=97&arrs1[]=110&arrs1[]=100&arrs1[]=32&arrs1[]=80&arrs1[]=97&arrs1[]=115&arrs1[]=115&arrs1[]=119&arrs1[]=111&arrs1[]=114&arrs1[]=100&arrs1[]=61&arrs1[]=39&arrs1[]=39&arrs1[]=32&arrs1[]=97&arrs1[]=110&arrs1[]=100&arrs1[]=32&arrs1[]=67&arrs1[]=111&arrs1[]=114&arrs1[]=112&arrs1[]=61&arrs1[]=39&arrs1[]=39&arrs1[]=32&arrs1[]=111&arrs1[]=114&arrs1[]=32&arrs1[]=49&arrs1[]=61&arrs1[]=40&arrs1[]=83&arrs1[]=69&arrs1[]=76&arrs1[]=69&arrs1[]=67&arrs1[]=84&arrs1[]=32&arrs1[]=64&arrs1[]=64&arrs1[]=86&arrs1[]=69&arrs1[]=82&arrs1[]=83&arrs1[]=73&arrs1[]=79&arrs1[]=78&arrs1[]=41&arrs1[]=45&arrs1[]=45&arrs1[]=32&arrs1[]=39'}, True)
>>>
{
    'payloads': [{
        'key': '',
        'score': 3.9800000190734863,
        'source': 'body: querystring_decode ',
        'value': "SELECT * From Table WHERE Name='SQL inject' and Password='' and Corp='' or 1=(SELECT @@VERSION)-- '"
    }, {
        'key': '',
        'score': 2.0899999141693115,
        'source': 'body: querystring_decode ',
        'value': "'SQL inject' and Password"
    }, {
        'key': '',
        'score': 2.180000066757202,
        'source': 'body: querystring_decode ',
        'value': "(SELECT @@VERSION)-- '"
    }, {
        'key': '',
        'score': 0.0,
        'source': 'body: querystring_decode ',
        'value': 'saveedit'
    }],
    'result': 1
}

Настройка

is_sqli API (в sqlchop.py) выявляют SQLi, дают оценку в качестве некоторой величины, вы можете настроить порог этой величины и вызвать действие в соответствии со сценарием использования.

def is_sqli(self, payload):
        ret = self.score_sqli(payload)
        return ret > 2.1  # here you can modify and test this threshold

    def classify(self, request, detail=False):
        ...

Оставить ответ

Ваш адрес email не будет опубликован. Обязательные поля помечены *