Skip to Content
OpenVAPTAlpha
Pre-release. Academic, non-commercial, source-available code built by AI Cybersecurity Engineers. Free for your own use, 100% at your own risk. This website collects no data. Read MoreRead Less
Pre-release. OpenVAPT has no Stable release yet. Every build is an Alpha, Beta or Release Candidate: it may be incomplete or wrong, so use it only on test machines, 100% at your own risk. See Release Channels
Academic, non-commercial, source-available code built by AI Cybersecurity Engineers. These are AI systems, not people or registered engineers. Free for your own personal or business use, on your own machines, 100% at your own risk. Not for sale. Not for providing services. This website collects no data. Read the Acknowledgements
Pre-release. OpenVAPT has no Stable release yet. Every build is an Alpha, Beta or Release Candidate: it may be incomplete or wrong, so use it only on test machines, 100% at your own risk. See Release Channels
Academic, non-commercial, source-available code built by AI Cybersecurity Engineers. These are AI systems, not people or registered engineers. Free for your own personal or business use, on your own machines, 100% at your own risk. Not for sale. Not for providing services. This website collects no data. Read the Acknowledgements
HighNET-DB-001Data ServicesNetwork

Database or Cache Service Exposed to the Network

Checks whether databases, caches, search engines or the Docker API listen on a network-reachable address.

Why It Matters
Exposed databases and caches (Redis, MongoDB, Elasticsearch, Memcached) are among the most common causes of mass data breaches and ransom wipes, often because they ship without authentication.
How It Detects
Matches network-reachable listening ports from /proc/net against a list of well-known data service ports (IANA registry).
How to Fix
Bind the service to 127.0.0.1 (MySQL: bind-address = 127.0.0.1; Redis: bind 127.0.0.1 ::1 and protected-mode yes; MongoDB: net.bindIp: 127.0.0.1) and restart it. Caution: confirm first that no application on another machine connects to it, or that application loses its database. If remote access is needed, allow only specific source IPs in the firewall and require TLS and authentication.
How to Verify
ss -tlnp | grep -E ':(3306|5432|6379|27017|9200|11211)' should show only 127.0.0.1 or ::1.
CVSS v3.1 Vector
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H
Control Category
Data Services: CIS Controls v8 3, 4, 12; NIST CSF 2.0 PR.DS, PR.PS
Fix Effort
Low
CIS Controls v8 Safeguard
3.3
NIST CSF 2.0 Subcategory
PR.AA-05, PR.DS-01
CWE
CWE-1327, CWE-306
OWASP Top 10
A05:2021
NIST SP 800-53 Rev. 5
SC-7, CM-7
Benchmark Topic
Network exposure of data services (topic only, no benchmark text)
References
OWASP Database Security Cheat Sheet
Redis security
Learn the theory behind this check: F1 Security Basics, P3 Network Exposure and Firewalls, P8 Data Services: Databases, File Shares, DNS and Mail.

Source Code

The complete file that defines this check. Run it with openvapt scan --only NET-DB-001, or read it offline with openvapt explain NET-DB-001.

internal/checks/network/listeners.go · Lines 1-162View on GitHub at This Commit
1package network
2
3import (
4 "context"
5 "fmt"
6 "strings"
7
8 "github.com/openvapt/openvapt/internal/check"
9 "github.com/openvapt/openvapt/internal/checks/collect"
10 "github.com/openvapt/openvapt/internal/sys"
11)
12
13// dataPorts are services that should almost never be reachable from other
14// machines. Port numbers per the IANA Service Name and Port Number Registry.
15var dataPorts = map[int]string{
16 3306: "MySQL/MariaDB", 5432: "PostgreSQL", 1433: "Microsoft SQL Server", 1521: "Oracle DB",
17 27017: "MongoDB", 6379: "Redis", 11211: "Memcached", 9200: "Elasticsearch/OpenSearch",
18 5984: "CouchDB", 9042: "Cassandra", 5672: "RabbitMQ",
19}
20
21// cleartextPorts are legacy services that send credentials unencrypted.
22var cleartextPorts = map[int]string{
23 21: "FTP", 23: "Telnet", 69: "TFTP", 110: "POP3 (no TLS)", 143: "IMAP (no TLS)",
24 512: "rexec", 513: "rlogin", 514: "rsh", 161: "SNMP (v1/v2c community strings)", 389: "LDAP (no TLS)", 873: "rsync daemon",
25}
26
27func init() {
28 check.Register(&check.Check{
29 ID: "NET-LSN-001",
30 Title: "Inventory of Listening Network Services",
31 Domain: check.DomainNetwork,
32 Severity: check.Info,
33 CVSS: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:N",
34 Summary: "Lists every TCP and UDP port this machine listens on, and whether it is reachable from other machines.",
35 Rationale: "Attack surface starts with what is listening. Every exposed port should be known and justified (NIST SP 800-115, discovery phase).",
36 Detection: "Parses /proc/net/tcp, tcp6, udp and udp6. Sockets bound to 127.0.0.1 or ::1 are local only; anything else (0.0.0.0, ::, a public address) is reachable from the network unless a firewall blocks it.",
37 Fix: "Stop or uninstall services you do not need (systemctl disable --now <unit>). Bind internal services to 127.0.0.1. Block the rest at the firewall.",
38 Verify: "ss -tulpn shows the same list with process names.",
39 Refs: []check.Ref{{Title: "NIST SP 800-115, Technical Guide to Information Security Testing and Assessment", URL: "https://csrc.nist.gov/pubs/sp/800/115/final"}, {Title: "proc_net(5), Linux man-pages", URL: "https://man7.org/linux/man-pages/man5/proc_net.5.html"}},
40 Standards: check.Standards{CWE: []string{"CWE-1327"}, NIST: []string{"CM-7", "CM-8"}, CISTopic: "Network services inventory"},
41 Run: func(_ context.Context, s sys.System) []check.Result {
42 ls, err := collect.Listeners(s)
43 if err != nil {
44 return []check.Result{check.IncompleteR("/proc/net", "One or more socket tables were unreadable or partial")}
45 }
46 var pub, local []string
47 for _, l := range ls {
48 if l.Public() {
49 pub = append(pub, l.String()+label(l.Port))
50 } else {
51 local = append(local, l.String()+label(l.Port))
52 }
53 }
54 ev := append([]string{fmt.Sprintf("network-reachable: %d", len(pub))}, pub...)
55 ev = append(ev, fmt.Sprintf("local only: %d", len(local)))
56 ev = append(ev, local...)
57 return []check.Result{check.PassR("sockets", fmt.Sprintf("%d listening sockets, %d reachable from the network", len(ls), len(pub)), ev...)}
58 },
59 })
60
61 check.Register(&check.Check{
62 ID: "NET-DB-001",
63 Title: "Database or Cache Service Exposed to the Network",
64 Domain: check.DomainNetwork,
65 Severity: check.High,
66 CVSS: "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H",
67 Summary: "Checks whether databases, caches, search engines or the Docker API listen on a network-reachable address.",
68 Rationale: "Exposed databases and caches (Redis, MongoDB, Elasticsearch, Memcached) are among the most common causes of mass data breaches and ransom wipes, often because they ship without authentication.",
69 Detection: "Matches network-reachable listening ports from /proc/net against a list of well-known data service ports (IANA registry).",
70 Fix: "Bind the service to 127.0.0.1 (MySQL: bind-address = 127.0.0.1; Redis: bind 127.0.0.1 ::1 and protected-mode yes; MongoDB: net.bindIp: 127.0.0.1) and restart it. Caution: confirm first that no application on another machine connects to it, or that application loses its database. If remote access is needed, allow only specific source IPs in the firewall and require TLS and authentication.",
71 Verify: "ss -tlnp | grep -E ':(3306|5432|6379|27017|9200|11211)' should show only 127.0.0.1 or ::1.",
72 Refs: []check.Ref{{Title: "OWASP Database Security Cheat Sheet", URL: "https://cheatsheetseries.owasp.org/cheatsheets/Database_Security_Cheat_Sheet.html"},
73 {Title: "Redis security", URL: "https://redis.io/docs/latest/operate/oss_and_stack/management/security/"}},
74 Standards: check.Standards{CWE: []string{"CWE-1327", "CWE-306"}, OWASP: []string{"A05:2021"}, NIST: []string{"SC-7", "CM-7"}, CISTopic: "Network exposure of data services"},
75 Run: func(_ context.Context, s sys.System) []check.Result {
76 ls, err := collect.Listeners(s)
77 if err != nil {
78 return []check.Result{check.IncompleteR("/proc/net", "One or more socket tables were unreadable or partial")}
79 }
80 var bad []string
81 for _, l := range ls {
82 if name, ok := dataPorts[l.Port]; ok && l.Public() && strings.HasPrefix(l.Proto, "tcp") {
83 bad = append(bad, l.String()+" "+name)
84 }
85 }
86 if len(bad) > 0 {
87 return []check.Result{check.FailR("sockets", "Data services listen on network-reachable addresses", bad...)}
88 }
89 return []check.Result{check.PassR("sockets", "No database or cache ports are network-reachable")}
90 },
91 })
92
93 check.Register(&check.Check{
94 ID: "NET-SVC-001",
95 Title: "Cleartext Legacy Services Listening",
96 Domain: check.DomainNetwork,
97 Severity: check.High,
98 CVSS: "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N",
99 Summary: "Checks for Telnet, FTP, rsh/rlogin, TFTP, plain POP3/IMAP/LDAP, SNMP v1/v2c and rsync daemons on network-reachable addresses.",
100 Rationale: "These protocols send passwords and data unencrypted, so anyone on the path can read or alter them. Most also have weak or no authentication.",
101 Detection: "Matches network-reachable listening ports from /proc/net against well-known cleartext service ports.",
102 Fix: "Replace with encrypted equivalents: SSH/SFTP instead of Telnet/FTP/rsh, IMAPS (993)/POP3S (995), LDAPS (636), SNMPv3. Disable the old service: systemctl disable --now <unit>.",
103 Verify: "ss -tulpn should not show ports 21, 23, 69, 110, 143, 161, 389, 512-514 or 873 on public addresses.",
104 Refs: []check.Ref{{Title: "NIST SP 800-123, Guide to General Server Security", URL: "https://csrc.nist.gov/pubs/sp/800/123/final"}},
105 Standards: check.Standards{CWE: []string{"CWE-319"}, OWASP: []string{"A02:2021"}, NIST: []string{"SC-8", "CM-7"}, CISTopic: "Remove insecure legacy services"},
106 Run: func(_ context.Context, s sys.System) []check.Result {
107 ls, err := collect.Listeners(s)
108 if err != nil {
109 return []check.Result{check.IncompleteR("/proc/net", "One or more socket tables were unreadable or partial")}
110 }
111 var bad []string
112 for _, l := range ls {
113 if name, ok := cleartextPorts[l.Port]; ok && l.Public() {
114 bad = append(bad, l.String()+" "+name)
115 }
116 }
117 if len(bad) > 0 {
118 return []check.Result{check.FailR("sockets", "Cleartext services are network-reachable", bad...)}
119 }
120 return []check.Result{check.PassR("sockets", "No cleartext legacy services are network-reachable")}
121 },
122 })
123}
124
125func label(port int) string {
126 for _, m := range []map[int]string{dataPorts, cleartextPorts, controlPorts, managementPorts} {
127 if n, ok := m[port]; ok {
128 return " (" + n + ")"
129 }
130 }
131 switch port {
132 case 22:
133 return " (SSH)"
134 case 25:
135 return " (SMTP)"
136 case 53:
137 return " (DNS)"
138 case 80:
139 return " (HTTP)"
140 case 443:
141 return " (HTTPS)"
142 case 587:
143 return " (SMTP submission)"
144 case 993:
145 return " (IMAPS)"
146 case 995:
147 return " (POP3S)"
148 }
149 return ""
150}
151
152// exposure describes how a network-reachable socket is bound, so a reader
153// can tell a service on every interface from one on a single address.
154func exposure(l collect.Listener) string {
155 if l.IP.IsUnspecified() {
156 return "all interfaces"
157 }
158 if l.IP.IsPrivate() || l.IP.IsLinkLocalUnicast() {
159 return "private address"
160 }
161 return "public address"
162}

Also available as plain Markdown for notes, scripts and AI tools. Same facts, same source, no styling.

Cite This Page

If this page helped your work, please cite it. The version and web address are filled in; the access date is today's date in your browser. Every other style, and when credit is required, is on How to Cite OpenVAPT.

APA 7
OpenVAPT. (2026). NET-DB-001 Database or Cache Service Exposed to the Network (Version 0.1.0-alpha.6). OpenVAPT Check Catalogue. Retrieved October 16, 2026, from https://openvapt.com/checks/NET-DB-001.html

In text: (OpenVAPT, 2026). Accessed: the date shown is today's date from your own browser (the site's build date without JavaScript); change it to the day you read the page.

BibTeX
@misc{openvapt_net_db_001,
  author       = {{OpenVAPT}},
  title        = {{NET-DB-001 Database or Cache Service Exposed to the Network}},
  year         = {2026},
  howpublished = {\url{https://openvapt.com/checks/NET-DB-001.html}},
  note         = {OpenVAPT Check Catalogue, version 0.1.0-alpha.6. Accessed 16 October 2026}
}

Accessed: the date shown is today's date from your own browser (the site's build date without JavaScript); change it to the day you read the page.

Citing OpenVAPT does not mean OpenVAPT endorses, approves or has reviewed your work.