Difference between revisions of "Wireshark TLS"

From UVOO Tech Wiki
Jump to navigation Jump to search
 
(2 intermediate revisions by the same user not shown)
Line 1: Line 1:
 +
tshark -l -i any -f 'port 443' -Y "ssl.handshake.ciphersuites" -Vx
 +
 +
tshark -i wlan1mon -l -T fields -e wlan.bssid -e wlan.ssid -e radiotap.dbm_antsignal -Y 'wlan.ssid' | grep -v "ff:ff:ff"
 +
 +
Maybe -e wlan.rsn.pcs.type and -e wlan.rsn.gcs.type are what you're looking for? Those are for the Pairwise Cipher Suite type" and "Group Cipher Suite type", respectively.
 +
https://stackoverflow.com/questions/47645051/display-network-encryption-type-in-tshark
 +
 +
 +
https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-4
 +
 +
 
```
 
```
 
Client Hello:
 
Client Hello:
Line 47: Line 58:
 
20 Finished
 
20 Finished
 
```
 
```
 +
 +
 +
{code}
 +
#include <tins/tins.h>
 +
 +
#include <algorithm>
 +
#include <iostream>
 +
#include <map>
 +
#include <string>
 +
 +
using namespace Tins;
 +
using namespace std;
 +
 +
 +
/*
 +
* Container class for the data that is retrieved from the beacon.
 +
*/
 +
class Unit {
 +
public:
 +
    /*
 +
    * Constructor. Parses the Dot11Beacon object and takes all the necessary
 +
    * data from it.
 +
    */
 +
    Unit(Dot11Beacon& beacon);
 +
    Unit() = default;
 +
    unsigned getCount();
 +
    void incrementCount();
 +
 +
    /*
 +
    * Prints this object onto the command line, in CSV format
 +
    */
 +
    void print();
 +
 +
private:
 +
    string ssid;
 +
    string bssid;
 +
    unsigned channel;
 +
    unsigned count;
 +
 +
    string gcs; // Group Cipher Suite
 +
    string pcs; // Pairwise Cipher Suite
 +
    string akm; // Authentication suite
 +
 +
    /*
 +
    * Returns a string representation of a RSNInformation::CypherSuites enum value
 +
    */
 +
    string type_to_string(const RSNInformation::CypherSuites& type);
 +
 +
    /*
 +
    * Returns a string representation of a RSNInformation::AKMSuites enum value
 +
    */
 +
    string type_to_string(const RSNInformation::AKMSuites& type);
 +
};
 +
 +
Unit::Unit(Dot11Beacon& beacon) :
 +
    count {1} /* When this unit is created, it has been seen exactly once */ {
 +
    ssid = beacon.ssid();
 +
    bssid = beacon.addr3().to_string();
 +
    channel = unsigned(beacon.ds_parameter_set());
 +
 +
    RSNInformation rsn;
 +
    for(const auto &opt : beacon.options()) {
 +
        if (opt.option() == Dot11::RSN) {
 +
            rsn = beacon.rsn_information();
 +
 +
            // Put all authentication suite types in a string
 +
            const RSNInformation::akm_type& akmTypeList = rsn.akm_cyphers();
 +
            for (const auto& akmIt : akmTypeList) {
 +
                if (akm.size() == 0)
 +
                    akm += type_to_string(akmIt);
 +
                else
 +
                    akm += ";" + type_to_string(akmIt);
 +
            }
 +
 +
            // Put all group cipher types in a string
 +
            const RSNInformation::CypherSuites& gcsType = rsn.group_suite();
 +
            gcs = type_to_string(gcsType);
 +
 +
 +
            // Put all pairwise ciphers in a string
 +
            const RSNInformation::cyphers_type& pcsTypeList = rsn.pairwise_cyphers();
 +
            for (const auto& pcsIt : pcsTypeList) {
 +
                if (pcs.size() == 0)
 +
                    pcs += type_to_string(pcsIt);
 +
                else
 +
                    pcs += ";" + type_to_string(pcsIt);
 +
            }
 +
        }
 +
    }
 +
}
 +
 +
unsigned Unit::getCount() {
 +
    return count;
 +
}
 +
 +
void Unit::incrementCount() {
 +
    count += 1;
 +
}
 +
 +
void Unit::print() {
 +
    string ssid_to_print;
 +
    if (ssid.length() == 0) {
 +
        ssid_to_print = "<ZERO_LENGTH>";
 +
    } else if (!isprint(ssid[0])) {
 +
        ssid_to_print = to_string(static_cast<int>(ssid[0]));
 +
    } else {
 +
        ssid_to_print = ssid;
 +
    }
 +
    if (find(ssid_to_print.begin(), ssid_to_print.end(), ',') != ssid_to_print.end()) {
 +
        ssid_to_print = "\"" + ssid_to_print + "\"";
 +
    }
 +
    cout <<  ssid_to_print << ","
 +
        << bssid << ","
 +
        << to_string(channel) << ","
 +
        << to_string(count) << ","
 +
        << gcs << ","
 +
        << pcs << ","
 +
        << akm << endl;
 +
}
 +
 +
string Unit::type_to_string(const RSNInformation::CypherSuites& type) {
 +
    switch (type) {
 +
    case RSNInformation::CypherSuites::CCMP:
 +
        return "CCMP";
 +
        break;
 +
    case RSNInformation::CypherSuites::TKIP:
 +
        return "TKIP";
 +
        break;
 +
    case RSNInformation::CypherSuites::WEP_104:
 +
        return "WEP_104";
 +
        break;
 +
    case RSNInformation::CypherSuites::WEP_40:
 +
        return "WEP_40";
 +
        break;
 +
    }
 +
}
 +
 +
string Unit::type_to_string(const RSNInformation::AKMSuites& type) {
 +
    switch (type) {
 +
    case RSNInformation::AKMSuites::PMKSA:
 +
        return "PMKSA";
 +
        break;
 +
    case RSNInformation::AKMSuites::PSK:
 +
        return "PSK";
 +
        break;
 +
    }
 +
}
 +
 +
/*
 +
* Class that reads the pcap, keeps track of the units and writes out one
 +
* beacon frame in pcap format for each unique AP it finds. This file is called
 +
* "unique_beacons.pcap"
 +
*/
 +
class PCAPParser {
 +
public:
 +
    /*
 +
    * Constructor. It takes the exact parameters that it will pas on to its
 +
    * FileSniffer object (a FileSniffer is actually just a file reader).
 +
    */
 +
    PCAPParser(const string& pcapFilename, const string& filter);
 +
 +
    /*
 +
    * Start reading the file.
 +
    */
 +
    bool run();
 +
 +
    /*
 +
    * Print CSV header and ask all of our collected Unit objects to print themselves
 +
    */
 +
    void print();
 +
 +
private:
 +
    FileSniffer sniffer;
 +
    PacketWriter writer;
 +
    map<string, Unit> apMap; // stands for Access Point Map
 +
 +
    bool handler(PDU&);
 +
};
 +
 +
PCAPParser::PCAPParser(const string& pcapFilename, const string& filter) :
 +
    sniffer {pcapFilename, filter},
 +
    writer {"unique_beacons.pcap", PacketWriter::RADIOTAP}  {
 +
    for (auto it = apMap.begin(); it != apMap.end(); it++) {
 +
        it->second.print();
 +
    }
 +
}
 +
 +
bool PCAPParser::run() {
 +
    sniffer.sniff_loop( [this] (PDU& pdu) { return (bool) this->handler (pdu); } );
 +
    return true;
 +
}
 +
 +
bool PCAPParser::handler(PDU& pdu) {
 +
    Dot11Beacon& beacon = pdu.rfind_pdu<Dot11Beacon>();
 +
 +
    // An ESSID may span multiple BSSID's. Also, it's nice to keep track of what
 +
    // channels an AP has been on. Therefore, the combination of SSID, BSSID and
 +
    // channel is considered key.
 +
    const string& ssid = beacon.ssid();
 +
    const string& mac = beacon.addr3().to_string();
 +
    const unsigned channel = unsigned(beacon.ds_parameter_set());
 +
    const string key = ssid + mac + to_string(channel);
 +
    if (apMap.find(key) == apMap.end()) { // we've got a new one
 +
        Unit unit(beacon);
 +
        apMap[key] = unit;
 +
        writer.write(pdu);
 +
    } else {
 +
        apMap[key].incrementCount();
 +
    }
 +
    return true;
 +
}
 +
 +
void PCAPParser::print() {
 +
    // Print the headers for the CSV output
 +
    cout << "SSID,BSSID,Current_channel,Count,Group_Cipher,Pairwise_Ciphers,Authentication_Suite" << endl;
 +
 +
    // Ask each of the units to print themselves for the CSV output
 +
    for (auto it = apMap.begin(); it != apMap.end(); it++) {
 +
        it->second.print();
 +
    }
 +
}
 +
 +
int main(int argc, char *argv[]) {
 +
    if(argc != 2) {
 +
        std::cout << "Usage: " << *argv << " <PCAP_FILE>\n";
 +
        return 1;
 +
    }
 +
 +
    PCAPParser pcapParser(argv[1], "wlan type mgt subtype beacon");
 +
    pcapParser.run();
 +
    pcapParser.print();
 +
}
 +
 +
{code}

Latest revision as of 03:20, 1 March 2022

tshark -l -i any -f 'port 443' -Y "ssl.handshake.ciphersuites" -Vx

tshark -i wlan1mon -l -T fields -e wlan.bssid -e wlan.ssid -e radiotap.dbm_antsignal -Y 'wlan.ssid' | grep -v "ff:ff:ff"

Maybe -e wlan.rsn.pcs.type and -e wlan.rsn.gcs.type are what you're looking for? Those are for the Pairwise Cipher Suite type" and "Group Cipher Suite type", respectively. https://stackoverflow.com/questions/47645051/display-network-encryption-type-in-tshark

https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-4

Client Hello:

ssl.handshake.type == 1

Server Hello:

ssl.handshake.type == 2

NewSessionTicket:

ssl.handshake.type == 4

Certificate:

ssl.handshake.type == 11

CertificateRequest

ssl.handshake.type == 13

ServerHelloDone:

ssl.handshake.type == 14

Note: “ServerHellpDone” means full-handshake TLS session.

Cipher Suites:

ssl.handshake.ciphersuite

TLS handshake message types

Message types
Code    Description
0   HelloRequest
1   ClientHello
2   ServerHello
4   NewSessionTicket
8   EncryptedExtensions (TLS 1.3 only)
11  Certificate
12  ServerKeyExchange
13  CertificateRequest
14  ServerHelloDone
15  CertificateVerify
16  ClientKeyExchange
20  Finished

{code}

include <tins/tins.h>

include

include

include

include

using namespace Tins; using namespace std;

/*

* Container class for the data that is retrieved from the beacon.
/

class Unit { public:

   /
    * Constructor. Parses the Dot11Beacon object and takes all the necessary
    * data from it.
    */
   Unit(Dot11Beacon& beacon);
   Unit() = default;
   unsigned getCount();
   void incrementCount();
/*
 * Prints this object onto the command line, in CSV format
 */
void print();

private:

   string ssid;
   string bssid;
   unsigned channel;
   unsigned count;
string gcs; // Group Cipher Suite
string pcs; // Pairwise Cipher Suite
string akm; // Authentication suite

/*
 * Returns a string representation of a RSNInformation::CypherSuites enum value
 */
string type_to_string(const RSNInformation::CypherSuites& type);

/*
 * Returns a string representation of a RSNInformation::AKMSuites enum value
 */
string type_to_string(const RSNInformation::AKMSuites& type);

};

Unit::Unit(Dot11Beacon& beacon) :

   count {1} /* When this unit is created, it has been seen exactly once */ {
   ssid = beacon.ssid();
   bssid = beacon.addr3().to_string();
   channel = unsigned(beacon.ds_parameter_set());
RSNInformation rsn;
for(const auto &opt : beacon.options()) {
    if (opt.option() == Dot11::RSN) {
        rsn = beacon.rsn_information();

        // Put all authentication suite types in a string
        const RSNInformation::akm_type& akmTypeList = rsn.akm_cyphers();
        for (const auto& akmIt : akmTypeList) {
            if (akm.size() == 0)
                akm += type_to_string(akmIt);
            else
                akm += ";" + type_to_string(akmIt);
        }

        // Put all group cipher types in a string
        const RSNInformation::CypherSuites& gcsType = rsn.group_suite();
        gcs = type_to_string(gcsType);


        // Put all pairwise ciphers in a string
        const RSNInformation::cyphers_type& pcsTypeList = rsn.pairwise_cyphers();
        for (const auto& pcsIt : pcsTypeList) {
            if (pcs.size() == 0)
                pcs += type_to_string(pcsIt);
            else
                pcs += ";" + type_to_string(pcsIt);
        }
    }
}

}

unsigned Unit::getCount() {

   return count;

}

void Unit::incrementCount() {

   count += 1;

}

void Unit::print() {

   string ssid_to_print;
   if (ssid.length() == 0) {
       ssid_to_print = "";
   } else if (!isprint(ssid[0])) {
       ssid_to_print = to_string(static_cast(ssid[0]));
   } else {
       ssid_to_print = ssid;
   }
   if (find(ssid_to_print.begin(), ssid_to_print.end(), ',') != ssid_to_print.end()) {
       ssid_to_print = "\"" + ssid_to_print + "\"";
   }
   cout <<  ssid_to_print << ","
        << bssid << ","
        << to_string(channel) << ","
        << to_string(count) << ","
        << gcs << ","
        << pcs << ","
        << akm << endl;

}

string Unit::type_to_string(const RSNInformation::CypherSuites& type) {

   switch (type) {
   case RSNInformation::CypherSuites::CCMP:
       return "CCMP";
       break;
   case RSNInformation::CypherSuites::TKIP:
       return "TKIP";
       break;
   case RSNInformation::CypherSuites::WEP_104:
       return "WEP_104";
       break;
   case RSNInformation::CypherSuites::WEP_40:
       return "WEP_40";
       break;
   }

}

string Unit::type_to_string(const RSNInformation::AKMSuites& type) {

   switch (type) {
   case RSNInformation::AKMSuites::PMKSA:
       return "PMKSA";
       break;
   case RSNInformation::AKMSuites::PSK:
       return "PSK";
       break;
   }

}

/*

* Class that reads the pcap, keeps track of the units and writes out one
* beacon frame in pcap format for each unique AP it finds. This file is called
* "unique_beacons.pcap"
/

class PCAPParser { public:

   /
    * Constructor. It takes the exact parameters that it will pas on to its
    * FileSniffer object (a FileSniffer is actually just a file reader).
    */
   PCAPParser(const string& pcapFilename, const string& filter);
/*
 * Start reading the file.
 */
bool run();

/*
 * Print CSV header and ask all of our collected Unit objects to print themselves
 */
void print();

private:

   FileSniffer sniffer;
   PacketWriter writer;
   map<string, Unit> apMap; // stands for Access Point Map
bool handler(PDU&);

};

PCAPParser::PCAPParser(const string& pcapFilename, const string& filter) :

   sniffer {pcapFilename, filter},
   writer {"unique_beacons.pcap", PacketWriter::RADIOTAP}  {
   for (auto it = apMap.begin(); it != apMap.end(); it++) {
       it->second.print();
   }

}

bool PCAPParser::run() {

   sniffer.sniff_loop( [this] (PDU& pdu) { return (bool) this->handler (pdu); } );
   return true;

}

bool PCAPParser::handler(PDU& pdu) {

   Dot11Beacon& beacon = pdu.rfind_pdu();
// An ESSID may span multiple BSSID's. Also, it's nice to keep track of what
// channels an AP has been on. Therefore, the combination of SSID, BSSID and
// channel is considered key.
const string& ssid = beacon.ssid();
const string& mac = beacon.addr3().to_string();
const unsigned channel = unsigned(beacon.ds_parameter_set());
const string key = ssid + mac + to_string(channel);
if (apMap.find(key) == apMap.end()) { // we've got a new one
    Unit unit(beacon);
    apMap[key] = unit;
    writer.write(pdu);
} else {
    apMap[key].incrementCount();
}
return true;

}

void PCAPParser::print() {

   // Print the headers for the CSV output
   cout << "SSID,BSSID,Current_channel,Count,Group_Cipher,Pairwise_Ciphers,Authentication_Suite" << endl;
// Ask each of the units to print themselves for the CSV output
for (auto it = apMap.begin(); it != apMap.end(); it++) {
    it->second.print();
}

}

int main(int argc, char *argv[]) {

   if(argc != 2) {
       std::cout << "Usage: " << *argv << " \n";
       return 1;
   }
PCAPParser pcapParser(argv[1], "wlan type mgt subtype beacon");
pcapParser.run();
pcapParser.print();

}

{code}