diff --git a/tables/wifi_network/BUILD.bazel b/tables/wifi_network/BUILD.bazel index cd2045a..0e70de9 100644 --- a/tables/wifi_network/BUILD.bazel +++ b/tables/wifi_network/BUILD.bazel @@ -16,6 +16,7 @@ go_test( name = "wifi_network_test", srcs = ["wifi_network_test.go"], embed = [":wifi_network"], + embedsrcs = ["wdutil_out.txt"], deps = [ "@com_github_osquery_osquery_go//plugin/table", "@com_github_stretchr_testify//assert", diff --git a/tables/wifi_network/wdutil_out.txt b/tables/wifi_network/wdutil_out.txt new file mode 100644 index 0000000..28cf2c2 --- /dev/null +++ b/tables/wifi_network/wdutil_out.txt @@ -0,0 +1,88 @@ +———————————————————————————————————————————————————————————————————— +NETWORK +———————————————————————————————————————————————————————————————————— + Primary IPv4 : en0 ((null) / gpd.pan) + : 192.168.1.1 + Primary IPv6 : en0 (Wi-Fi / 8FE3682E-51CE-450A-9A7D-B2A02AA407F2) + : 2001:0db8:85a3:0000:0000:8a2e:0370:7334 + : 2001:0db8:85a3:0000:0000:8a2e:0370:7334 + : 2001:0db8:85a3:0000:0000:8a2e:0370:7334 + : 2001:0db8:85a3:0000:0000:8a2e:0370:7334 + : 2001:0db8:85a3:0000:0000:8a2e:0370:7334 + DNS Addresses : 8.8.8.8 + Apple : Reachable +———————————————————————————————————————————————————————————————————— +WIFI +———————————————————————————————————————————————————————————————————— + MAC Address : (hw=) + Interface Name : en0 + Power : On [On] + Op Mode : STA + SSID : + BSSID : + RSSI : -34 dBm + Noise : -92 dBm + Tx Rate : 2401.0 Mbps + Security : WPA3 Personal + PHY Mode : 11ax + MCS Index : 11 + Guard Interval : 800 + NSS : 2 + Channel : 6g101 (160 MHz, Active) + Country Code : US + Scan Cache Count : 31 + NetworkServiceID : 9A0B692D-C462-4771-982E-65EC1C2B28F8 + IPv4 Config Method : DHCP + IPv4 Address : 192.168.1.34 + IPv4 Router : 192.168.1.1 + IPv6 Config Method : Automatic + IPv6 Address : 2001:0db8:85a3:0000:0000:8a2e:0370:7334 + : 2001:0db8:85a3:0000:0000:8a2e:0370:7334 + : 2001:0db8:85a3:0000:0000:8a2e:0370:7334 + : 2001:0db8:85a3:0000:0000:8a2e:0370:7334 + : 2001:0db8:85a3:0000:0000:8a2e:0370:7334 + IPv6 Router : fd12:3456:789a:1::1 + DNS : 192.168.1.1 + BTC Mode : Off + Desense : + Chain Ack : [] + BTC Profile 2.4GHz : Disabled + BTC Profile 5GHz : Disabled +———————————————————————————————————————————————————————————————————— +BLUETOOTH +———————————————————————————————————————————————————————————————————— + Power : On + Address : 00:16:3E:28:52:1A + Discoverable : No + Connectable : No + Scanning : No + Devices : 10 (paired=10 cloud=0 connected=0) + + Office + Address : 40-ab-cd-12-e3-4f + Paired : Yes + CloudPaired : No + Connected : No + +———————————————————————————————————————————————————————————————————— +AWDL +———————————————————————————————————————————————————————————————————— + AirDrop Disc Mode : Everyone + AWDL Enabled : No + Interface Name : awdl0 + Power : On + IPv6 Address : fd12:3456:789a:1::1 + Schedule State : n/a + Channel Sequence : n/a + Op Mode : n/a + Real Time Mode : No + Sync State : n/a + Sync Params : n/a + Master Channel : n/a + Election Params : n/a +———————————————————————————————————————————————————————————————————— +POWER +———————————————————————————————————————————————————————————————————— + Power Source : AC + Battery Warning Level: None + System Caps : FullWake:cpu disk net aud vid \ No newline at end of file diff --git a/tables/wifi_network/wifi_network.go b/tables/wifi_network/wifi_network.go index f0e0864..ee99f85 100644 --- a/tables/wifi_network/wifi_network.go +++ b/tables/wifi_network/wifi_network.go @@ -1,6 +1,7 @@ package wifi_network import ( + "bufio" "context" "os" "os/exec" @@ -117,6 +118,45 @@ func getWifiNetworkName(cmdExecutor CommandExecutor, wifiInterface string) (stri return strings.TrimSpace(splitOut[1]), nil } +func getSecurityLevel(cmdExecutor CommandExecutor, interfaceName string) (string, error) { + out, err := getWdutilOutput(cmdExecutor) + if err != nil { + return "", err + } + + return extractSecurityValue(out, interfaceName), nil +} + +func getWdutilOutput(cmdExecutor CommandExecutor) (string, error) { + out, err := cmdExecutor.ExecCommand("/usr/bin/wdutil", "info", "-q") + if err != nil { + return "", errors.Wrap(err, "failed to run wdutil") + } + return string(out), nil +} + +func extractSecurityValue(input string, desiredInterfaceName string) string { + scanner := bufio.NewScanner(strings.NewReader(input)) + interfaceName := "" + for scanner.Scan() { + line := scanner.Text() + if strings.Contains(line, "Interface Name") { + parts := strings.Split(line, ":") + if len(parts) > 1 { + interfaceName = strings.TrimSpace(parts[1]) + } + } + if strings.Contains(line, "Security") && interfaceName == desiredInterfaceName { + parts := strings.Split(line, ":") + if len(parts) > 1 { + return strings.TrimSpace(parts[1]) + } + } + } + + return "" +} + // buildWifiNetwork func buildWifiNetworkFromResponse(cmdExecutor CommandExecutor, wifiStatus map[string]string) (*WifiNetwork, error) { wifiInterface, err := getValueFromResponse(wifiStatus, "interface") @@ -154,18 +194,19 @@ func buildWifiNetworkFromResponse(cmdExecutor CommandExecutor, wifiStatus map[st return nil, err } - securityType, err := getValueFromResponse(wifiStatus, "security_type") + mode, err := getValueFromResponse(wifiStatus, "mode") if err != nil { return nil, err } - mode, err := getValueFromResponse(wifiStatus, "mode") + // get the wifi network name + wifiNetworkName, err := getWifiNetworkName(cmdExecutor, wifiInterface) if err != nil { return nil, err } - // get the wifi network name - wifiNetworkName, err := getWifiNetworkName(cmdExecutor, wifiInterface) + // get the security level + securityType, err := getSecurityLevel(cmdExecutor, wifiInterface) if err != nil { return nil, err } diff --git a/tables/wifi_network/wifi_network_test.go b/tables/wifi_network/wifi_network_test.go index 0966d75..2400ac1 100644 --- a/tables/wifi_network/wifi_network_test.go +++ b/tables/wifi_network/wifi_network_test.go @@ -2,12 +2,18 @@ package wifi_network import ( "errors" + "fmt" "testing" "github.com/osquery/osquery-go/plugin/table" "github.com/stretchr/testify/assert" + + _ "embed" ) +//go:embed wdutil_out.txt +var wdutilOut []byte + type MockOsqueryClient struct{} func (m MockOsqueryClient) QueryRow(query string) (map[string]string, error) { @@ -19,9 +25,14 @@ func (m MockOsqueryClient) Close() {} type MockCommandExecutor struct{} func (m MockCommandExecutor) ExecCommand(name string, args ...string) ([]byte, error) { + fmt.Println(args) if args[1] == "en0" { return []byte("Current Wi-Fi Network: MyNetwork"), nil } + // /usr/bin/wdutil info -q + if args[0] == "info" { + return wdutilOut, nil + } return nil, errors.New("commad failed") } @@ -130,7 +141,7 @@ func TestBuildWifiNetworkFromResponse(t *testing.T) { "channel_width": "20", "channel_band": "2.4 GHz", "transmit_rate": "300 Mbps", - "security_type": "WPA2 Personal", + "security_type": "", "mode": "Station", }, &WifiNetwork{ @@ -142,7 +153,7 @@ func TestBuildWifiNetworkFromResponse(t *testing.T) { ChannelWidth: "20", ChannelBand: "2.4 GHz", TransmitRate: "300 Mbps", - SecurityType: "WPA2 Personal", + SecurityType: "WPA3 Personal", Mode: "Station", }, false, @@ -222,3 +233,27 @@ func TestBuildWifiNetworkResults(t *testing.T) { }) } } + +func TestGetWdutilOutput(t *testing.T) { + t.Log(wdutilOut) + mockCmdExecutor := MockCommandExecutor{} + result, err := getWdutilOutput(mockCmdExecutor) + assert.NoError(t, err) + t.Logf("Result: %s", result) + assert.NotEmpty(t, result) +} + +func TestExtractSecurityValue(t *testing.T) { + expectedOutput := "WPA3 Personal" + + output := extractSecurityValue(string(wdutilOut), "en0") + + assert.Equal(t, expectedOutput, output) +} + +func TestGetSecurityLevel(t *testing.T) { + mockCmdExecutor := MockCommandExecutor{} + result, err := getSecurityLevel(mockCmdExecutor, "en0") + assert.NoError(t, err) + assert.Equal(t, "WPA3 Personal", result) +}