А как бы вы сделали? [ OSQuery - Часть 1]

D2

Администратор
Регистрация
19 Фев 2025
Сообщения
4,380
Реакции
0

osqueryi​

Это первая часть статьи, которая посвящена OSQuery, вторая часть будет "OSQuery + MITRE". В этой статье мы немного поработаем с osquery и будем использовать небольшой графический интерфейс, который я создал.

Спойлер: Все мои статьи
Дневник белой шляпы
НЕ Дневник белой шляпы

Содержание
  • Что такое OSQuery?
  • Лаборатории

Что такое OSQuery?​

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

Установка OSQuery​

На этот раз мы будем использовать Kali Linux в качестве нашей лаборатории. Я установлю там OSQuery, и мы немного поработаем там, а уже после этого проверим лаборатории.

Код: Скопировать в буфер обмена
Код:
sudo mkdir -p /etc/apt/keyrings
curl -L https://pkg.osquery.io/deb/pubkey.gpg | sudo tee /etc/apt/keyrings/osquery.asc
sudo nano /etc/apt/sources.list # deb [arch=amd64 signed-by=/etc/apt/keyrings/osquery.asc] https://pkg.osquery.io/deb deb main
sudo apt update
sudo apt install osquery
sudo systemctl start osqueryd

Я поискал и нашел статьи, где OSQuery настраивается вместе с Wazuh. Подключение Osquery к Wazuh позволяет нам использовать подробную системную информацию, предоставляемую OSQuery, в наших рабочих процессах мониторинга безопасности. Эта интеграция может помочь нам более эффективно выявлять угрозы безопасности и реагировать на них. Я не член синей команды, я не эксперт, я стараюсь специализироваться только в одной области и чуток в областях, связанных с ней. #RedTeamForever

Я решил создать простой интерфейс для OSQuery. Чтобы мы могли нажимать на кнопки и получать системную информацию в любое удобное для нас время. Также я постараюсь проверить его на наличие потенциальных проблем с безопасностью. Я хочу сделать все это для того, чтобы мы лучше понимали OSQuery и только после этого переходили к лабораторным работам.

Начинаем Работу​

Где находится база данных osquery?
OSQuery использует базу данных SQLite для локального хранения. Расположение базы данных osquery в системе зависит от операционной системы, в которой она запущена. В Linux база данных OSQuery хранится в /var/osquery/osquery.db. Это каталог, а не файл. В этом каталоге есть файлы внутри, в моем случае они:

000005.log | CURRENT | IDENTITY | LOCK | MANIFEST-000004 | OPTIONS-000019 | OPTIONS-000021

У меня не так много информации о них, поэтому мы не собираемся их трогать (не сегодня).

Ладно, пора выполнить несколько запросов. Давайте начнем с .tables - это, очевидно, покажет нам таблицы:
Код: Скопировать в буфер обмена
osqueryi '.tables’
Код: Скопировать в буфер обмена
Код:
  => acpi_tables
  => apparmor_events
  => apparmor_profiles
  => apt_sources
  => arp_cache
  => atom_packages
  => augeas
  => authorized_keys
  => azure_instance_metadata
  => azure_instance_tags
  => block_devices
  => bpf_process_events
  => bpf_socket_events
  => carbon_black_info
  => carves
  => certificates
  => chrome_extension_content_scripts
  => chrome_extensions
  => cpu_info
  => cpu_time
  => cpuid
  => crontab
  => curl
  => curl_certificate
  => deb_packages
  => device_file
  => device_hash
  => device_partitions
  => disk_encryption
  => dns_resolvers
  => docker_container_envs
  => docker_container_fs_changes
  => docker_container_labels
  => docker_container_mounts
  => docker_container_networks
  => docker_container_ports
  => docker_container_processes
  => docker_container_stats
  => docker_containers
  => docker_image_history
  => docker_image_labels
  => docker_image_layers
  => docker_images
  => docker_info
  => docker_network_labels
  => docker_networks
  => docker_version
  => docker_volume_labels
  => docker_volumes
  => ec2_instance_metadata
  => ec2_instance_tags
  => etc_hosts
  => etc_protocols
  => etc_services
  => extended_attributes
  => file
  => file_events
  => firefox_addons
  => groups
  => hardware_events
  => hash
  => intel_me_info
  => interface_addresses
  => interface_details
  => interface_ipv6
  => iptables
  => kernel_info
  => kernel_keys
  => kernel_modules
  => known_hosts
  => last
  => listening_ports
  => load_average
  => logged_in_users
  => lxd_certificates
  => lxd_cluster
  => lxd_cluster_members
  => lxd_images
  => lxd_instance_config
  => lxd_instance_devices
  => lxd_instances
  => lxd_networks
  => lxd_storage_pools
  => magic
  => md_devices
  => md_drives
  => md_personalities
  => memory_array_mapped_addresses
  => memory_arrays
  => memory_device_mapped_addresses
  => memory_devices
  => memory_error_info
  => memory_info
  => memory_map
  => mounts
  => msr
  => npm_packages
  => oem_strings
  => os_version
  => osquery_events
  => osquery_extensions
  => osquery_flags
  => osquery_info
  => osquery_packs
  => osquery_registry
  => osquery_schedule
  => pci_devices
  => platform_info
  => portage_keywords
  => portage_packages
  => portage_use
  => process_envs
  => process_events
  => process_file_events
  => process_memory_map
  => process_namespaces
  => process_open_files
  => process_open_pipes
  => process_open_sockets
  => processes
  => prometheus_metrics
  => python_packages
  => routes
  => rpm_package_files
  => rpm_packages
  => seccomp_events
  => secureboot
  => selinux_events
  => selinux_settings
  => shadow
  => shared_memory
  => shell_history
  => smbios_tables
  => socket_events
  => ssh_configs
  => startup_items
  => sudoers
  => suid_bin
  => syslog_events
  => system_controls
  => system_info
  => systemd_units
  => time
  => ulimit_info
  => uptime
  => usb_devices
  => user_events
  => user_groups
  => user_ssh_keys
  => users
  => yara
  => yara_events
  => ycloud_instance_metadata
  => yum_sources
Я думаю, мы можем понять таблицы по их названиям.

У каждого есть видение на своем собственном уровне. В моем случае, я думаю, одной из таблиц, которые мы должны проверить через OSQuery, является таблица "logged_in_users". Как вы можете понять, он покажет нам список вошедших в систему пользователей. В некоторых случаях может быть полезно узнать, кто вошел на ваш сервер. Но это не будет означать, что если нет дополнительного пользователя, то мы в безопасности. Допустим, у нас есть веб-сайт, который имеет уязвимость RCE, в этом случае мы увидим выполнение команд, скажем, от пользователя www-data. Таблица со списком вошедших в систему пользователей не изменится, так как никто не входил в систему, но все же команды выполняются.
Код: Скопировать в буфер обмена
osqueryi 'SELECT * FROM logged_in_users;'
Код: Скопировать в буфер обмена
Код:
+-----------+----------+-------+-------------------+------------+-------+
| type      | user     | tty   | host              | time       | pid   |
+-----------+----------+-------+-------------------+------------+-------+
| boot_time | reboot   | ~     | 6.3.0-kali1-amd64 | 1695982752 | 0     |
| runlevel  | runlevel | ~     | 6.3.0-kali1-amd64 | 1695982754 | 53    |
| login     | LOGIN    | tty1  |                   | 1695982754 | 927   |
| user      | kali     | tty7  | :0                | 1695983314 | 1259  |
| user      | kali     | pts/1 |                   | 1695983342 | 2057  |
| user      | xss      | pts/2 | 10.161.31.1       | 1696009938 | 99983 |
+-----------+----------+-------+-------------------+------------+-------+
Мы видим, что есть зарегистрированный пользователь xss и локальный IP-адрес. Я думаю, что в реальной жизни вполне вероятно, что кто-то получит пароль от вашего сервера и логин для входа. Если ваш пароль сгенерирован автоматически, то вы, вероятно, сохранили его где-нибудь, если он не сгенерирован автоматически, то вы, вероятно, использовали его где-то в другом месте. В обоих случаях получение вашего пароля возможно.

Мы также можем получить список процессов (это полезно для меня) в случае, если мы запускаем какие-то инструменты на нашем сервере, приятно знать, что они работают, также мы можем понять, когда инструмент завершил свою работу. Очевидно, что все это также можно сделать без OSQuery, но в таком случае эта статья была бы бесполезна, поэтому мы используем osquery :движуха:

Команда для отображения списка всех процессов:
Код: Скопировать в буфер обмена
osqueryi 'SELECT * FROM processes;'

Изображение [1]: Запрашиваем процессы


Изображение [1]: Запрашиваем процессы​

Допустим, что меня интересует только конкретный процесс, например ping, тогда я могу использовать команду:
Код: Скопировать в буфер обмена
osqueryi 'SELECT * FROM processes WHERE name = "ping";'
Код: Скопировать в буфер обмена
Код:
+-------+------+---------------+--------------+-------+------------+------+------+------+------+------+------+------+---------+------------+---------------+------------+-----------+-------------+-----------------+--------------------+------------+--------+--------+---------+------+---------------------------------------------+
| pid   | name | path          | cmdline      | state | cwd        | root | uid  | gid  | euid | egid | suid | sgid | on_disk | wired_size | resident_size | total_size | user_time | system_time | disk_bytes_read | disk_bytes_written | start_time | parent | pgroup | threads | nice | cgroup_path                                 |
+-------+------+---------------+--------------+-------+------------+------+------+------+------+------+------+------+---------+------------+---------------+------------+-----------+-------------+-----------------+--------------------+------------+--------+--------+---------+------+---------------------------------------------+
| 26606 | ping | /usr/bin/ping | ping 1.1.1.1 | S     | /home/kali | /    | 1000 | 1000 | 1000 | 1000 | 1000 | 1000 | 1       | 0          | 2490368       | 7860224    | 130       | 1320        | 94208           | 0                  | 1696001334 | 26565  | 26606  | 1       | 0    | /user.slice/user-1000.slice/session-5.scope |
+-------+------+---------------+--------------+-------+------------+------+------+------+------+------+------+------+---------+------------+---------------+------------+-----------+-------------+-----------------+--------------------+------------+--------+--------+---------+------+---------------------------------------------+
Мы также можем ввести путь, по которому находится команда, или команду, которую мы выполнили. Путь был бы /usr/bin/ping, а команда - "ping 1.1.1.1". Давайте попробуем написать эти запросы.

Чтобы получить информацию через путь к команде, результат будет таким же, как указано выше.
Код: Скопировать в буфер обмена
osqueryi 'SELECT * FROM processes WHERE path = "/usr/bin/ping";'
Теперь давайте напишем запрос, основанный на команде, которую мы выполнили. Допустим, я ежедневно “пингую” разные IP-адреса, теперь я не знаю, какой из них я проверял сегодня. Я могу использовать "LIKE" в SQL для получения информации с помощью команды. В этом случае наш запрос будет выглядеть следующим образом:
Код: Скопировать в буфер обмена
osqueryi 'SELECT * FROM processes WHERE cmdline LIKE "ping%";'
Я подумал, что делать все это с помощью кнопок будет очень утомительно. Лучше создать строку поиска и сделать ее автозаполняемой, например, когда я напишу "пользователь", я получу любую таблицу с именем, содержащим слово "пользователь".

API​

Чтобы все это заработало, мы должны сначала создать простой API и заставить его выполнять запросы OSQuery. Когда я смотрю на этот код, я думаю, что он уязвим для внедрения команд операционной системы, SQL-инъекции и нарушенного контроля доступа. Но прежде чем говорить о каком-либо из них, позвольте мне объяснить, что делает этот код. Значит, если пользователь запрашивает из /api /tables, то пользователь получает список таблиц. Это поможет нам выполнить автозаполнение через строку поиска. Кроме этого, когда пользователь запрашивает что-либо еще, скажем, /api/users, выполняется запрос OSQuery, и результат поступает к нам через этот API. Если мы захотим, мы можем интегрировать его с Telegram, на самом деле мы можем интегрировать его со всем, что захотим! Кстати, также для запроса данных должен быть заголовок "Gucci: Gang", в противном случае он выведет "401".

Код: Скопировать в буфер обмена
Код:
from flask import Flask, request, jsonify
import subprocess
import json
from flask_cors import CORS

app = Flask(__name__)
CORS(app)

def read_table_names(file_path):
    with open(file_path, 'r') as file:
        return [line.strip() for line in file]

table_names_file = 'osquery_tables.txt'

table_names = read_table_names(table_names_file)

@app.route('/api/<table_name>', methods=['GET'])
def get_table_info(table_name):
    if request.headers.get('Gucci') == 'Gang'and table_name != 'tables':
        try:
            query = f'SELECT * FROM {table_name}'
            result = subprocess.check_output(['osqueryi', '--json', query])
            data = result.decode('utf-8').strip()
            return jsonify({table_name: json.loads(data)})
        except Exception as e:
            return jsonify({'error': str(e)})
    elif request.headers.get('Gucci') == 'Gang' and table_name == 'tables':
        try:
            query = f'.tables'
            result = subprocess.check_output(['osqueryi', query])
            data = result.decode('utf-8')
            return data
        except Exception as e:
            return jsonify({'error': str(e)})
    else:
        return jsonify({'error': 'Unauthorized'}), 401

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

FRONT-END​

Это интерфейсная часть нашего приложения. У него включено автозаполнение, и он получает список таблиц из бэкенда. Когда мы используем enter, он автоматически выполняет запрос и выдает нам ответ. На самом деле в этой части есть уязвимость XSS, она не сохраняется и не отражается, как вы думаете, что это за XSS?
Код: Скопировать в буфер обмена
Код:
<!DOCTYPE html>
<html>
<head>
    <title>OSQuery</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 0;
        }

        h1 {
            background-color: #333;
            color: #fff;
            padding: 10px;
            margin: 0;
        }

        #result {
            margin: 20px;
            padding: 20px;
            border: 1px solid #ddd;
            background-color: #f5f5f5;
            overflow: auto;
            max-height: 400px;
        }
        @media screen and (max-width: 768px) {
            h1 {
                font-size: 24px;
            }

            #result {
                margin: 10px;
                padding: 10px;
            }
        }

        table {
            width: 100%;
            border-collapse: collapse;
        }

        th, td {
            border: 1px solid #ddd;
            padding: 8px;
            text-align: left;
        }

        th {
            background-color: #f2f2f2;
        }

        #query-form {
            display: flex;
            justify-content: center;
            align-items: center;
            margin-top: 20px;
        }

        #table_name {
            flex: 1;
            padding: 10px;
            border: 1px solid #ccc;
            border-radius: 4px;
            margin-right: 10px;
        }
        footer {
            text-align: center;
            padding: 0.1px;
            background-color: grey;
            color: white;
        }

    </style>
    <link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
</head>
<body>
    <h1>OSQuery для XSS.is</h1>
 
    <div id="query-form">
        <input type="text" id="table_name" placeholder="Введите имя таблицы">
    </div>
 
    <div id="result">
    </div>

    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
    <script>
    $(document).ready(function() {
        function getTableData(table_name) {
            table_name = table_name.trim();
 
            $.ajax({
                url: `http://localhost:5000/api/${table_name}`,
                method: 'GET',
                headers: { 'Gucci': 'Gang' },
                success: function(data) {
                    console.log('Response from server:', data);
                    console.log('Table name:', table_name);

                    if (!data || $.isEmptyObject(data) || (data[table_name] && data[table_name].length === 0)) {
                        $('#result').html('<p>No response was returned</p>');
                    } else if (data.error) {
                        $('#result').html('<p>Error: ' + data.error + '</p>');
                    } else if (data[table_name]) {
                        var tableHtml = '<table><thead><tr>';
                        var keys = Object.keys(data[table_name][0]);

                        for (var i = 0; i < keys.length; i++) {
                            tableHtml += '<th>' + keys[i] + '</th>';
                        }
                        tableHtml += '</tr></thead><tbody>';

                        for (var i = 0; i < data[table_name].length; i++) {
                            tableHtml += '<tr>';
                            for (var j = 0; j < keys.length; j++) {
                                tableHtml += '<td>' + data[table_name][i][keys[j]] + '</td>';
                            }
                            tableHtml += '</tr>';
                        }
                        tableHtml += '</tbody></table>';

                        $('#result').html(tableHtml);
                    } else {
                        $('#result').html('<p>Error: Table data for ' + table_name + ' not found in the response.</p>');
                    }
                },
                error: function(error) {
                    $('#result').html('<p>Error: ' + error.responseText + '</p>');
                }
            });
        }

        $.ajax({
            url: 'http://localhost:5000/api/tables',
            method: 'GET',
            success: function(data) {
                var tableNames = data.split(' => ');
                tableNames.shift();

                $('#table_name').autocomplete({
                    source: tableNames,
                    minLength: 2,
                    select: function(event, ui) {
                        $(this).val(ui.item.value);
                        getTableData(ui.item.value);
                        return false;
                    }
                });
            },
            error: function(error) {
                console.error('Error fetching table list:', error);
            }
        });

        $('#table_name').keypress(function(event) {
            if (event.which === 13) {
                var tableName = $(this).val();
                getTableData(tableName);
            }
        });
    });
   </script>
<footer>
  <p>Сделано с ♥ для XSS.is<br>
</footer>
</body>
</html>


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

Запустите это приложение на одном сервере, если вы будете работать на разных серверах, просто замените "localhost" на IP-адрес сервера, на котором запущен скрипт python.

Запуск приложения:
Bash: Скопировать в буфер обмена
Код:
sudo service apache2 start
cd /var/www/html
sudo rm index.html
sudo nano index.html #вставляем второй код и открываем в localhost браузере
cd
mkdir server
cd server
nano server.py #вставляем первый код
python3 server.py

Продолжение в комментах

Автор grozdniyandy

Источник https://xss.is/

 
Сверху Снизу