This is a nameplate on the server-room door, not a key under the mat
Tenable plugin 25926 is flagging SQL Anywhere / Adaptive Server Anywhere servers that answer client discovery broadcasts. When broadcast listening is enabled, a host on the same LAN can elicit connection metadata such as the server name, port, version, and sometimes database names. This is not tied to a narrow broken build; SAP/Sybase documentation shows the behavior across older ASA 9.x and later SQL Anywhere releases whenever the default broadcast listener remains enabled instead of using -sb 0 or BroadcastListener=NO.
The vendor's MEDIUM label is too generous for enterprise patch triage. The decisive friction is attacker position: the actor already needs access to the same broadcast domain or internal subnet, and the payoff is only reconnaissance metadata rather than credential theft, code execution, or direct record exposure. Treat it as configuration hygiene on legacy flat networks, not as an urgent vulnerability.
3 steps from start to impact.
Land on the same subnet
- Internal network presence on the same VLAN/subnet, or equivalent routed access to the broadcast segment
- UDP broadcast traffic to the SQL Anywhere listener is not blocked locally
- Requires prior compromise, rogue device access, VPN entry, or physical presence
- Network segmentation, NAC, and isolated server VLANs sharply reduce reachable population
Send a discovery broadcast
broadcast-sybase-asa-discover or Nessus plugin sybase_asa_ping.nasl, the attacker sends the same style of broadcast used by legitimate client discovery. If the server is using the default broadcast listener, it replies with connection metadata.- SQL Anywhere/ASA is listening for client connection broadcasts
- Server was not started with
-sb 0and TCP/IP broadcast listening was not disabled withBroadcastListener=NO
- If
-sb 0is set, the server does not answer UDP broadcasts - Some deployments hide database names with
-dh, reducing the recon value
25926 detects this behavior remotely on-network, and Nmap has a dedicated broadcast discovery script. Passive monitoring can also flag unusual UDP/2638 discovery traffic.Use the metadata for follow-on targeting
- The attacker can reach the actual SQL Anywhere service after discovery
- A separate weakness exists, such as weak credentials or another remotely exploitable bug
- This plugin stops at recon; it does not grant session establishment
- Modern auth controls, segmentation, and monitoring still have to fail for impact to follow
The supporting signals.
| In-the-wild status | No credible evidence of active exploitation campaigns tied to this issue, and no CISA KEV listing. This looks like legacy recon behavior, not a live operator favorite. |
|---|---|
| Proof-of-concept availability | Public safe discovery tooling exists: Nmap's broadcast-sybase-asa-discover and Tenable's detection plugin demonstrate how trivial enumeration is once an attacker is on-LAN. |
| EPSS | N/A — no CVE identifier surfaced for this finding, so there is no FIRST EPSS score to anchor likelihood. |
| KEV status | Not listed in the CISA KEV catalog. Practically, the absence of a CVE makes KEV tracking inapplicable here. |
| CVSS reality check | No authoritative CVSS vector was found. If you forced a real-world vector, it would look closer to adjacent/internal recon with low confidentiality impact than to a true remotely exploitable server flaw. |
| Affected versions | Behavior spans Adaptive Server Anywhere 9.x through later SQL Anywhere releases when TCP/IP broadcast listening is enabled. Docs for ASA 9.0.2, SQL Anywhere 11.0.1, 12.0.1, and 17 all describe the broadcast listener behavior. |
| Fixed / hardened state | There is no patch version to chase. Hardening is configuration-based: start the server with -sb 0 or BroadcastListener=NO; optionally use -dh to suppress database names in responses. |
| Exposure and scanning reality | This is LAN-scoped broadcast discovery, so internet census data from Shodan/Censys/GreyNoise is mostly irrelevant. Nmap explicitly documents the script as discovering servers on the LAN, which is the whole point. |
| Disclosure date | The Tenable detection was published on 2007-08-22. That reinforces the age and stability of the behavior. |
| Reporter / tooling lineage | Detection lineage is from Tenable (sybase_asa_ping.nasl) and Nmap script author Patrik Karlsson. This is well-understood enumeration behavior, not fresh vuln research. |
noisgate verdict.
The single biggest downgrade factor is attacker position: the actor already needs same-subnet/internal access to get any value from this. The impact ceiling is also low because the response exposes connection metadata for reconnaissance, not direct data access or code execution.
Why this verdict
- Adj -2.0 for attacker position: this is not unauthenticated internet reachability; it starts with internal/same-broadcast-domain access, which implies prior compromise or trusted-network presence.
- Adj -1.5 for impact ceiling: the reply gives server name, port, version, and possibly database names — useful recon, but not credentials, records, or code execution.
- Adj -1.0 for exposure population: broadcast discovery is LAN-scoped, so the reachable population is far smaller than a normal remote service bug and invisible to most internet-scale opportunistic scanning.
Why not higher?
There is no exploit chain here unless you add another failure after this one — weak auth, another remote bug, or already-compromised internal access. On its own, the finding is reconnaissance noise from a patch-management perspective, not an enterprise-severity incident driver.
Why not lower?
It is not literally zero-risk because a flat legacy network can leak server names, version hints, and database names to any internal foothold. That metadata can improve follow-on targeting, so the right posture is to document it as hardening debt rather than pretend it has no security relevance at all.
What to do — in priority order.
- Disable broadcast listening — Start SQL Anywhere with
-sb 0or setBroadcastListener=NOso the server stops answering UDP discovery. For an IGNORE verdict there is no formal SLA; do this during normal maintenance or when the service is next touched. - Hide database names — Use
-dhwhere supported so even if some discovery behavior remains, the response leaks less useful metadata. This is backlog hardening, not emergency work. - Keep legacy database servers off user VLANs — Put SQL Anywhere hosts behind segmentation so only application tiers and admin jump paths can reach them. This directly kills the same-subnet prerequisite that makes the finding possible.
- A WAF does nothing here because this is not HTTP traffic.
- Internet-facing exposure reviews are the wrong lens; the behavior is broadcast/LAN-local, so Shodan-style scanning will not tell you much.
- Emergency patching is misplaced because there is no specific fixed build to roll out for this plugin finding.
Crowdsourced verification payload.
Run this on the target SQL Anywhere host from an admin shell so it can inspect process command lines and local sockets. Invoke it as python3 check_sqlanywhere_broadcast.py; root/Administrator is recommended, otherwise the script may return UNKNOWN if the OS hides process details.
#!/usr/bin/env python3
"""
check_sqlanywhere_broadcast.py
Determine whether a local SQL Anywhere / Adaptive Server Anywhere instance
appears to answer client connection broadcasts.
Exit codes:
0 = PATCHED
1 = VULNERABLE
2 = UNKNOWN
"""
import os
import platform
import re
import subprocess
import sys
SAFE_PATTERNS = [
re.compile(r'(^|\s)-sb\s*0(\s|$)', re.I),
re.compile(r'broadcastlistener\s*=\s*(no|0)', re.I),
re.compile(r'(^|\s)-x\s+none(\s|$)', re.I),
]
RISKY_HINTS = [
re.compile(r'(^|\s)-sb\s*1(\s|$)', re.I),
re.compile(r'(^|\s)-x\s+.*tcpip', re.I),
re.compile(r'dbsrv\d+|dbeng\d+', re.I),
]
PROC_NAME_RE = re.compile(r'dbsrv\d+|dbeng\d+|dbsrv|dbeng', re.I)
def run(cmd):
try:
return subprocess.check_output(cmd, stderr=subprocess.DEVNULL, text=True, shell=isinstance(cmd, str))
except Exception:
return ""
def get_processes():
system = platform.system().lower()
procs = []
if system == 'windows':
ps = run(['powershell', '-NoProfile', '-Command',
"Get-CimInstance Win32_Process | Select-Object ProcessId,Name,CommandLine | ConvertTo-Csv -NoTypeInformation"])
for line in ps.splitlines()[1:]:
parts = []
cur = ''
in_q = False
for ch in line:
if ch == '"':
in_q = not in_q
elif ch == ',' and not in_q:
parts.append(cur)
cur = ''
else:
cur += ch
parts.append(cur)
if len(parts) >= 3:
name = parts[1].strip('"')
cmd = parts[2].strip('"')
if PROC_NAME_RE.search(name) or PROC_NAME_RE.search(cmd):
procs.append((name, cmd))
return procs
if os.path.isdir('/proc'):
for pid in os.listdir('/proc'):
if not pid.isdigit():
continue
cmdline_path = os.path.join('/proc', pid, 'cmdline')
try:
raw = open(cmdline_path, 'rb').read().replace(b'\x00', b' ').decode(errors='ignore').strip()
except Exception:
continue
if raw and PROC_NAME_RE.search(raw):
name = raw.split()[0]
procs.append((name, raw))
return procs
ps = run(['ps', '-axo', 'command='])
for line in ps.splitlines():
if PROC_NAME_RE.search(line):
name = line.split()[0] if line.split() else 'unknown'
procs.append((name, line.strip()))
return procs
def udp_2638_listener_present():
outputs = [
run(['ss', '-lunp']),
run(['netstat', '-anu']),
run(['lsof', '-nP', '-iUDP']),
run(['powershell', '-NoProfile', '-Command', 'Get-NetUDPEndpoint | Format-Table -HideTableHeaders LocalPort'])
]
for out in outputs:
if re.search(r'(^|\D)2638(\D|$)', out):
return True
return False
def main():
procs = get_processes()
if not procs:
print('UNKNOWN - no local dbsrv/dbeng process found')
sys.exit(2)
hardened = []
risky = []
for name, cmd in procs:
cmd_norm = ' ' + cmd.strip() + ' '
if any(p.search(cmd_norm) for p in SAFE_PATTERNS):
hardened.append((name, cmd))
elif any(p.search(cmd_norm) for p in RISKY_HINTS):
risky.append((name, cmd))
else:
# Default server behavior in documented builds is to answer broadcasts unless disabled.
risky.append((name, cmd))
listener = udp_2638_listener_present()
if risky and listener:
print('VULNERABLE - SQL Anywhere process found without broadcast hardening and UDP/2638 listener detected')
sys.exit(1)
if risky and not listener:
print('UNKNOWN - SQL Anywhere process found without explicit broadcast hardening, but UDP/2638 listener was not confirmed')
sys.exit(2)
if hardened:
print('PATCHED - SQL Anywhere process appears hardened with -sb 0, BroadcastListener=NO, or local-only networking')
sys.exit(0)
print('UNKNOWN - unable to determine effective broadcast listener state')
sys.exit(2)
if __name__ == '__main__':
main()
If you remember one thing.
-sb 0 / BroadcastListener=NO and optionally -dh into normal maintenance instead of spending emergency patch capacity here.Sources
- Tenable Plugin 25926
- SAP Help: -sb Database Server Option
- Sybase SQL Anywhere 11.0.1: BroadcastListener protocol option
- Sybase SQL Anywhere 11.0.1: -sb server option
- Sybase SQL Anywhere 12.0.1: TCP/IP protocol
- Adaptive Server Anywhere 9.0.2 Administration Guide PDF
- SAP KBA 2217028: disable broadcast listener
- Nmap NSEDoc: broadcast-sybase-asa-discover
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.