• XSS.stack #1 – первый литературный журнал от юзеров форума

Статья Магический --eval великолепного SQLMap

вавилонец

CPU register
Пользователь
Регистрация
17.06.2021
Сообщения
1 116
Реакции
1 265
Освойте возможности использования самых сложных SQL-инъекций

1656071901414.png

Иногда вам нужна мощь четырех элементов , чтобы автоматизировать использование SQL-инъекций.
Это то что --eval дает вам, и вот как взять на себя эту силу.
В зависимости от случая вам может потребоваться изменить различные части запроса.
SQLMap использует exec() метод для выполнения вашего скрипта. инструмент передает разные части запроса этому методу как локальные переменные. таким образом, вы можете получить к ним доступ и изменить их.
тело сообщения запроса может иметь разные типы данных, такие как JSON, XML и т. д., чтобы обеспечить доступ к элементам каждого типа, SQLMap распознает тип по этим регулярным выражениям затем спрашивает, хотите ли вы, чтобы инструмент обрабатывал данные:
JSON/XML/... data found in POST/PUT/... body. Do you want to process it?
очевидно, вам нужно ответить YES, если вы хотите, чтобы все работало как задумано.

Доступ к различным частям запроса

URI​

URI запроса без строки запроса доступен через uriпараметр.
если пользователь указывает пользовательскую точку внедрения в пути URL-адреса, uriПараметр также будет содержать внедренную полезную нагрузку в кодировке URL.
пример:

Код:
sqlmap -u “http://example.com/path?id=123"

локальная переменная:

Код:
uri --> http://example.com/path

локальная переменная:

Код:
uri --> http://example.com/path

команда:

Код:
sqlmap -u “http://example.com/path*?id=123"

локальная переменная:

Код:
uri --> http://example.com/path<URL-ENCODED PAYLOAD>

GET - запрос

значение каждого параметра запроса GET, а также введенная полезная нагрузка (если есть) доступны через локальные переменные с именем исходных параметров GET.
пример:
Код:
sqlmap -u "http://example.com/path?param1=123&param2=456&class.id=789"

локальные переменные:
Код:
param1 --> 123
param2 --> 456
EVAL_636c6173732e6964 --> 789(читайте примечание ниже)

Примечание: если имя параметра содержит специальные символы или является зарезервированным ключевым словом в python, перед передачей переменной в exec() метод, SQLMap меняет свое имя на основе этого шаблона:
Код:
EVAL_<HEX OF ORIGINAL NAME>

применяется ко всем переменным, которые передаются в метод exec(), включая файлы cookie и данные POST.

ВКУСНЯШКИ

1656072516467.png

содержание заголовков Cookie, а также введенная полезная нагрузка (если есть) доступны через переменную cookie.

команда:

Код:
 sqlmap -u "http://example.com/path?id=123" --cookie=”C1=123; C2=456"

локальная переменная:

Код:
cookie --> C1=123; C2=456

заголовки

есть два словаря в exec(), связанный с заголовками запроса:
Код:
_locals['headers']
_locals['auxHeaders']
Вы можете получить доступ к заголовкам запроса через headers, но его изменение не повлияет на запрос, чтобы внести изменения в заголовки конечного запроса, вам нужен update() в auxHeaders.
Значение auxHeaders является Noneпо умолчанию. это означает, что вам нужно добавить все заголовки — измененные или нет, в auxHeaders.
пример:
допустим, вы хотите изменить значение заголовка User-Agent и добавьте собственный заголовок аутентификации X-Auth.

Это может выглядеть так.

Код:
# _locals['auxHeaders'] is None here
_locals['headers']['User-Agent'] = "pentesting, no worries!!"
_locals['headers']['X-Auth'] = "My_Secret_Token"
_locals['auxHeaders'].update(_locals['headers'])

POST тело

SQLMap распознает шесть типов данных POST, используя регулярные выражения:

JSON
JSON-like (regex)
XML
Multipart
Array-like (regex)
Form-based

Чтобы увидеть, как выглядят типы данных, подобные JSON и массивам, обратитесь к регулярным выражениям, которые их распознают. На момент написания этой статьи SQLMap разбирает form-based а также json типы данных. Для других типов данных у вас нет доступа к значению элементов но вы все равно можете изменить значение элементов, объявив переменную с тем же именем, что и имя элемента. SQLMap заменяет исходное значение новым с помощью регулярного выражения,обратите внимание, что эта реализация содержит ошибки array-like типы данных, но вы можете найти решение здесь .

полезная нагрузка

полезная нагрузка SQL, которую SQLMap внедрил в запрос, доступен через _locals['payload'] переменную.

длинные сценарии

Когда код, который вы хотите выполнить, состоит из нескольких строк, вы можете добавить скрипт в качестве значения --eval в терминале:
Код:
sqlmap ... --eval="#first_line; #second_line; #third_line"
но если ваш сценарий длиннее, не рекомендуется писать весь сценарий в терминале, вместо этого вы можете написать свой код в .py файл и импортировать его как модуль:
Код:
sqlmap ... --eval="import myModule; #use_functions_of_myModule"

отладка

Если вы хотите отладить свой код внутри SQLMap или хотите познакомиться с окружающей средой, вы можете использовать ipdp модуль это дает вам отладочную оболочку, и вы можете перемещаться и видеть, что происходит. в locals() может быть хорошей отправной точкой.
Код:
sqlmap ... --eval=”import ipdb; ipdb.set_trace()”

Новая реализация

Как вы можете видеть, гораздо лучше с флагом --eval. В этой новой реализации все типы данных поддерживаются унифицированным образом, также, я сделал row GET/ POST данные доступны как локальные переменные, так что, если пользователю нужно модифицировать запрос, а уже локальные существующие переменные ему не нужны, он может использовать сырые данные и парсить их так, как ему нужно.

Пользователь имеет доступ к этим словарям как к локальным переменным:

headers: все заголовки запроса. изменение этого словаря повлияет на запрос.
get_data: обработанные данные запроса GET
post_data: обработанное тело POST. независимо от того, какой тип данных, пользователь имеет доступ ко ВСЕМ элементам и атрибутам типа данных.
get_query: необработанные данные запроса GET
post_body: необработанные данные тела POST

Примечание: изменение get_query или же post_body перезапишет изменения, внесенные в get_data, а также post_data соответственно.

Код:
if conf.evalCode:
            delimiter = conf.paramDel or DEFAULT_GET_POST_DELIMITER
            variables = {"uri": uri, "get_query": get, "headers": headers, "post_body": post, "get_data": {}, "post_data": {}, "lastPage": threadData.lastPage, "_locals": locals()}
            original_get = get
            original_post = post
            if get:
                for part in get.split(delimiter):
                    if '=' in part:
                        name, value = part.split('=', 1)
                        name = name.strip()
                        value = urldecode(value, convall=True)
                        variables['get_data'][name] = value
            if kb.postHint:
                if kb.postHint in (POST_HINT.XML, POST_HINT.SOAP):
                    variables['post_data'] = xmltodict.parse(post)
                if kb.postHint == POST_HINT.JSON:
                    variables['post_data'] = json.loads(post)
                if kb.postHint == POST_HINT.JSON_LIKE:
                    if json_like_type == 3:
                        post = re.sub(r'(,|\{)\s*([^\'\s{,]+)\s*:', '\g<1>"\g<2>":', post)
                    if json_like_type == 4:
                        post = re.sub(r'(,|\{)\s*([^\'\s{,]+)\s*:', "\g<1>'\g<2>':", post)
                    if json_like_type in (2, 4):
                        post = post.replace("\\'", REPLACEMENT_MARKER).replace('\"','\\"').replace("'",'"').replace(REPLACEMENT_MARKER, "'")
                    variables['post_data'] = json.loads(post)
                if kb.postHint == POST_HINT.MULTIPART:
                    multipart = MultipartDecoder(bytes(post, 'utf-8'), contentType)
                    boundary = '--' + multipart.boundary.decode('utf-8')
                    for part in multipart.parts:
                        name = re.search(r'"([^\"]*)"', part.headers._store[b'content-disposition'][1].decode('utf-8')).group(1)
                        value = part.text
                        variables['post_data'][name] = value
                if kb.postHint == POST_HINT.ARRAY_LIKE:
                    post = re.sub(r"\A%s" % delimiter, "", post)
                    array_name = re.findall(r"%s(.*?)\[\]=" % delimiter, post)[0].strip()
                    variables['post_data'] = []
                    for value in post.split("%s[]=" % array_name)[1:]:
                        variables['post_data'].append(value.replace(delimiter, ""))
            elif post:
                for part in post.split(delimiter):
                    if '=' in part:
                        name, value = part.split('=', 1)
                        name = name.strip()
                        value = urldecode(value, convall=True, spaceplus=kb.postSpaceToPlus)
                        variables['post_data'][name] = valueevaluateCode(conf.evalCode, variables)if kb.postHint:
                if kb.postHint in (POST_HINT.XML, POST_HINT.SOAP):
                    post = xmltodict.unparse(variables['post_data'])
                if kb.postHint == POST_HINT.JSON:
                    post = json.dumps(variables['post_data'])
                if kb.postHint == POST_HINT.JSON_LIKE:
                    post = json.dumps(variables['post_data'])
                    if json_like_type in (3, 4):
                        post = re.sub(r'"([^"]+)":', '\g<1>:', post)
                    if json_like_type in (2, 4):
                        post = post.replace('\\"', REPLACEMENT_MARKER).replace("'", "\\'").replace('"', "'").replace(REPLACEMENT_MARKER, '"')
                if kb.postHint == POST_HINT.MULTIPART:
                    for name, value in variables['post_data'].items():
                        post = re.sub(r"(?s)(name=\"%s\"(?:; ?filename=.+?)?\r\n\r\n).*?(%s)" % (name, boundary), r"\g<1>%s\r\n\g<2>" % value.replace('\\', r'\\'), post)
                if kb.postHint == POST_HINT.ARRAY_LIKE:
                    post = array_name + "[]=" + (delimiter + array_name + "[]=").join(variables['post_data'])
            else:
                post = delimiter.join(f'{key}={value}' for key, value in variables['post_data'].items())uri = variables['uri']
            get = delimiter.join(f'{key}={value}' for key, value in variables['get_data'].items())
            auxHeaders.update(variables['headers'])
            cookie = variables['headers']['Cookie'] if 'Cookie' in variables['headers'] else None
            get = variables['get_query'] if variables['get_query'] != original_get else get
            post = variables['post_body'] if variables['post_body'] != original_post else post

Вам нужно добавить эти библиотеки в папку thirdparty:

xmltodict
request_toolblet

для получения дополнительной информации об этой реализации обратитесь к pull request on Github.



ОРИГИНАЛЬНАЯ СТАТЬЯ
 

Вложения

  • 1656072308679.png
    1656072308679.png
    62.5 КБ · Просмотры: 5


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх