Skip to content

Commit

Permalink
Add some solutions for SadServers Medium challenges
Browse files Browse the repository at this point in the history
  • Loading branch information
devl00p committed Mar 2, 2024
1 parent 17bbd78 commit 464514e
Show file tree
Hide file tree
Showing 8 changed files with 1,180 additions and 1 deletion.
172 changes: 172 additions & 0 deletions _posts/2024-02-03-Solution-du-challenge-Cape-Town-de-SadServers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
---
title: "Solution du challenge Cape Town de SadServers.com"
tags: [CTF,AdminSys,SadServers
---

**Scenario:** "Cape Town": Borked Nginx

**Level:** Medium

**Type:** Fix

**Tags:** [nginx](https://sadservers.com/tag/nginx) [realistic-interviews](https://sadservers.com/tag/realistic-interviews)

**Description:** There's an Nginx web server installed and managed by systemd. Running `curl -I 127.0.0.1:80` returns `curl: (7) Failed to connect to localhost port 80: Connection refused` , fix it so when you curl you get the default Nginx page.

**Test:** `curl -Is 127.0.0.1:80|head -1` returns `HTTP/1.1 200 OK`

**Time to Solve:** 15 minutes.

Déjà la base : est-ce que le port est en écoute (et donc le service lancé) ?

```console
admin@i-06cb61539b1effc2b:/$ ss -lntp
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 4096 *:6767 *:* users:(("sadagent",pid=567,fd=7))
LISTEN 0 4096 *:8080 *:* users:(("gotty",pid=566,fd=6))
LISTEN 0 128 [::]:22 [::]:*
```

Non, alors voyons son état systemctl :

```console
admin@i-06cb61539b1effc2b:/$ systemctl status nginx
● nginx.service - The NGINX HTTP and reverse proxy server
Loaded: loaded (/etc/systemd/system/nginx.service; enabled; vendor preset: enabled)
Active: failed (Result: exit-code) since Sat 2024-03-02 09:52:55 UTC; 1min 16s ago
Process: 574 ExecStartPre=/usr/sbin/nginx -t (code=exited, status=1/FAILURE)
CPU: 29ms

Mar 02 09:52:55 i-06cb61539b1effc2b systemd[1]: Starting The NGINX HTTP and reverse proxy server...
Mar 02 09:52:55 i-06cb61539b1effc2b nginx[574]: nginx: [emerg] unexpected ";" in /etc/nginx/sites-enabled/default:1
Mar 02 09:52:55 i-06cb61539b1effc2b nginx[574]: nginx: configuration file /etc/nginx/nginx.conf test failed
Mar 02 09:52:55 i-06cb61539b1effc2b systemd[1]: nginx.service: Control process exited, code=exited, status=1/FAILURE
Mar 02 09:52:55 i-06cb61539b1effc2b systemd[1]: nginx.service: Failed with result 'exit-code'.
Mar 02 09:52:55 i-06cb61539b1effc2b systemd[1]: Failed to start The NGINX HTTP and reverse proxy server.
```

Erreur à la première ligne du fichier de configuration, voyons ça :

```console
admin@i-06cb61539b1effc2b:/etc/nginx/sites-enabled$ head default
;
##
# You should look at the following URL's in order to grasp a solid understanding
# of Nginx configuration files in order to fully unleash the power of Nginx.
# https://www.nginx.com/resources/wiki/start/
# https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/
# https://wiki.debian.org/Nginx/DirectoryStructure
#
# In most cases, administrators will remove this file from sites-enabled/ and
# leave it as reference inside of sites-available where it will continue to be
```

La correction est vite faite, mais sans trop de surprises, on tombe sur un problème plus gros :

```console
admin@i-06cb61539b1effc2b:/etc/nginx/sites-enabled$ sudo vi default
admin@i-06cb61539b1effc2b:/etc/nginx/sites-enabled$ sudo systemctl start nginx
admin@i-06cb61539b1effc2b:/etc/nginx/sites-enabled$ systemctl status nginx
● nginx.service - The NGINX HTTP and reverse proxy server
Loaded: loaded (/etc/systemd/system/nginx.service; enabled; vendor preset: enabled)
Active: active (running) since Sat 2024-03-02 09:56:14 UTC; 7s ago
Process: 862 ExecStartPre=/usr/sbin/nginx -t (code=exited, status=0/SUCCESS)
Process: 863 ExecStart=/usr/sbin/nginx (code=exited, status=0/SUCCESS)
Main PID: 864 (nginx)
Tasks: 2 (limit: 524)
Memory: 2.4M
CPU: 31ms
CGroup: /system.slice/nginx.service
├─864 nginx: master process /usr/sbin/nginx
└─865 nginx: worker process

Mar 02 09:56:14 i-06cb61539b1effc2b systemd[1]: Starting The NGINX HTTP and reverse proxy server...
Mar 02 09:56:14 i-06cb61539b1effc2b nginx[862]: nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
Mar 02 09:56:14 i-06cb61539b1effc2b nginx[862]: nginx: configuration file /etc/nginx/nginx.conf test is successful
Mar 02 09:56:14 i-06cb61539b1effc2b systemd[1]: Started The NGINX HTTP and reverse proxy server.
admin@i-06cb61539b1effc2b:/etc/nginx/sites-enabled$ curl -Is 127.0.0.1:80|head -1
HTTP/1.1 500 Internal Server Error
```

On va devoir regarder dans les logs du serveur.

```console
admin@i-06cb61539b1effc2b:/etc/nginx/sites-enabled$ tail /var/log/nginx/error.log
2022/09/11 16:39:11 [emerg] 5875#5875: unexpected ";" in /etc/nginx/sites-enabled/default:1
2022/09/11 16:54:26 [emerg] 5931#5931: unexpected ";" in /etc/nginx/sites-enabled/default:1
2022/09/11 16:55:00 [emerg] 5961#5961: unexpected ";" in /etc/nginx/sites-enabled/default:1
2022/09/11 17:02:07 [emerg] 6066#6066: unexpected ";" in /etc/nginx/sites-enabled/default:1
2022/09/11 17:07:03 [emerg] 6146#6146: unexpected ";" in /etc/nginx/sites-enabled/default:1
2024/03/02 09:52:55 [emerg] 574#574: unexpected ";" in /etc/nginx/sites-enabled/default:1
2024/03/02 09:56:14 [alert] 864#864: socketpair() failed while spawning "worker process" (24: Too many open files)
2024/03/02 09:56:14 [emerg] 865#865: eventfd() failed (24: Too many open files)
2024/03/02 09:56:14 [alert] 865#865: socketpair() failed (24: Too many open files)
2024/03/02 09:56:40 [crit] 865#865: *1 open() "/var/www/html/index.nginx-debian.html" failed (24: Too many open files), client: 127.0.0.1, server: _, request: "HEAD / HTTP/1.1", host: "127.0.0.1"
```

Le serveur ne parvient pas à ouvrir le fichier d'index, car trop de fichiers sont ouverts sur le système.

Ma première réaction a été de voir du côté de `ulimit` :

```console
admin@i-05a9742de4b12737a:/$ ulimit -a
real-time non-blocking time (microseconds, -R) unlimited
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 1748
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 1748
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
```

Tout semble standard ici...

Si la limite n'est pas globale au système, elle concerne alors probablement que le processus. Encore un hack de chez systemd ?

```console
root@i-05a9742de4b12737a:/etc/security# cat /etc/systemd/system/nginx.service
[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target

[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/usr/sbin/nginx -s reload
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true
LimitNOFILE=10

[Install]
WantedBy=multi-user.target
```

Bingo ! La directive `LimitNOFILE` limite le nombre de fichiers ouverts par le service.

Il suffit de retirer l'option et de redémarrer le service :

```console
root@i-05a9742de4b12737a:/etc/security# vi /etc/systemd/system/nginx.service
root@i-05a9742de4b12737a:/etc/security# systemctl restart nginx
Warning: The unit file, source configuration file or drop-ins of nginx.service changed on disk. Run 'systemctl daemon-reload' to reload units.
root@i-05a9742de4b12737a:/etc/security# systemctl daemon-reload
root@i-05a9742de4b12737a:/etc/security# curl -Is 127.0.0.1:80|head -1
HTTP/1.1 500 Internal Server Error
root@i-05a9742de4b12737a:/etc/security# systemctl restart nginx
root@i-05a9742de4b12737a:/etc/security# curl -Is 127.0.0.1:80|head -1
HTTP/1.1 200 OK
```
196 changes: 196 additions & 0 deletions _posts/2024-02-03-Solution-du-challenge-Lisbon-de-SadServers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
---
title: "Solution du challenge Lisbon de SadServers.com"
tags: [CTF,AdminSys,SadServers
---

**Scenario:** "Lisbon": etcd SSL cert troubles

**Level:** Medium

**Type:** Fix

**Tags:** [etcd](https://sadservers.com/tag/etcd) [ssl](https://sadservers.com/tag/ssl) [realistic-interviews](https://sadservers.com/tag/realistic-interviews)

**Description:** There's an *etcd* server running on https://localhost:2379 , get the value for the key "foo", ie `etcdctl get foo` or `curl https://localhost:2379/v2/keys/foo`

**Test:** etcdctl get foo returns bar.

**Time to Solve:** 20 minutes.

Ce scénario a été un vrai casse-tête. J'en ai résolu une partie, mais j'ai dû jeter l'éponge à la fin et consulter la solution.

Voyons ce qu'il se passe avec la commande :

```console
admin@i-08f438fe20e16868c:/$ etcdctl get foo
Error: client: etcd cluster is unavailable or misconfigured; error #0: x509: certificate has expired or is not yet valid: current time 2025-03-02T17:18:38Z is after 2023-01-30T00:02:48Z

error #0: x509: certificate has expired or is not yet valid: current time 2025-03-02T17:18:38Z is after 2023-01-30T00:02:48Z
```

Le certificat a expiré. En plus l'erreur nous indique que nous sommes en 2025 au lieu de 2024.

On peut aussi constater le problème de certificat avec `openssl` :

```console
admin@i-08f438fe20e16868c:/etc/default$ openssl s_client -connect 127.0.0.1:2379
CONNECTED(00000003)
Can't use SSL_get_servername
depth=0 C = AU, ST = Some-State, O = Internet Widgits Pty Ltd, CN = localhost
verify error:num=10:certificate has expired
notAfter=Jan 30 00:02:48 2023 GMT
verify return:1
depth=0 C = AU, ST = Some-State, O = Internet Widgits Pty Ltd, CN = localhost
notAfter=Jan 30 00:02:48 2023 GMT
verify return:1
---
Certificate chain
0 s:C = AU, ST = Some-State, O = Internet Widgits Pty Ltd, CN = localhost
i:C = AU, ST = Some-State, O = Internet Widgits Pty Ltd, CN = localhost
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIDkzCCAnugAwIBAgIUH9str4OD0GJuoYSEBWSMjLvDZyIwDQYJKoZIhvcNAQEL
BQAwWTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDESMBAGA1UEAwwJbG9jYWxob3N0MB4X
DTIyMTIzMTAwMDI0OFoXDTIzMDEzMDAwMDI0OFowWTELMAkGA1UEBhMCQVUxEzAR
BgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5
IEx0ZDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
MIIBCgKCAQEA4Q6WAutMU7NwZNVedwkkFu2vElGXt4UNhraRauCtD9XzP7RSm8UG
IXg5ddqFhOmi06LtSybimbA9K9763y5T5ncpluuYBN+Z9h8t83ZRV+QYW3gO5YRD
WfZjIRBhHXW4cfHOu2oOJd0rD95V87p1u1zxuqbDjh+4vWvgzzyuCRqlWyuKPmGk
XbmM4+qxlq62VhukhL1q46DKmSBE9zL1Oe23bermvp8XSPdfaWgNx4ChitJddvV4
eXOQw6VmA9Lf/WibMbYaubwsjhx+y2du20GcDqG8wk0IO2SyLgZrLsV/JiGqBnT2
49u33gDW+CP/2YUlPCURAkxt4sftu4sKeQIDAQABo1MwUTAdBgNVHQ4EFgQUiXpO
MNVRg1O+yM+Gvvw2TjN/zX0wHwYDVR0jBBgwFoAUiXpOMNVRg1O+yM+Gvvw2TjN/
zX0wDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAJlr9IQXzWfZo
PVwYu1hZTWkCR3UUKy9mvy3t5JX+2evQXZOhDfycq6CNkxfg6EXEjhqPrmoSosMU
Z9miIvbQMyWn4o6ORQpE3wacJri6GhLBjpyNfoMQivJMhJ0BXUrGyvZPD+wQF2Jc
Iwhj45Xtn+wluh9AmqCGy6S/Zf1QNjdnpbFImwzviuY/lqHhnSsIPQTaX5wYxrER
UbryzP5/4HF9kHEQJXxeHS3/URIp8otpviq3H7UODHeIviZgLdBtJGlkBXmub30p
7xgnGw/YHOlJcxUes0u8kbiTUQvFPj2OS0oYpV/txHvdiC9lqmfxcE28smTdMoV9
1F4bJMqqSQ==
-----END CERTIFICATE-----
subject=C = AU, ST = Some-State, O = Internet Widgits Pty Ltd, CN = localhost

issuer=C = AU, ST = Some-State, O = Internet Widgits Pty Ltd, CN = localhost

---
No client certificate CA names sent
Peer signing digest: SHA256
Peer signature type: RSA-PSS
Server Temp Key: X25519, 253 bits
---
SSL handshake has read 1475 bytes and written 363 bytes
Verification error: certificate has expired
--- snip ---
```

Le programme `etcd` est lancé avec des options permettant d'utiliser un certificat SSL :

```console
admin@i-08f438fe20e16868c:/etc/default$ ps aux | grep etcd
etcd 578 0.8 5.2 11729040 24668 ? Ssl 17:17 0:04 /usr/bin/etcd --cert-file /etc/ssl/certs/localhost.crt --key-file /etc/ssl/certs/localhost.key --advertise-client-urls=https://localhost:2379 --listen-client-urls=https://localhost:2379
```

Tout est lancé depuis systemd :

```console
root@i-08f438fe20e16868c:/etc/default# cat ../systemd/system/etcd2.service
[Unit]
Description=etcd - highly-available key value store
Documentation=https://etcd.io/docs
Documentation=man:etcd
After=network.target
Wants=network-online.target

[Service]
Environment=DAEMON_ARGS=
Environment=ETCD_NAME=%H
Environment=ETCD_DATA_DIR=/var/lib/etcd/default
EnvironmentFile=-/etc/default/%p
Type=notify
User=etcd
PermissionsStartOnly=true
#ExecStart=/bin/sh -c "GOMAXPROCS=$(nproc) /usr/bin/etcd $DAEMON_ARGS"
ExecStart=/usr/bin/etcd $DAEMON_ARGS \
--cert-file /etc/ssl/certs/localhost.crt \
--key-file /etc/ssl/certs/localhost.key \
--advertise-client-urls=https://localhost:2379 \
--listen-client-urls=https://localhost:2379
Restart=on-abnormal
#RestartSec=10s
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
Alias=etcd2.service
```

J'ai d'abord tenté de supprimer toutes les options données à etcd afin qu'il écoute en _clair_.

Malgré cela le client continuait de tomber sur un certificat... étrange.

J'ai donc plutôt choisi de mettre le certificat auto-signé à jour.

Déjà, il fallait corriger la date du système qui avance d'une année :

```bash
sudo date -s "last year"
```

Puis régénérer un certificat :

```console
admin@i-0b35d84e135f65ac8:/$ sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/certs/localhost.key -out /etc/ssl/certs/localhost.crt
Generating a RSA private key
............+++++
....+++++
writing new private key to '/etc/ssl/certs/localhost.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:localhost
Email Address []:
admin@i-0b35d84e135f65ac8:/$ sudo systemctl restart etcd2
admin@i-0b35d84e135f65ac8:/$ etcdctl get foo
Error: client: etcd cluster is unavailable or misconfigured; error #0: x509: certificate has expired or is not yet valid: current time 2024-03-02T17:53:17Z is after 2023-01-30T00:02:48Z

error #0: x509: certificate has expired or is not yet valid: current time 2024-03-02T17:53:17Z is after 2023-01-30T00:02:48Z
```

C'est la grosse claque : le serveur continue d'utiliser l'ancien certificat alors qu'on a écrasé les fichiers... WTF !

La blague qui était en place sur ce challenge, c'est qu'une règle iptables redirige le port de `etcd` vers un Nginx qui utilise le vieux certificat :

```console
admin@i-02f3860338fe0d7a3:/$ sudo iptables -t nat -L OUTPUT --line-numbers
Chain OUTPUT (policy ACCEPT)
num target prot opt source destination
1 REDIRECT tcp -- anywhere anywhere tcp dpt:2379 redir ports 443
2 DOCKER all -- anywhere !ip-127-0-0-0.us-east-2.compute.internal/8 ADDRTYPE match dst-type LOCAL
```

Une fois la règle retirée :

```bash
sudo iptables -t nat -D OUTPUT 1
```

On pouvait finalement accéder aux données.

```console
admin@i-02f3860338fe0d7a3:/$ sudo systemctl restart etcd2
admin@i-02f3860338fe0d7a3:/$ etcdctl get foo
bar
```
Loading

0 comments on commit 464514e

Please sign in to comment.