• Smart lighting systems are supposed to make managing commercial buildings easier and more energy efficient. MaxLite’s c-Max system (as well as others that seem to rebrand the same technology), sell a Bluetooth mesh solution for commerical lighting, lets facility managers control lighting networks using a smartphone app and QR codes. However, a closer look at how these QR codes are generated reveals a security oversight. Below is an exerpt from the setup guide:

    The primary issue is when you decode each of these setup keys when generated from the app or even from as listed in documentation the result is the same. The User QR Code when decoded using a QR code reader is 1&%@3&%@AP7SIKUDGElGnIXHB and the Admin QR Code is 0&%@3&%@AP7SIKUDGElGnIXHB such that the only difference is the first digit.

    In short: the system’s “restricted control” passes can be easily transformed into “master keys” with a single, simple change.

    The Digital “Master Key” Problem

    When setting up the c-Max system, administrators generate QR codes to give other people access. There are two main levels:

    • Admin: Full control over the entire network (schedules, zones, settings).
    • User: Limited control (usually just turning local lights on or off).

    Imagine a hotel where a standard room key has a “1” written on it, and the master key for the whole building has a “0.” If an attacker realizes this, they can just cross out the “1,” write a “0,” and suddenly have access to every room.

    That is exactly how the c-Max app works.

    The QR Code Breakdown

    When reviewed the c-Max management app (basic technical breakdown here), it was found that the QR codes are not unique and are deterministic from based on the MeshQRCode structure serialized via Gson in the app, from the following Fields: 

    index

    meshName

    pinData

    pinName

    lights

    devices

    highPermission

    So if you have deployed this system be aware of issuing out “User” level codes or making the code generally available may not be good practice.

  • The Core Problem: User-Bound Identity vs. Application Integration

    When evaluating SaaS API integrations, enterprise platforms generally fall into two categories: “all-or-nothing” monolithic keys, or modern, fully granular Role-Based Access Control (RBAC) designed specifically for programmatic service principals. I am not saying I enjoy setting up least priviledge especialiy on a new integration that doesn’t have enough documentation or if you are building a custom integration and identifying the priviledge level.

    Cisco Meraki platforms occupy a unique mid-point that introduces a distinct engineering hurdle: API keys are strictly bound to individual user identities. As the official Meraki Dashboard API documentation explicitly states:

    “This API key will be associated with the dashboard administrator account which generates it and will inherit the same permissions as that account. You can generate, revoke, and regenerate your API key on your profile.

    This design decision introduces three immediate architectural drawbacks for enterprise environments:

    1. Inherited Over-Privilege: If a senior network engineer generates a personal API key to run an inventory script, that API key inherits full administrative rights across every organization and network that user has access to. If the key is compromised, the entire infrastructure is exposed. For a granular integration this may not work if you have multiple children groups in your organization and they need their individual integrations to work.
    2. Hard Limits on Scale: Meraki enforces a strict restriction: “Two API keys per user profile.” Once you generate two keys, the option is completely disabled. If you have three separate third-party tools (e.g., a monitoring system, a ticketing system, and a custom automation script), you literally cannot run them under a single user context.
    3. Personnel Churn Risks: If an administrator leaves the organization and their dashboard account is deleted or modified during the offboarding process, any critical business integrations relying on their personal API key instantly break.

    The Workaround: Implementing Programmatic “Service Accounts”

    Since Meraki lacks a native, distinct “API Service Principal” object for standard API keys, the architectural best practice is to abstract the API context entirely from real human users.

    You must treat the Meraki dashboard like an legacy Active Directory environment: Create dedicated, machine-specific administrator accounts.

    The Implementation Pattern:

    1. Provision an Email Alias: Create a scoped corporate email alias or distribution group specific to the integration (e.g., integrationname@yourdomain.com).
    2. Create the Dashboard Admin: Invite this email address as a new administrator under Organization > Configure > Administrators.
    3. Enforce Principle of Least Privilege: Do not grant this account organization-wide Read/Write access unless absolutely necessary. Scope the user account strictly to the required networks or target tags, using the lowest administrative role possible (e.g., Read-Only or Guest Ambassador depending on the automation task).
    4. Generate and Isolate the Key: Log into the dashboard via the new service account, navigate to My Profile or Organization > Configure > API & Webhooks, and generate the token
    5. Record your API Service accounts in your Enterprise IT Documentation Solution!

    The Benefits of This Approach

    Bypassing Key Limits: Each new service account identity gets its own allocation of two API keys, resolving the scalability bottleneck.

    Granular Audit Trails: The Meraki API Analytics dashboard logs requests by the specific administrator identity associated with the key. Using dedicated accounts lets you isolate and view exactly which application is making which calls.

    Blast Radius Mitigation: If the API key for your dev script leaks, the exposure is limited strictly to the minor scope assigned to that dummy account—not your entire multi-tenant or global corporate layout.

  • During a recent flight, I decided to take a closer look at the Bluetooth devices my phone could detect. Using the iOS app Bluetooth Inspector, I scanned my surroundings. While I don’t use every feature of the app, I find it incredibly useful for locating nearby devices. I’ve even used it to track down Bluetooth headphones that lack a “find my device” feature, relying on signal strength for guidance.

    On this particular trip, I was shocked to discover more than a thousand Bluetooth devices nearby. This made me reflect on my own gear and the sheer number of radios we carry daily. A pair of Bluetooth headphones alone can account for three radios (one per earbud and the case), not to mention other Bluetooth Low Energy (BLE) devices like AirTags and fitness trackers. With smartwatches and other connected gadgets becoming increasingly common, it’s not unusual for a single person to have ten or more Bluetooth-enabled devices on them, forming an intricate web of connectivity around us.

    .

  • Recently, I faced a challenge while trying to deploy a wireless profile from the Meraki Systems Manager MDM platform as I transitioned to Intune. Unfortunately, the deployment didn’t go as planned. Windows machines were either timing out after several failed attempts or failing to connect altogether when using the WPA (automatic) feature. Although the MDM successfully applied the wireless settings to Android, MacOS, and iOS devices, Windows continued to be problematic. The key challenge was inspecting the settings profile sent to the Windows machines. I noticed that the MDM wireless profile format was similar to the Netsh wlan profile export, but I needed to find a way to access this information on the Windows client. The breakthrough came with the use of SyncML Viewer, a tool designed for monitoring MDM transactions between clients and the MDM. By extracting a functional manual wireless profile configuration using Netsh and comparing it with the MDM’s deployment, I pinpointed the issue. Although SyncML Viewer displayed certain characters differently, a simple find-and-replace adjustment aligned everything accurately. Ultimately, I discovered that the root of the problem was the absence of a trusted certificate thumbprint in the wireless profile, which required me to submit a support ticket to the vendor. If you ever need detailed insights into MDM transactions, I highly recommend using SyncML Viewer.

    A screenshot showing a WLAN profile export in the SyncML Viewer, highlighting essential configuration settings and indicating the absence of a trusted certificate thumbprint.
    Visual comparison of WLAN profile export data in SyncML Viewer, highlighting essential configurations for troubleshooting MDM issues.
  •  

    This powershell script will get the HyperV Host server FQDN and save as a variable to input as the Location in the Location field of SNMP. Updates to the SNMP agent will require the agent to be restarted to take effect.

     

    $VMHost
    = (get-item
    “HKLM:\SOFTWARE\Microsoft\Virtual Machine\Guest\Parameters”).GetValue(“HostName”)

    $SNMPAgent
    =
    “HKLM:\SYSTEM\CurrentControlSet\services\SNMP\Parameters\RFC1156Agent”

    Set-ItemProperty
    -path
    $SNMPAgent
    -Name
    sysLocation
    -value
    $VMHost.ToString()

     

     

  • Until recently I was stumped trying to import the ACLs off my 8206 Procurve (Aruba) switch into HP IMC using the ACL Devices function. The error I would receive was an Unknown Error and a Failed last poll result.

     

    Ironically the issue was simple after trying to recreate the issue on another device. Once I moved an access-list that was named beginning with a number for example 879-in the ACL Management component would fail. By creating the same access-list on the Procurve as Vlan879-in the synchronization would turn to Succeeded.

    This isn’t an issue on H3C product because all ACLs are numbered and naming is just for convienence.

  • I recently came to the realization that I could be using the SQL backend systems of the different products I maintain to allow for additional insight into operations. As part of this I started to look at comparing my Whatsup Gold implementation with my HP IMC implementation. The systems fundamentally perform similar functions of management of the network but there is a basic difference WhatsUp Gold has the capability of taking a action as a result of a condition being met and IMC does not. Since I have been running two systems and periodically the two systems come out of sync with respect to whether a device is in one system or the other I took a look this morning and decided to start reporting against each database with respect to each other and came up with the query below. This query when used as a WhatsUp Gold Dynamic Group SQL query shows the devices that are listed in WhatsUp Gold but not in IMC.

    —————-

    SELECT DISTINCT WhatsUp15.dbo.Device.nDeviceID

     

     

    FROM

     

    WhatsUp15.dbo.MonitorState

    INNER JOIN WhatsUp15.dbo.Device ON WhatsUp15.dbo.MonitorState.nMonitorStateID = WhatsUp15.dbo.Device.nWorstStateID

    INNER JOIN WhatsUp15.dbo.DeviceType ON WhatsUp15.dbo.Device.nDeviceTypeID = WhatsUp15.dbo.DeviceType.nDeviceTypeID

    FULL OUTER JOIN WhatsUp15.dbo.NetworkInterface ON WhatsUp15.dbo.Device.nDefaultNetworkInterfaceID = WhatsUp15.dbo.NetworkInterface.nNetworkInterfaceID

    FULL OUTER JOIN config_db.imc_config.tbl_dev ON WhatsUp15.dbo.NetworkInterface.sNetworkAddress = config_db.imc_config.tbl_dev.dev_ip

     

     

    WHERE

    (NOT (WhatsUp15.dbo.NetworkInterface.sNetworkAddress = N’127.0.0.1′)) AND

    (config_db.imc_config.tbl_dev.dev_ip IS NULL) AND

    (NOT (WhatsUp15.dbo.MonitorState.nInternalMonitorState = 2)) AND

    (NOT (WhatsUp15.dbo.DeviceType.sDisplayName LIKE N’%Windows%’)) AND

    (WhatsUp15.dbo.NetworkInterface.bPollUsingNetworkName = 0)

     

     

     

    —————–

    This is based on my own environment with a shared SQL server and the IMC using config_db as a database and WhatsUp Gold using WhatsUp15 as a database. This could easily be accomplished by having linked servers in case of a split deployment.

    The where clauses at the bottom do the following:

    Statement 1: Ensure no loopback addresses are included

    Statement 2: Ensure that the device doesn’t exist in IMC

    Statement 3: Ensure the device is not in Maintenance mode in Whatsup Gold

    Statement 4: Remove all devices that are Windows based ( I don’t monitor these with IMC)

    Statement 5: Remove all devices that are polled using DNS name ( IMC doesn’t allow DNS resolution it only uses IP address once a device is created in the system)

     

    I have included a diagram of the tables used and their relationships:

     

     

  • One of the issues in documentation is being able to leverage existing data stored in management systems. A good example of this is in the HP IMC product it can use SQL as a backend which allows for data to be pulled out is you know how to formulate the queries. Below is a example of the query to export all the VLANs IMC is aware of using two SQL views. The first view is a custom query specific to your environment and requires knowing you core L3 routing devices so that you can generate a report of only those devices Layer 3 routing ports in my case this is the four switches that have the device id’s of 1153, 1174, 1179, and 1278 in the database config_db and table tbl_dev.

    —————————–

    CREATE
    VIEW [dbo].[vlaninfo_L3]

    AS

    SELECT
    TOP (100) PERCENT vlan.tbl_vlan_virtual_if_info.vlan_id, vlan.tbl_vlan_overall_vlan.vlan_name, config_db.imc_config.tbl_snmp_sysinfo.sys_name,

    vlan.tbl_vlan_virtual_if_info.ip_addr, vlan.tbl_vlan_virtual_if_info.ip_mask, vlan.tbl_vlan_overall_vlan.has_routing_port

    FROM vlan.tbl_vlan_overall_vlan LEFT
    OUTER
    JOIN

    vlan.tbl_vlan_virtual_if_info INNER
    JOIN

    config_db.imc_config.tbl_dev ON vlan.tbl_vlan_virtual_if_info.dev_id = config_db.imc_config.tbl_dev.dev_id INNER
    JOIN

    config_db.imc_config.tbl_snmp_sysinfo ON vlan.tbl_vlan_virtual_if_info.dev_id = config_db.imc_config.tbl_snmp_sysinfo.dev_id ON

    vlan.tbl_vlan_overall_vlan.vlan_id = vlan.tbl_vlan_virtual_if_info.vlan_id

    WHERE (config_db.imc_config.tbl_dev.dev_id = 1153)
    OR


    (config_db.imc_config.tbl_dev.dev_id = 1174)
    OR


    (config_db.imc_config.tbl_dev.dev_id = 1179)
    OR


    (config_db.imc_config.tbl_dev.dev_id = 1278)

    ORDER
    BY vlan.tbl_vlan_virtual_if_info.vlan_id

    ——————

     

     

    The second SQL view is a union of all vlan information and the Layer 3 (routed vlan) information.

     

    ——————

    SELECT vlan.tbl_vlan_overall_vlan.vlan_id AS Number, vlan.tbl_vlan_overall_vlan.vlan_name AS Name, vlan.tbl_vlan_overall_vlan.has_routing_port AS [Layer 3],

    dbo.vlaninfo_L3.sys_name AS Switch, dbo.vlaninfo_L3.ip_addr AS [Default Gateway], dbo.vlaninfo_L3.ip_mask AS [Subnet Mask]

    FROM dbo.vlaninfo_L3 RIGHT
    OUTER
    JOIN

    vlan.tbl_vlan_overall_vlan ON dbo.vlaninfo_L3.vlan_id = vlan.tbl_vlan_overall_vlan.vlan_id

    ——————

     

     

     

     

     

     

    For vlans with multiple default gateways it will show as multiple entries with the same vlan number.

     

  • I was trying to find a report in Backup Exec to show me the tapes used in the last day or so for backups unfortunately I am running Backup Exec 2010 R3 and this feature is broken per http://www.symantec.com/docs/TECH52278 as a result I went digging into the SQL. Here is my query:

     

    SELECT DISTINCT

    TOP (100) PERCENT dbo.JobHistorySummary.JobName, dbo.fConvertDateTime(dbo.JobHistorySummary.OriginalStartTime) AS OriginalStartTime,

    dbo.JobHistorySummary.IsJobActive, dbo.JobHistoryDetailInfo.Data

    FROM dbo.JobHistoryDetail RIGHT OUTER JOIN

    dbo.JobHistorySummary ON dbo.JobHistoryDetail.JobHistoryID = dbo.JobHistorySummary.JobHistoryID LEFT OUTER JOIN

    dbo.JobHistoryDetailInfo ON dbo.JobHistoryDetail.JobHistoryDetailID = dbo.JobHistoryDetailInfo.JobHistoryDetailID CROSS JOIN

    dbo.Media

    WHERE (dbo.JobHistoryDetailInfo.Data IS NOT NULL) AND (dbo.JobHistorySummary.ActualStartTime > DATEADD(day, – 1, GETDATE())) AND

    (dbo.JobHistorySummary.TaskTypeID = 200)

    ORDER BY OriginalStartTime

     

     

    I then placed it in a SharePoint webpage for quick access as a Data View Web Part:

  • We have been rolling out an updated Moodle based training site and recently I was asked to be able to create multiple certificates within a single course. I found it fairly easy to modify /mod/certificate/type/A4_non_embeddded to reference the name of a certificate item in the course and get a matching certificate to the title. To make this change you should modify the certificate.php-file for the desired type in my case A4_non_embedded and replace “$course->fullname” with “$certificate->name”.

     

    So the end result would look like the following highlighted line:

     

    While I did play around with the idea of updating the underlying table with an additional column I didn’t think that it would be prudent and very likely to break in a future release.