Assalamualaikum warahmatullahi wabarakatuh, hello everyone! in this article, i will try to write the article in full English text, Why? i don't know, just practice my writing skills. Please forgive any grammar mistake or textual errors (typo) š¤¢
My daily work as a penetration tester (or pentester) doing[ pentesting ] if you donāt familiar with this kind of term, pentesting is simply breaking the companyās application with ethic for early report to the company if their application / system is vulnerable that could make their business is in danger. The specific ādangerā here is that if an application database could be breached with several technique (SQL Injection, or any Broken Access Control) or there is some vulnerability if the vulnerability is exploitable by āBad Personā the āBad Personā could enter in the whole system of the companyās and doing another things such like drop the Ransomware (server ransomed) the whole server and asked for āmoneyā for unlocking (decryption key and algorithm) the encrypted files. unless is like PDNS when the attacker give you the keys and how to use the keys, haha.
Throughout 2024 doing penetration testing, when doing infrastructure penetration testing i am always found a finding with title KONG ADMIN Take Over via No Authenticated Process
, simply the description of findings is an attacker with access to infrastructure or publicly could access the default port of KONG ADMIN at port 8081
will able to doing any operation such like, Create, Read, Update, Delete (CRUD) the whole configuration inside KONG it self, the main threat of this findings is when a DevOps settings the API Application at port 3333
(an express js application) listen at local interface (127.0.0.1) and serve to public via KONG Gateway forward traffic from Consumers to upstream Services port (80[http], 443[https]). The idea is every client request to port 80 path /api
(KONG) ā will forwarded 3333 (express js main application) and the communication client to server will be established via HTTP/s protocols.
So whatās the actual problem, seems a normal flow isnāt? yes itās a normal flow from KONG to the upstream, the problem is the KONG ADMIN
since the tutorial and documentation at official KONG pages doesnāt implementing authentication at KONG ADMIN
and listen to all interfaces 0.0.0.0
an attacker that realize the port default or custom port for KONG ADMIN
will able to doing any operation of CRUD to KONG GATEWAY (80,443), imagine the normal flow that explained before rewrite to scenario if any client trying to access /api
at port 80 or 443 the consumers will forward to upstream attacker.com/malicious
? itās possible? YES. Itās the nature of KONG ADMIN, the ADMIN features detail explained will be proofed below.
So to prove the default KONG installation documentation on the official site can have a big risk of danger to the existing business flow will detailed below, first the tutorial that writer used is in this links the installation will be using Docker the core of KONG is have to models installation first using Database whichās Postgres database another models is installation without the database (dbless), the configuration will setting up with yaml
configurations and could be updated or deleted
since thereās no Database.
Actually the documentation of Installation with docker is already warned the users if they using the default command that provide by Documentation it will be have a risk on it, but they have an another solution also. But reflecting from my Penetration Experience throughout 2024 thereās many DevOps doesnāt read the documentation enough, even tend to ignore it š
and
Writer will use the mode dbless because itās just for proof of the concepts, the installation command is from official documentations will pasted below.
docker run --read-only -d --name kong-dbless \
--network=kong-net \
-v "$(pwd)/declarative:/kong/declarative/" \
-v "$(pwd)/tmp_volume:/tmp" \
-v "$(pwd)/prefix_volume:/var/run/kong" \
-e "KONG_PREFIX=/var/run/kong" \
-e "KONG_DATABASE=off" \
-e "KONG_DECLARATIVE_CONFIG=/kong/declarative/kong.yml" \
-e "KONG_PROXY_ACCESS_LOG=/dev/stdout" \
-e "KONG_ADMIN_ACCESS_LOG=/dev/stdout" \
-e "KONG_PROXY_ERROR_LOG=/dev/stderr" \
-e "KONG_ADMIN_ERROR_LOG=/dev/stderr" \
-e "KONG_ADMIN_LISTEN=0.0.0.0:8001" \
-e "KONG_ADMIN_GUI_URL=http://localhost:8002" \
-e KONG_LICENSE_DATA \
-p 8000:8000 \
-p 8443:8443 \
-p 8001:8001 \
-p 8444:8444 \
-p 8002:8002 \
-p 8445:8445 \
-p 8003:8003 \
-p 8004:8004 \
kong/kong-gateway:3.9.0.0
From the command that copied from the documentation, writer rewrite the command to format docker-compose.yaml
for flexibility reason, the configuration is not change the purpose of the official command, my docker-compose configuration is below
version: '3.8'
services:
kong:
image: kong/kong-gateway
container_name: kong
environment:
KONG_DATABASE: "off"
KONG_PROXY_ACCESS_LOG: "/dev/stdout"
KONG_ADMIN_ACCESS_LOG: "/dev/stdout"
KONG_PROXY_ERROR_LOG: "/dev/stderr"
KONG_ADMIN_ERROR_LOG: "/dev/stderr"
KONG_ADMIN_LISTEN: "0.0.0.0:8001, 0.0.0.0:8444 ssl"
ports:
- "8000:8000"
- "8443:8443"
- "8001:8001"
- "8444:8444"
restart: unless-stopped
Just run with docker compose up -d
or dockerc-compose up -d
the application will run same like the official documentation, the inside listen configuration is below
netstat -ptln
nmap from outside
So like the screenshot above, the port will listen to all interface since the configuration from the documentation is listen to 0.0.0.0
is listen to all interface problem? for the KONG GATEWAY is NOT, but KONG ADMIN thereās problem, so thereās a proof at all interface we could see the configuration detail of the KONG GATEWAY
at this moment we could doing any operation at CRUD methodologies to the configuration at path server_ip:8001/api
just post the new configuration detail and boom! you could take over the whole routing server. Managing the whole server is quite bit challenging since itās more like writing another fully .yaml
configs š¢ but donāt so worry, thereās a bunch GUI to manage the application, the KONG ADMIN GUI itās available, but itās only for enterprise user onyly
(please correct me if i am wrong). Thereās another popular KONG ADMIN Manager called KONGA
itās web interface, easy to use and more (vulnerabilities) š±š±š±
KONGA have a description in their repository called More than just another GUI to Kong Admin API
so simply KONGA is GUI for managing any configuration at path /config
to KONG ADMIN service, i have ever doing penetration testing and source code review to the KONGA repository and realize thereās potential security issue with default configuration on their repository. First of all the potential security issue is weak token to take over the whole KONGA and KONG it self
the problem is at this codes KONGA-JWT-HANDLER the handler of JWT is
so simply if the variable at .env
called TOKEN_SECRET
not available it will be used hardcoded key token called oursecret
but the in .env_example
( https://github.com/pantsel/konga/blob/c7518acae7ec4082a996ffcc5067c6a169606351/.env_example ) it already have predefined TOKEN_SECRET that possibly from many Junior DevOps will not change the value
So what is the problem when the TOKEN_SECRET
is weak and realizable by an attacker? simply is Every Account take over to the KONGA it self. How? yeah just craft the payload with format
{
"alg": "HS256"
},
ANY_ID_INTEGER_RELATED_TO_ID_USER,
SIGNATURE
And voila with this default configuration you able to generate valid JWT to take over the KONGA and KONG ADMIN behind, credit to ( https://medium.com/manomano-tech/kong-konga-exploitation-hardening-d54ea75a870a )
This is my KONG design patch relate to KONG Documentation it self, KONG basically have to main port exposed 8001 for KONG ADMIN and 8000 KONG GATEWAY, if KONG ADMIN listen to 0.0.0.0 or all interfaces it will a findings with HIGH CVSS or HIGH Severity, so the idea is bind KONG ADMIN 8001 to the localhost, and make a route path to the KONG ADMIN via KONG GATEWAY with Authentication.
So how? change the docker-compose configuration to this configuration that i attach below
version: '3.8'
services:
kong:
image: kong/kong-gateway
container_name: kong
environment:
KONG_DATABASE: "off"
KONG_PROXY_ACCESS_LOG: "/dev/stdout"
KONG_ADMIN_ACCESS_LOG: "/dev/stdout"
KONG_PROXY_ERROR_LOG: "/dev/stderr"
KONG_ADMIN_ERROR_LOG: "/dev/stderr"
KONG_ADMIN_LISTEN: "127.0.0.1:8001, 127.0.0.1:8444 ssl"
ports:
- "8000:8000"
- "8443:8443"
- "127.0.0.1:8001:8001"
- "127.0.0.1:8444:8444"
restart: unless-stopped
the idea is bind all KONG_ADMIN to localhost.
After that re-run the docker-compose, and check the port is listen in what interfaces.
netstat -ptln
nmap from public interfaces
So the port of KONG ADMIN already bind to 127.0.0.1 and couldnāt accessible from another network except the localhost it self, so how to access the KONG ADMIN for now? yeah setting up the routing to KONG ADMIN via KONG GATEWAY with authentication, KONG have bunch authentication plugin to authenticate with the routes thereās available JWT, Basic Auth, API Key and mores, i will demo PoC for 2 Basic Auth and API Key authentication configuration.
API Key Authentication
_format_version: "3.0"
services:
- name: admin-api
url: http://127.0.0.1:8001
routes:
- name: admin-api
paths:
- /admin-api
plugins:
- name: key-auth
consumers:
- username: tubagus
keyauth_credentials:
- key: nikko-hate-king-kong-666
Basic Auth Authentication
_format_version: "3.0"
services:
- name: my_admin
url: http://127.0.0.1:8001
routes:
- name: my_route
paths:
- /my-admin
- name: go_factorial_service
url: http://192.168.110.122:8080/
routes:
- name: go_factorial_route
paths:
- /go-factorial
plugins:
- name: basic-auth
service: my_admin
consumers:
- username: admin
basicauth_credentials:
- username: admin
password: adminLongLongPasswordToGOOOO6666
So to apply the configuration to dbless KONG, we need to curl the configuration.yaml to path :8001/config
in local machine of installation KONG, thereās proof
So when we access the routing /admin-api
that forward to upstream KONG ADMIN at 127.0.0.1:8001 from pbulic interface it will response error since thereās no API Key Founded
To authenticated with API Key we could safely supply the authentication from the headers called apikey
add the secret apikey that predefined before
Also another way to implementing authentication is enable plugin basic authentication like the configuration above, just submit again the .yaml
so like the proof of concept above how we harden and secure our KONG service especially KONG ADMIN service by hide it on KONG GATEWAY with authentication.
So since KONGA is not maintained and have a bunch of vulnerability, whatās the alternative if you not comfortable with the manual config with .yaml
i have ever surf the internet space and found out the repository primate
(https://github.com/getprimate/primate) itās similar with KONGA but itās GUI Desktop based built with mainly using Electron.
The GUI is nice and also easy to operate, if you wanna using primate
you must set the KONG ADMIN forwarder with Basic Authentication types.
Every documentation is meant to be read carefully. It exists so users can understand what the developers expect when running their program in the best way possible. The maintainers always talk about security, making sure users are aware of the risks associated with basic setups. Ideally, default configurations should be "secure by default," but sometimes they need tweaking since they're just the starting point.
This wraps up my English practice article. I hope I've made fewer typos or grammar mistakes. Sorry if my explanation above didn't meet your expectations or if I got something wrong. I'd love to chat more about what I've written, so feel free to email me at @rainysm (telegram)