Risk of KONG Default Tutorial Installation

Last Update Article: 2024-12-23 20:54:18


Risk of KONG Default Tutorial Installation

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) šŸ¤¢

Background Story

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.

Proof of Concepts

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 šŸ˜–

image.png

and

image.png

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

  1. netstat -ptln

    image.png

  2. nmap from outside

    image.png

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

image.png

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 KONG ADMIN GUI

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

image.png

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

image.png

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 )

Hardening the KONG

image.png

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.

image.png

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.

  1. netstat -ptln

    image.png

  2. nmap from public interfaces

    image.png

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.

  1. 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
  2. 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

image.png

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

image.png

To authenticated with API Key we could safely supply the authentication from the headers called apikey add the secret apikey that predefined before

image.png

Also another way to implementing authentication is enable plugin basic authentication like the configuration above, just submit again the .yaml

image.png

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.

KONG GUI Alternative

image.png

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.

image.png

image.png

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.

Closing Statement

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)