generated from cotes2020/chirpy-starter
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add some solutions for SadServers Medium challenges
- Loading branch information
Showing
8 changed files
with
1,180 additions
and
1 deletion.
There are no files selected for viewing
172 changes: 172 additions & 0 deletions
172
_posts/2024-02-03-Solution-du-challenge-Cape-Town-de-SadServers.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
196
_posts/2024-02-03-Solution-du-challenge-Lisbon-de-SadServers.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
``` |
Oops, something went wrong.