Как получить ключ безопасности WiFi (WPA, WPA2, ESS) сканируемых сетей с помощью NL80211_BSS_CAPABILITY?

Я использую библиотеку netlink nl80211.h для сканирования сетей Wi-Fi и успешного получения ssid, mac-адреса, статуса, частоты и сигнала. Я хочу добавить тип безопасности каждой сети, используя одну и ту же библиотеку. Я использую NL80211_BSS_CAPABILITY как одно из перечислений, которое дает целое число, которое я жестко кодирую в своем коде для безопасности. Это кажется утомительным, и при таком подходе необходимо вводить много данных (целочисленных значений). Получение WPA/WPA2 — это хорошо, но код не работает, когда есть открытые сети. Ниже приведены значения, которые я использовал до сих пор. Лучшая логика, которая могла бы открыть мне сеть (ESS или WEP), была бы оценена предпочтительно по аналогии с wpa_supplicant и библиотекой netlink.

int keynum;
char *keytype;
keynum = nla_get_u32(bss[NL80211_BSS_CAPABILITY]);

if(keynum==5153 || keynum == 34)
    keytype="NONE";

else if(keynum==5169 || keynum == 1297 || keynum==1073|| keynum == 5393)
    keytype="WPA2";

else if (keynum == 1041)
    keytype="WPA WPA2";

else
    keytype="WPA WPA2";

person iambhaskaranand    schedule 15.01.2021    source источник
comment
привет, я столкнулся с точно такой же проблемой, не могли бы вы сказать мне, нашли ли вы решение или какую-либо вспомогательную информацию?   -  person Gaurav Goswami    schedule 24.03.2021


Ответы (1)


Во-первых, давайте посмотрим, какие данные находятся в NL80211_BSS_CAPABILITY
Чтобы понять это, я сначала обращу ваше внимание на свойство NL80211_BSS_BEACON_IES
Описание этого поля выглядит следующим образом:

/**
* @NL80211_BSS_BEACON_IES: binary attribute containing the raw
* information
*/

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

  1. Информация о возможностях (2 байта) Это поле содержит количество подполей, которые используются для указания запрошенных или объявленных дополнительных возможностей.

Возьмем, к примеру, один из пакетов, захваченных с помощью wireshark, и его поле Сapabilities Information (хорошая статья о том, как это сделать, — здесь):

Сapabilities Information: 0x0431
            .... .... .... ...1 = ESS capabilities: Transmitter is an AP
            .... .... .... ..0. = IBSS status: Transmitter belongs to a BSS
            .... ..0. .... 00.. = CFP participation capabilities: No point coordinator at AP (0x00)
            .... .... ...1 .... = Privacy: AP/STA can support WEP
            .... .... ..1. .... = Short Preamble: Allowed
            .... .... .0.. .... = PBCC: Not Allowed
            .... .... 0... .... = Channel Agility: Not in use
            .... ...0 .... .... = Spectrum Management: Not Implemented
            .... .1.. .... .... = Short Slot Time: In use
            .... 0... .... .... = Automatic Power Save Delivery: Not Implemented
            ...0 .... .... .... = Radio Measurement: Not Implemented
            ..0. .... .... .... = DSSS-OFDM: Not Allowed
            .0.. .... .... .... = Delayed Block Ack: Not Implemented
            0... .... .... .... = Immediate Block Ack: Not Implemented

Как мы видим, один из флагов (под общим именем security или Privacy: AP/STA can support WEP, как в данном случае). Этот флаг, как написано, говорит нам, что эта сеть поддерживает шифрование wep. Но другие флаги этого тега не несут информации о других алгоритмах кодирования, используемых в сети. Поэтому впоследствии этот анализ этого поля превратится в:

if (bss[NL80211_BSS_CAPABILITY] != NULL) {
    wlan_info.bss_capability = nla_get_u16(bss[NL80211_BSS_CAPABILITY]);
  }
  if (!(wlan_info.bss_wpa1_wpa2 | wlan_info.bss_wpa2 | wlan_info.bss_wpa1)) {
    wlan_info.bss_wep = wlan_info.bss_capability & 16;
  }

Но это еще не конец. Нам еще нужно найти информацию о других алгоритмах шифрования.
Для этого возвращаемся к NL80211_BSS_BEACON_IES.
1.Проверяем, не пусто ли оно.

if (NULL != bss[NL80211_BSS_BEACON_IES] && NULL != nla_data(bss[NL80211_BSS_BEACON_IES]))

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

for (int i = 0;;) {
      bool first = i;
      uint8_t header_type =
          *(uint8_t *)((nla_data(bss[NL80211_BSS_BEACON_IES])) + i++);
      uint8_t header_len =
          *(uint8_t *)((nla_data(bss[NL80211_BSS_BEACON_IES])) + i++);
      i += header_len;

3.Среди всех тегов ищем 2 конкретных: # 48 (0x30) или # 221 (0xDD).Они могут выглядеть так:

Первый:

Tag: RSN Information
            Tag Number: RSN Information (48)
            Tag length: 20
            RSN Version: 1
            Group Cipher Suite: 00:0f:ac (Ieee 802.11) AES (CCM)
                Group Cipher Suite OUI: 00:0f:ac (Ieee 802.11)
                Group Cipher Suite type: AES (CCM) (4)
            Pairwise Cipher Suite Count: 1
            Pairwise Cipher Suite List 00:0f:ac (Ieee 802.11) AES (CCM)
                Pairwise Cipher Suite: 00:0f:ac (Ieee 802.11) AES (CCM)
                    Pairwise Cipher Suite OUI: 00:0f:ac (Ieee 802.11)
                    Pairwise Cipher Suite type: AES (CCM) (4)
            Auth Key Management (AKM) Suite Count: 1
            Auth Key Management (AKM) List 00:0f:ac (Ieee 802.11) PSK
                Auth Key Management (AKM) Suite: 00:0f:ac (Ieee 802.11) PSK
                    Auth Key Management (AKM) OUI: 00:0f:ac (Ieee 802.11)
                    Auth Key Management (AKM) type: PSK (2)
            RSN Capabilities: 0x0000

в информационном теге RSN нас интересуют 2 поля (будущие 4 байта): Auth Key Management (AKM) OUI: 00: 0f: ac (Ieee 802.11) и Auth Key Management (AKM) type: PSK (2).

в зависимости от (AKM) type: PSK (2) или (AKM) type: WPA (1) это будет WPA2 или WPA1 соответственно

Второй:

Tag: Vendor Specific: Microsoft Corp.: WPA Information Element
            Tag Number: Vendor Specific (221)
            Tag length: 22
            OUI: 00:50:f2 (Microsoft Corp.)
            Vendor Specific OUI Type: 1
            Type: WPA Information Element (0x01)
            WPA Version: 1
            Multicast Cipher Suite: 00:50:f2 (Microsoft Corp.) AES (CCM)
                Multicast Cipher Suite OUI: 00:50:f2 (Microsoft Corp.)
                Multicast Cipher Suite type: AES (CCM) (4)
            Unicast Cipher Suite Count: 1
            Unicast Cipher Suite List 00:50:f2 (Microsoft Corp.) AES (CCM)
                Unicast Cipher Suite: 00:50:f2 (Microsoft Corp.) AES (CCM)
                    Unicast Cipher Suite OUI: 00:50:f2 (Microsoft Corp.)
                    Unicast Cipher Suite type: AES (CCM) (4)
            Auth Key Management (AKM) Suite Count: 1
            Auth Key Management (AKM) List 00:50:f2 (Microsoft Corp.) PSK
                Auth Key Management (AKM) Suite: 00:50:f2 (Microsoft Corp.) PSK
                    Auth Key Management (AKM) OUI: 00:50:f2 (Microsoft Corp.)
                    Auth Key Management (AKM) type: PSK (2)

Этот указывает нам на WPA1 WPA2. Вот фрагмент, как мы можем справиться с этим.

if (header_type == VENDOR_TAG_ID) {
        long long int oui = 0;
        memcpy(&oui,
               (uint8_t *)((nla_data(bss[NL80211_BSS_BEACON_IES])) -
                           header_len + i),
               6);
        if (oui == WPA1_WPA2_BEACON) wlan_info.bss_wpa1_wpa2 = 1;
      } else if (header_type == RSN_TAG_ID) {
        int32_t oui = 0;
        memcpy(&oui,
               (uint8_t *)((nla_data(bss[NL80211_BSS_BEACON_IES])) - 6 + i), 4);
        if ((oui == WPA2_BEACON_1) || (oui == WPA2_BEACON_2))
          wlan_info.bss_wpa2 = 1;
        else if (oui == WPA1_BEACON)
          wlan_info.bss_wpa1 = 1;
      }

И используемый здесь определяет:

#define RSN_TAG_ID 0x30
#define VENDOR_TAG_ID 0xdd
#define BEACON_DATA_LEN 0x100
#define BSS_SSID_LEN BEACON_DATA_LEN
#define WPA1_BEACON 0x1AC0F00
#define WPA2_BEACON_1 0x2AC0F00
#define WPA2_BEACON_2 0x4AC0F00
#define WPA1_WPA2_BEACON 0x101F25000

Еще одним интересным моментом является ядро iw. impl
Посмотрите здесь Это уже готовая функция, но я не изучал, как она работает.

void print_ies(unsigned char *ie, int ielen, bool unknown,
           enum print_ie_type ptype)
{
    struct print_ies_data ie_buffer = {
        .ie = ie,
        .ielen = ielen };

    if (ie == NULL || ielen < 0)
        return;

    while (ielen >= 2 && ielen - 2 >= ie[1]) {
        if (ie[0] < ARRAY_SIZE(ieprinters) &&
            ieprinters[ie[0]].name &&
            ieprinters[ie[0]].flags & BIT(ptype)) {
            print_ie(&ieprinters[ie[0]],
                 ie[0], ie[1], ie + 2, &ie_buffer);
        } else if (ie[0] == 221 /* vendor */) {
            print_vendor(ie[1], ie + 2, unknown, ptype);
        } else if (ie[0] == 255 /* extension */) {
            print_extension(ie[1], ie + 2, unknown, ptype);
        } else if (unknown) {
            int i;

            printf("\tUnknown IE (%d):", ie[0]);
            for (i=0; i<ie[1]; i++)
                printf(" %.2x", ie[2+i]);
            printf("\n");
        }
        ielen -= ie[1] + 2;
        ie += ie[1] + 2;
    }
}

И последний пункт — это атрибуты группы attr. В отличие от групповых атрибутов bss, они применяются к wiphy структурам
Я не достаточно изучил это, чтобы понять, как сетевой менеджер извлекает из него необходимую информацию о сетях, но вы можете попробовать посмотреть linbl и netlink источники, и, вероятно, информация об этом будет. Также вот один пример их использования:
репозиторий
исходный файл
Значения перечисления для ключей безопасности:

/**
 * NMDeviceWifiCapabilities:
 * @NM_WIFI_DEVICE_CAP_NONE: device has no encryption/authentication capabilities
 * @NM_WIFI_DEVICE_CAP_CIPHER_WEP40: device supports 40/64-bit WEP encryption
 * @NM_WIFI_DEVICE_CAP_CIPHER_WEP104: device supports 104/128-bit WEP encryption
 * @NM_WIFI_DEVICE_CAP_CIPHER_TKIP: device supports TKIP encryption
 * @NM_WIFI_DEVICE_CAP_CIPHER_CCMP: device supports AES/CCMP encryption
 * @NM_WIFI_DEVICE_CAP_WPA: device supports WPA1 authentication
 * @NM_WIFI_DEVICE_CAP_RSN: device supports WPA2/RSN authentication
 * @NM_WIFI_DEVICE_CAP_AP: device supports Access Point mode
 *
 * 802.11 specific device encryption and authentication capabilities.
 **/
typedef enum {
    NM_WIFI_DEVICE_CAP_NONE          = 0x00000000,
    NM_WIFI_DEVICE_CAP_CIPHER_WEP40  = 0x00000001,
    NM_WIFI_DEVICE_CAP_CIPHER_WEP104 = 0x00000002,
    NM_WIFI_DEVICE_CAP_CIPHER_TKIP   = 0x00000004,
    NM_WIFI_DEVICE_CAP_CIPHER_CCMP   = 0x00000008,
    NM_WIFI_DEVICE_CAP_WPA           = 0x00000010,
    NM_WIFI_DEVICE_CAP_RSN           = 0x00000020,
    NM_WIFI_DEVICE_CAP_AP            = 0x00000040
} NMDeviceWifiCapabilities;

И способы его использования:
источник файл

if (tb[NL80211_ATTR_CIPHER_SUITES]) {
    int num;
    int i;
    __u32 *ciphers = nla_data (tb[NL80211_ATTR_CIPHER_SUITES]);

    num = nla_len (tb[NL80211_ATTR_CIPHER_SUITES]) / sizeof(__u32);
    for (i = 0; i < num; i++) {
        switch (ciphers[i]) {
        case 0x000fac01:
            info->caps |= NM_WIFI_DEVICE_CAP_CIPHER_WEP40;
            break;
        case 0x000fac05:
            info->caps |= NM_WIFI_DEVICE_CAP_CIPHER_WEP104;
            break;
        case 0x000fac02:
            info->caps |= NM_WIFI_DEVICE_CAP_CIPHER_TKIP |
                      NM_WIFI_DEVICE_CAP_WPA;
            break;
        case 0x000fac04:
            info->caps |= NM_WIFI_DEVICE_CAP_CIPHER_CCMP |
                      NM_WIFI_DEVICE_CAP_RSN;
            break;
        default:
            nm_log_err (LOGD_HW | LOGD_WIFI, "Don't know the meaning of NL80211_ATTR_CIPHER_SUITES %#8.8x.", ciphers[i]);
            break;
        }
    }
}

и используемая там цепочка вызовов и обратных вызовов:

     wifi_utils_init (const char *iface, int ifindex, gboolean check_scan)
                                  ^
                                  ||
             wifi_nl80211_init (const char *iface, int ifindex)
                                   ^
                                  ||
    static int nl80211_wiphy_info_handler (struct nl_msg *msg, void *arg)

WPA 3 EDIT:
Пока ничего не могу сказать. Мои поиски начались с эта страница и далее по страницам, на которые есть ссылка.
nmcli Вероятно, не поддерживает WPA 3, так как последний коммит, судя по репозиторию, был 9 лет назад (А WPA 3 был введен from 802.11ax стандарт, который вышел, если не ошибаюсь, всего два года назад ).
Если у вас есть точка доступа с шифрованием WPA 3, это легко проверить с помощью команды nmcli dev wifi. В отличие от nmcli, последний коммит в репозитории iw был относительно недавним и, соответственно, он может уже обрабатывать наш случай.
Также ничего не могу сказать о содержании пакетов из репозитория wireshark с шифрованием WPA 3, т.к. нет нужной точки доступа и соответственно не проверял.

person plzvtl    schedule 25.03.2021
comment
Похоже, что многое нужно узнать о key_mgmt. Есть ли какой-либо набор данных, который можно сопоставить со значениями, которые могут дать нам типы безопасности, поскольку сейчас WPA 3 также находится в разработке?? Кстати, спасибо за чудовищные подробности. @plzvtl - person iambhaskaranand; 28.04.2021
comment
@iambhaskaranand отредактировал мои предположения. - person plzvtl; 28.04.2021
comment
также wpa_supplicant пока не поддерживает WPA 3. - person iambhaskaranand; 28.04.2021