🔧

SadServers Writeups

#tech#Linux

2023-11-1

SadServersというのがあり,Linuxサーバーのトラブルシューティングを行える.これを解いたのでその解法を記載する.解き終わってかつ,日本語を書く気持ちが出たものは順次ここに追記していく.

Writeups

Saint John [Easy]

$ sudo rm /var/log/bad.log

Saskatoon [Easy]

$ cut -d- -f1 /home/admin/access.log | sort | uniq -c | sort

で一番下に最も多いreq数のやつが来るからこれを適当に書き込むと良い

Santiago [Easy]

2問構成.まず/home/admin直下の.txtなファイルに対して,Aliceが登場する行の数を見る必要があるが,xargsを使うと便利.

$ ls *.txt | xargs grep -c Alice

これの出力を足し合わせて1問目クリア.次2問目.問題文曰く,Aliceの出現回数が1なファイルを見ると良くて,これが一意なので適当にlessで表示している最中に"/Alice"でAliceが存在する行まで移動して次の行を見ると答えが書いてあるのでクリア.

Taipei [Easy]

ポートノッキングされたサーバーがlocalhost:80にあるから,これを開けるようにする.

$ curl localhost -v
*   Trying 127.0.0.1:80...
* connect to 127.0.0.1 port 80 failed: Connection refused
* Failed to connect to localhost port 80: Connection refused
* Closing connection 0
curl: (7) Failed to connect to localhost port 80: Connection refused

まあそうだよねって気持ちになる.とりあえずポートスキャンしてみる:

$ nmap localhost
Starting Nmap 7.80 ( https://nmap.org ) at 2024-01-04 05:03 UTC
Nmap scan report for localhost (127.0.0.1)
Host is up (0.00012s latency).
Not shown: 998 closed ports
PORT     STATE SERVICE
22/tcp   open  ssh
8080/tcp open  http-proxy

Nmap done: 1 IP address (1 host up) scanned in 0.07 seconds

22と8080が空いている.knockdに付属するknockコマンドを用いると特定のポートをノックすることができる:

$ knock localhost 22
$ curl localhost
Who is there?

Lhasa [Easy]

スペース区切りで1行に2つの数字が書かれたtxtがあるのでこの後者の方だけの平均を取る.

Tip: There's bc, Python3, Golang and sqlite3 installed in this VM.とあるが,普通にシェルワンライナーができそう -> できた:

$ awk '{sum+=$2} END {printf "%.2f\n", int(sum*100/NR)/100}' ~/scores.txt > ~/solution

これで~/solutionのMD5が問題に書いてあるものと一致するのでクリア.

Manhattan [Medium]

psqlに書き込みができないらしいが頑張りを発揮するとできるようになるらしい.ご丁寧にHelpful Postgres information: it's a service that listens to a port (:5432) and writes to disk in a data directory,などと書いてあるので問題文を読んでいる際にディスクが一杯なのかな~という推測が立つ.実際にこれが原因なのかを確かめるには例えば次のようにする:

# sudo -u postgres psql -c "insert into persons(name) values ('jane smith');" -d dt
psql: error: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: No such file or directory
        Is the server running locally and accepting connections on that socket?
# cat /var/log/postgresql/postgresql-14-main.log
2023-09-01 12:39:47.066 UTC [651] FATAL:  could not create lock file "postmaster.pid": No space left on device
pg_ctl: could not start server
Examine the log output.

つまり適当にinsertしようとしてみてからログを見に行く.実際にはpsqlのデフォルトのログ置き場である/var/log/pgsqlではなく/var/log/postgresqlにログが置かれていたので一度実行に失敗した.

まあけど要はディスクがないんだねってことでdfすると/opt/pgdataのUse%が100なので適当に中身を消してあげてからsystemctl restart postgresqlしてinsertするとできるようになるのでクリア.

Tokyo [Medium]

127.0.0.1:80に立てたサイトがローカルから叩いても何の返答も無いらしい.案の定頑張りを発揮すれば解けるらしいのでFWが悪さをしている可能性を考慮してiptables -Lすると

Chain INPUT (policy ACCEPT)
target prot opt source destination
DROP tcp -- anywhere anywhere tcp dpt:http

となっていてはい.めんどいのでiptables -Fするとこの辺の設定を全て吹き飛ばせて便利.

じゃあこれでいけるかな~と思って勢いよくcurlを叩くもForbiddenのページが返ってくる.ローカルなものなのでhtmlファイルの権限を確認しに行くと600でなんやねんという気持ちになってパーミッションを適当に変えて

# curl localhost:80

すると所望のレスポンスが返る.これここまで書いて思ったけど何で問題名が全部都市名なん?

Cape Town [Medium]

systemdで管理されたNginxにリクエストを送るもConnection refusedになるから直すと良いらしい.ので適当に

$ systemctl status nginx

してみるとunexpected ";" in /etc/nginx/sites-enabled/default:1らしいのでそうなんだという気持ちで/etc/nginx/sites-enabled/defaultから不要なセミコロンを消去してnginxを再起動してcurlするとInternal Server Error.ひょえー.

nginxのログを見たいので/var/log/nginx/error.logを見るとToo many open filesとのこと.これは/etc/systemd/system/nginx.serviceで設定できる(空にもできる)から見に行くと案の定LimitNOFILEが10になっているからこれを適当に998244353とかにするやんちゃをして再起動するとクリア.

Salta [Medium]

Dockernizeされたアプリケーションがあるからこれを動かしてね!ただしFor the solution to be valid, there should be only one running Docker container.だよ!らしい.まあDockerイメージ焼くだけで問題にならないのはそれはそう.

なのでまずは8888を取っているやつの正体を探る.これはcurl -vとかするとnginxであることが分かるので適当にsystemd stopしておく.これでConnection refusedになるのでこのポートが空いた.

次にDockerイメージを焼いて動かす.アプリケーションがあるディレクトリに移動して適当にdocker build & docker runするとコケる.曰くError: Cannot find module '/usr/src/app/serve.js'らしいのでDockerfile内で参照しているjsファイルが存在していない.似たような名前でserver.jsが存在するのでこれのtypoと判断し修正して動かす.まだ何かがおかしいので確認するとEXPOSE 8880になっている.使うのは8888なので修正して動かすと動作するようになる.

Venice [Medium]

シェルがコンテナ内で動いているのかVM内で動いているのかを判定してね!という問題.知らんかったのでググったけど例えば

$ ls -ali / | sed '2!d' |awk {'print $1'}

の結果が2だったらコンテナ外,そうでないならコンテナ内らしい.なるほどなあ.実際にはPodmanのコンテナ内部で想定解法は

cat /proc/1/environ|tr "\0" "\n"|grep container

らしい.まあDockerだと普通に/.dockerenvの有無だけで分かってしまうしなあ.

Oaxaca [Medium]

/home/admin/somefileがあるプロセスによって書き込みモードで開かれているらしいが,このプロセスを殺すことなくファイルを閉じる問題.

まずはどのプロセスが開いているのかを観察する:

$ lsof /home/admin/somefile
COMMAND PID  USER   FD   TYPE DEVICE SIZE/OFF   NODE NAME
bash    817 admin   77w   REG  259,1        0 272875 /home/admin/somefile

よってプロセスIDが817のbashがファイルディスクリプタ77番で開いているのを消せばよさそう.プロセスの保持するファイルディスクリプタは/proc以下に存在するから確認してみる:

$ ls /proc/817/fd
0  1  2  255  77

これを消すにはexecコマンドを用いるとできる:

$ exec 77<&-

これでlsofしても何も表示されないのでクリア.

Lisbon [Medium]

etcdという,KVSのサーバーがhttps://localhost:2379で動いているけど問題があるから修正して正しくバリューを返すようにする.

実際にetcdctl get fooをすると:

$ 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-12-03T08:27:59Z is after 2023-01-30T00:02:48Z

error #0: x509: certificate has expired or is not yet valid: current time 2024-12-03T08:27:59Z is after 2023-01-30T00:02:48Z

と言われ,SSL証明書が期限切れらしい.ということで現在のサーバー時間を確認してみると2024/12/3と言われた.これは確かに期限切れになるので:

$ sudo date -s "01/30 00:00 2023"
Mon Jan 30 00:00:00 UTC 2023
admin@ip-10-0-0-138:/$ date
Mon Jan 30 00:00:01 UTC 2023
admin@ip-10-0-0-138:/$ etcdctl get foo
Error:  client: response is invalid json. The endpoint is probably not valid etcd cluster endpoint.

う~ん,何やら変わりおった.なんですかという気持ちでverboseしてほしい:

$ curl https://localhost:2379/v2/keys/foo -v
*   Trying 127.0.0.1:2379...
* Connected to localhost (127.0.0.1) port 2379 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use http/1.1
* Server certificate:
*  subject: C=AU; ST=Some-State; O=Internet Widgits Pty Ltd; CN=localhost
*  start date: Dec 31 00:02:48 2022 GMT
*  expire date: Jan 30 00:02:48 2023 GMT
*  common name: localhost (matched)
*  issuer: C=AU; ST=Some-State; O=Internet Widgits Pty Ltd; CN=localhost
*  SSL certificate verify ok.
> GET /v2/keys/foo HTTP/1.1
> Host: localhost:2379
> User-Agent: curl/7.74.0
> Accept: */*
>
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
* Mark bundle as not supporting multiuse
< HTTP/1.1 404 Not Found
< Server: nginx/1.18.0
< Date: Mon, 30 Jan 2023 00:00:55 GMT
< Content-Type: text/html
< Content-Length: 153
< Connection: keep-alive
<
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.18.0</center>
</body>
</html>
* Connection #0 to host localhost left intact

けったいなので,Server: nginx/1.18.0などと宣っている.普通にetcdが返せやという気持ちになるのでNATの設定を確認する:

$ sudo /usr/sbin/iptables -L -t nat
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination
DOCKER     all  --  anywhere             anywhere             ADDRTYPE match dst-type LOCAL

Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
REDIRECT   tcp  --  anywhere             anywhere             tcp dpt:2379 redir ports 443
DOCKER     all  --  anywhere            !ip-127-0-0-0.us-east-2.compute.internal/8  ADDRTYPE match dst-type LOCAL

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
MASQUERADE  all  --  ip-172-17-0-0.us-east-2.compute.internal/16  anywhere

Chain DOCKER (2 references)
target     prot opt source               destination
RETURN     all  --  anywhere             anywhere

見ると,ポート2379から443へのリダイレクトが走っているのでこれが原因っぽそう.設定をiptables -Fとかで吹き飛ばしてクリア.

Kihei [Medium]

~/kiheiを実行しようとすると死ぬから死なないようにするタスク.

まず普通に動かしてpanicすることを確認.無いかな~と思って-h付けるとあって,ご丁寧に-vが存在するらしい.ほえ~

admin@i-00ea3683be33c9605:~$ ./kihei -v
Creating file /home/admin/data/newdatafile with size 1.5GB...
panic: exit status 1

goroutine 1 [running]:
main.main()
        ./main.go:64 +0x47d

じゃあこの1.5GB作ろうとしているのがあかんねって気持ちになってdfとかしてみると

$ df
Filesystem      1K-blocks    Used Available Use% Mounted on
udev               221828       0    221828   0% /dev
tmpfs               46636     368     46268   1% /run
/dev/nvme0n1p1    8026128 6354488   1242384  84% /
tmpfs              233168      12    233156   1% /dev/shm
tmpfs                5120       0      5120   0% /run/lock
/dev/nvme0n1p15    126678    6016    120662   5% /boot/efi

なんや/dev/nvme0n1p1って気持ちになってlsblkする:

$ lsblk
NAME         MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
nvme0n1      259:0    0    8G  0 disk
├─nvme0n1p1  259:2    0  7.9G  0 part /
├─nvme0n1p14 259:3    0    3M  0 part
└─nvme0n1p15 259:4    0  124M  0 part /boot/efi
nvme1n1      259:1    0    1G  0 disk
nvme2n1      259:5    0    1G  0 disk

/dev/nvme0n1p1というやつが7.9GB食っている.これをいい感じにshirinkできれば空き領域が広がりそう:

$ sudo tune2fs -m1 /dev/nvme0n1p1
tune2fs 1.46.2 (28-Feb-2021)
Setting reserved blocks percentage to 1% (20643 blocks)

これで./kiheiするとpanicせずに実行できる.

Marrakech [Medium]

スペースか改行か.,:;のいずれかで区切られたテキスト群があるから2番目に多く出てくる単語を見つけるタスク.ただし大文字小文字は区別しないらしい.

Lhasaと同じで,PythonやGolangは入っているらしいが,シェルワンライナー縛りができそう -> できた:

$ tr -s '[:space:]' '\n' < frankestein.txt | tr '[:upper:]' '[:lower:]' | grep -E -o '\b[^,.;:"]+\b' | tr '[:lower:]' '[:upper:]' | sort | uniq -c | sort -nr | sed -n '2s/^[ \t]*[0-9]*[ \t]*//p' > ~/mysolution

Bern [Hard]

WordPressのDockerコンテナがMariaDBのコンテナに接続できないと言っている.ので問題文にある通りのコマンドで接続してみようとする:

$ sudo docker exec wordpress mysqladmin -h mysql -u root -ppassword ping
mysqladmin: connect to server at 'mysql' failed
error: 'Unknown MySQL server host 'mysql' (-2)'
Check that mysqld is running on mysql and that the port is 3306.
You can check this by doing 'telnet mysql 3306'

DBのコンテナが動いているかを確認したいのでdocker psしてみる:

$ sudo docker ps
CONTAINER ID   IMAGE            COMMAND                  CREATED         STATUS          PORTS                    NAMES
6ffb084b515c   wordpress:sad    "docker-entrypoint.s…"   16 months ago   Up 22 seconds   0.0.0.0:80->80/tcp       wordpress
0eef97284c44   mariadb:latest   "docker-entrypoint.s…"   16 months ago   Up 22 seconds   0.0.0.0:3306->3306/tcp   mariadb

動いてはいそう.けどよしなにdocker-compose.yml作ってdocker-compose upすれば終わりな気配はあるのでとりあえず2つのコンテナを止める:

$ sudo docker stop mariadb wordpress
mariadb
wordpress
$ sudo docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

次にdocker-compose.ymlを作成する.このときのMYSQL_ROOT_PASSWORDなどの環境変数はコンテナが動いている際に適当にdocker inspectすることで確認した:

version: '3'

services:
    mysql:
        image: mariadb:latest
        container_name: mysql
        hostname: mysql
        ports:
            - 3306:3306
        environment:
            MYSQL_ROOT_PASSWORD: password
            MYSQL_DATABASE: wordpress
    wordpress:
        depends_on:
            - mysql
        image: wordpress:sad
        container_name: wordpress
        hostname: wordpress
        ports:
            - 80:80
        environment:
            WORDPRESS_DB_USER: root
            WORDPRESS_DB_PASSWORD: password

これでdocker-compose upする.

Hong-Kong [Hard]

Manhattanと同じように,psqlに対してinsertができないのを解決するタスク.

まずpsqlが立っているかどうかを確かめる:

# ps aux | grep postgre
root       703  0.0  0.1   4832   876 pts/0    S+   04:52   0:00 grep postgre

立っていないのでsystemctl start postgresqlしてから再度確認しても立っていない.このためログを確認する:

# journalctl -p err
-- Logs begin at Fri 2024-01-05 04:51:45 UTC, end at Fri 2024-01-05 04:54:11 UTC. --
Jan 05 04:51:45 ip-172-31-25-11 kernel: ena 0000:00:05.0: LLQ is not supported Fallback to host mode pol
Jan 05 04:51:50 ip-172-31-25-11 systemd[1]: Failed to start PostgreSQL Cluster 14-main.
Jan 05 04:53:15 ip-172-31-25-11 systemd[1]: Timed out waiting for device /dev/xvdb.
Jan 05 04:53:26 ip-172-31-25-11 systemd[1]: Failed to start PostgreSQL Cluster 14-main.
lines 1-5/5 (END)

/dev/xvdbを待ってタイムアウトしているから,これはなんやということでlsblkしてみる:

# lsblk -f

/dev/xvdbなんぞ無いから当然タイムアウトになる.ここで代わりに/dev/nvme0n1などを使うことができそう.

systemdがどのデバイスを用いるかの設定は,

Roseau [Hard]

ローカルで動いているApacheのサーバー内に秘匿されている情報を取り出したい.この問題の特徴として,次のようなものが問題文に書かれている:

Also note that the password crackers Hashcat and Hydra are installed from packages and John the Ripper binaries have been built from source in /home/admin/john/run

ということはどこかでブルートフォースしそうだなというあたりをつけてVMを開く.

まずApacheのサーバーにリクエストを飛ばしてみる:

$ curl localhost:80 -v
*   Trying 127.0.0.1:80...
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET / HTTP/1.1
> Host: localhost
> User-Agent: curl/7.74.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 401 Unauthorized
< Date: Fri, 08 Dec 2023 12:46:19 GMT
< Server: Apache/2.4.54 (Debian)
< WWW-Authenticate: Basic realm="Protected Content"
< Content-Length: 456
< Content-Type: text/html; charset=iso-8859-1
<
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>401 Unauthorized</title>
</head><body>
<h1>Unauthorized</h1>
<p>This server could not verify that you
are authorized to access the document
requested.  Either you supplied the wrong
credentials (e.g., bad password), or your
browser doesn't understand how to supply
the credentials required.</p>
<hr>
<address>Apache/2.4.54 (Debian) Server at localhost Port 80</address>
</body></html>
* Connection #0 to host localhost left intact

認証が通っていないらしい.Apacheの認証設定は/etc/apache2/sites-enabled/000-default.confにあり,BASIC認証をしている:

$ cat /etc/apache2/sites-enabled/000-default.conf
<VirtualHost *:80>
        ServerAdmin webmaster@localhost
        DocumentRoot /var/www/html
        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined


        <Directory "/var/www/html">
                AuthType Basic
                AuthName "Protected Content"
                AuthUserFile /etc/apache2/.htpasswd
                Require valid-user
        </Directory>
</VirtualHost>

このパスワードをハッシュ化したものは/etc/apache2/.htpasswdにあるといっている:

$ cat /etc/apache2/.htpasswd
carlos:$apr1$b1kyfnHB$yRHwzbuKSMyW62QTnGYCb0

このパスワードを破るとよさそう.これにはJohn the Ripperが使える:

$ ./john /etc/apache2/.htpasswd
Warning: detected hash type "md5crypt", but the string is also recognized as "md5crypt-long"
Use the "--format=md5crypt-long" option to force loading these as that type instead
Using default input encoding: UTF-8
Loaded 1 password hash (md5crypt, crypt(3) $1$ (and variants) [MD5 256/256 AVX2 8x3])
Will run 2 OpenMP threads
Proceeding with single, rules:Single
Press 'q' or Ctrl-C to abort, 'h' for help, almost any other key for status
Warning: Only 34 candidates buffered for the current salt, minimum 48 needed for performance.
Almost done: Processing the remaining buffered candidate passwords, if any.
0g 0:00:00:00 DONE 1/3 (2023-12-08 12:49) 0g/s 3613p/s 3613c/s 3613C/s Carlos1921..Carlos1900
Proceeding with wordlist:./password.lst
Enabling duplicate candidate password suppressor
chalet           (carlos)
1g 0:00:00:02 DONE 2/3 (2023-12-08 12:49) 0.4716g/s 31377p/s 31377c/s 31377C/s 050381..song
Use the "--show" option to display all of the cracked passwords reliably
Session completed.

carlosというユーザーのPWはchaletであることが分かる.これを使ってlocalhost:80にログインする:

$ curl localhost:80 -u "carlos:chalet"
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
 <head>
  <title>Index of /</title>
 </head>
 <body>
<h1>Index of /</h1>
  <table>
   <tr><th valign="top"><img src="/icons/blank.gif" alt="[ICO]"></th><th><a href="?C=N;O=D">Name</a></th><th><a href="?C=M;O=A">Last modified</a></th><th><a href="?C=S;O=A">Size</a></th><th><a href="?C=D;O=A">Description</a></th></tr>
   <tr><th colspan="5"><hr></th></tr>
<tr><td valign="top"><img src="/icons/unknown.gif" alt="[   ]"></td><td><a href="webfile">webfile</a></td><td align="right">2023-02-13 02:39  </td><td align="right">215 </td><td>&nbsp;</td></tr>
   <tr><th colspan="5"><hr></th></tr>
</table>
<address>Apache/2.4.54 (Debian) Server at localhost Port 80</address>
</body></html>

localhost:80/webfileに何かがありそうなので見てみると,何かのバイナリファイルが落ちてくるらしいから--ouputで受け取る:

$ curl localhost:80/webfile -u "carlos:chalet" --output res
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   215  100   215    0     0   209k      0 --:--:-- --:--:-- --:--:--  209k

これはzipファイルらしいのでunzipしようとするとPWがかかっている.なのでこれもJohn the Ripperにかけるとよさそう:

$ ./zip2john ~/res
ver 1.0 efh 5455 efh 7875 res/secret.txt PKZIP Encr: 2b chk, TS_chk, cmplen=29, decmplen=17, crc=AAC6E9AF ts=14E0 cs=14e0 type=0
res/secret.txt:$pkzip$1*2*2*0*1d*11*aac6e9af*0*44*0*1d*14e0*7307b809c29d0e4602770428f8f469ba44ff98065855e557f76e29e8d1*$/pkzip$:secret.txt:res::/home/admin/res
admin@i-0af09adc22e1edf02:~/john/run$ ./zip2john ~/res > ~/hash
ver 1.0 efh 5455 efh 7875 res/secret.txt PKZIP Encr: 2b chk, TS_chk, cmplen=29, decmplen=17, crc=AAC6E9AF ts=14E0 cs=14e0 type=0
admin@i-0af09adc22e1edf02:~/john/run$ ./john ~/hash
Using default input encoding: UTF-8
Loaded 1 password hash (PKZIP [32/64])
Will run 2 OpenMP threads
Proceeding with single, rules:Single
Press 'q' or Ctrl-C to abort, 'h' for help, almost any other key for status
Almost done: Processing the remaining buffered candidate passwords, if any.
0g 0:00:00:00 DONE 1/3 (2023-12-08 12:54) 0g/s 175033p/s 175033c/s 175033C/s Txtres1900..Tsecret1900
Proceeding with wordlist:./password.lst
Enabling duplicate candidate password suppressor
andes            (res/secret.txt)
1g 0:00:00:01 DONE 2/3 (2023-12-08 12:54) 0.8333g/s 469025p/s 469025c/s 469025C/s poussinet..nisa1234
Use the "--show" option to display all of the cracked passwords reliably
Session completed.

zipのPWが分かったから開けてクリア.

Monaco [Hard]

localhost:5000上のサーバーに存在するフォームに正しい文字列をポストしてflagをゲットするという内容.

Descriptionからだけだと何も分からないのでとりあえずcurlしてみる:

$ curl localhost:5000 -v
*   Trying 127.0.0.1:5000...
* Connected to localhost (127.0.0.1) port 5000 (#0)
> GET / HTTP/1.1
> Host: localhost:5000
> User-Agent: curl/7.74.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: Werkzeug/3.0.0 Python/3.9.2
< Date: Thu, 04 Jan 2024 04:16:57 GMT
< Content-Type: text/html; charset=utf-8
< Content-Length: 217
< Connection: close
<

        <form method="POST">
            <label for="password">Password:</label>
            <input type="password" id="password" name="password">
            <input type="submit" value="Submit">
        </form>
* Closing connection 0

Pythonで動いているのは分かるが,それ以上の情報が無いやねという気持ちになる.

分からんねの気持ちで何となくls -aすると

$ ls -a
.  ..  .ansible  .bash_history  .bash_logout  .bashrc  .config  .git  .profile  .ssh  agent

.gitがあるらしい.そうなんだということでgit statusするとPythonファイルが1つ消されているらしい.中身を見てみる:

$ git diff
diff --git a/webserver_v1.py b/webserver_v1.py
deleted file mode 100755
index e1ac37d..0000000
--- a/webserver_v1.py
+++ /dev/null
@@ -1,29 +0,0 @@
-from flask import Flask, request
-import os
-
-app = Flask(__name__)
-
-
-@app.route('/', methods=['GET', 'POST'])
-def home():
-    if request.method == 'POST':
-        entered_password = request.form.get('password')
-        super_secret_password = os.environ.get('SUPERSECRETPASSWORD')
-
-        if entered_password == super_secret_password:
-            return 'Access granted!'
-            # DO STUFF HERE
-
-        return 'Access denied!'
-
-    return '''
-        <form method="POST">
-            <label for="password">Password:</label>
-            <input type="password" id="password" name="password">
-            <input type="submit" value="Submit">
-        </form>
-    '''
-
-
-if __name__ == '__main__':
-    app.run()

ほーん,$SUPERSECRETPASSWORDとの一致を見ているんやねという気持ちになるので勢いよく中身を見ようとしてみる:

$ echo $SUPERSECRETPASSWORD

そうなんだ.けど無いわけなくない?という気持ちになるからこれ以外の方法であるんだろうなの気持ちになる.

ところでシェルから起動したプロセスは,シェルと同一の環境変数を用いているとは限らない.実際にどのような環境変数を用いているかは/proc/${PID}/environを見ると良い.そのためにまずはlocalhost:5000上で動いているプロセスのPIDを知りたい:

$ lsof -i :5000
COMMAND PID  USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
python3 572 admin    3u  IPv4  11732      0t0  TCP localhost:5000 (LISTEN)

PIDは572だから次のようにして環境変数の一覧を得る:

$ cat /proc/572/environ
LANG=C.UTF-8PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binHOME=/home/adminLOGNAME=adminUSER=adminSHELL=/bin/bashINVOCATION_ID=af634a88cbb34fb596a836e07c4ede4aJOURNAL_STREAM=8:11516SUPERSECRETPASSWORD=bdFBkE4suaCy

$SUPERSECRETPASSWORDが分かったのでflagを入手しに行く:

$ curl -d "password=bdFBkE4suaCy" -XPOST localhost:5000
Access granted! Secret is QhyjuI98BBvf