No Auth, 164 Million Records: The Malawi Credit Bureau Exposure
#01CRITICAL/ FirewallFables/ Oct 15, 2026/ 5 min read
Verdict: A public-facing Kibana 5.6.16 instance, deployed on a major European cloud provider with no authentication in front of it, exposed the complete national credit-bureau dataset of Malawi — 164,684,330 records across 40+ Elasticsearch indices, including full PII for 2.4 million individuals, loan-level financial data for 49 million credit lines, and live application logs leaking session tokens in real time.
This is a write-up of the exposure, how it was verified, and what it means when a country's financial identity layer ends up on the public internet with the front door open. All network indicators are redacted; the disclosure was reported to Malawi CERT through responsible channels.
#The exposure
The system was a Kibana 5.6.16 dashboard — the kind of setup teams reach for when they want to browse Elasticsearch data "internally." It wasn't internal. The instance sat directly on the public internet on a European cloud provider's network, with zero authentication: no login page, no API key, no IP allowlist. Kibana's built-in Elasticsearch proxy at /elasticsearch/ turned the dashboard into a full read-write gateway to the backend database. Anyone who found the host could list indices, run queries, read mappings, and export everything.
Two identifiers confirmed the owner beyond doubt: the Kibana dashboard title named the system as the national credit-data platform, and the server hostname matched the operator's internal naming. The Elasticsearch version was 5.6.16 — a 2017-era release that had never been upgraded.
#What was inside
| Metric | Value |
|---|---|
| Total records | 164,684,330 |
| Total data size | 183.5 GB |
| Elasticsearch version | 5.6.16 |
| Number of indices | 40+ |
The individuals index alone held 2,408,384 people with complete identity profiles:
- Identity: first, middle, last and maiden names
- Demographics: date of birth, sex, marital status, number of dependents
- Location: home address and home village/traditional authority (with phone numbers embedded)
- Documents: national ID, driving licence and passport numbers, residence permit numbers
- Professional: profession, nationality and district identifiers — plus a photo field
Around it sat the financial graph:
| Index | Records | Content |
|---|---|---|
credit_lines |
48,993,786 | Balances, approved amounts, repayments, days in arrears, delinquency dates, collateral, interest rates, amortization schedules |
insurance_policies |
47,343,156 | Policy numbers, premiums, coverage details |
cris-web |
10,362,116 | Business registrations: owner names, emails, phones, addresses, tax IDs |
uploadr |
15,570,736 | Raw Excel/CSV uploads from data-provider institutions |
filebeat-* (35 indices) |
~40,351,712 | Live Apache access logs, PHP errors — including POST bodies and session tokens |
cdss |
32,664 | Credit decision-support data |
The credit bureau pooled data from 23 member institutions — commercial banks, microfinance companies, a rural finance company, and the national revenue authority. Every institution feeding the bureau was exposed through it. The filebeat-* indices were perhaps the most immediately dangerous: active application logs capturing live traffic, meaning session tokens and form submissions were being written into an open database as the platform served real users.
#How it was verified
With no authentication required, verification was a handful of anonymous requests:
# Confirm the instance is open — no credentials, no cookies
curl -s http://REDACTED-IP:5601/elasticsearch/
# Count the individuals index (~2.4M records)
curl -s http://REDACTED-IP:5601/elasticsearch/individuals/_count?pretty
# Sample records — full PII returned to an anonymous caller
curl -s 'http://REDACTED-IP:5601/elasticsearch/individuals/_search?pretty&size=3'
# List every index in the cluster
curl -s 'http://REDACTED-IP:5601/elasticsearch/_cat/indices?v'
# Dump the full schema, including field names for every PII attribute
curl -s 'http://REDACTED-IP:5601/elasticsearch/individuals/_mapping?pretty'
Each command works from any network anywhere in the world. That is what "zero authentication" means in practice.
#Why this matters
Identity theft at national scale. Two million complete identity profiles — name, DOB, national ID, address, photo — is not a breach of "some data." It is a ready-made synthetic-identity factory: enough to open accounts, apply for loans, and file tax returns in someone else's name.
Financial surveillance of an entire population. The credit-line index maps who owes what to which institution, with delinquency status and collateral details. Combined with the identity index, it answers questions no outsider should ever be able to ask: who is behind on loans, where they live, and what they put up as collateral.
Cross-institution blindness, broken. A credit bureau exists precisely because member institutions agree not to see each other's raw customer data. The misconfiguration inverted that agreement: every institution's inputs became visible in one place, to everyone.
Live credential leakage. Session tokens and POST data in the log indices mean the exposure was not just historical data sitting idle — it was an actively refreshing stream of usable credentials.
Moral: The most sensitive database in a country's financial system was one unauthenticated HTTP request away from the public internet. Perimeter security isn't a firewall you bought — it's the absence of accidental front doors. If your data platform has a UI, assume the whole internet can see it unless something boring and invisible (authn, network policy) says otherwise.
#What the operators should do
Immediately:
- Restrict Kibana and Elasticsearch to internal networks — no public listeners, no cloud security-group holes
- Rotate every password, API key and service token that ever touched the cluster (the log indices may have captured live ones)
- Audit credentials across all 23 member institutions and revoke anything over-privileged
Short term:
- Put real authentication in front of every Elasticsearch endpoint (native security, or an SSO-aware reverse proxy)
- Enable audit logging and alert on unusual query volume — an anonymous export of 164M rows generates a lot of traffic nobody was watching for
- Delete or age-out application logs that capture request bodies; POST data does not belong in analytics indices
Long term:
- External penetration test of the entire bureau infrastructure before this data pool is trusted again
- Data-classification review: photos, national IDs and collateral records deserve encryption at rest and strict access tiers, not "the dashboard needs it"
#Disclosure
Reported to Malawi CERT via responsible disclosure in October 2026 by an independent researcher. Instances may have been secured since discovery. All commands above are reproduced in redacted form; no citizen data is reproduced anywhere in this post.
Moral of the fable: the data was never hacked. It was simply there — and "there" turned out to mean "everywhere."
Pass it on
More fables
The Registry That Called Everyone: 265 Million Numbers Exposed at India's DND
Two unauthenticated CouchDB nodes held India's entire Do-Not-Disturb registry — 245 million phone preferences, 7 million consent records and full residential PII — behind nothing but an open port.
The SQLite File That Exposed a Monitoring Environment
A three-year-old Grafana path traversal led to a plaintext database, then to Zabbix API access, then to a full infrastructure map.
365,000 Attacks in Seven Days: What a TPOT Honeypot Sees on the Open Internet
One Azure VM, one week, 365,000 logged events. root/123456 at the top of the credential charts, SIP and SSH at the top of the port charts, and cloud providers doing most of the shooting.