[SadServers] 解説 "Karakorum": WTFIT – What The Fun Is This?
"Karakorum": WTFIT – What The Fun Is This?
SadServersの "Karakorum": WTFIT – What The Fun Is This? の解説です。
SadServers って何? って人は、 SadServers解説 を見てください。
一言でいうと、LeetCode (コーディング問題集) の Linuxサーバ設定版のようなものです。
問題
問題を見ていきます。 >
の箇所は DeepLでの翻訳です。
Scenario: "Karakorum": WTFIT – What The Fun Is This?
Level: Hard
Description: There's a binary at /home/admin/wtfit that nobody knows how it works or what it does ("what the fun is this"). Someone remembers something about wtfit needing to communicate to a service in order to start. Run this wtfit program so it doesn't exit with an error, fixing or working around things that you need but are broken in this server. (Note that you can open more than one web "terminal").
> /home/admin/wtfitにバイナリがありますが、誰もそれがどう動くのか、何をするのか知りません(「これは何が面白いんだ」)。誰かが、wtfitが起動するためにサービスと通信する必要があることを何かで覚えているのです。このwtfitプログラムがエラーで終了しないように実行し、必要だがこのサーバーでは壊れているものを修正したり、回避したりします。(複数のウェブ「端末」を開くことができることに注意してください)。
Test: Running /home/admin/wtfit returns OK.
Time to Solve: 20 minutes.
OS: Debian 11
/home/admin/wtfit
というプログラムを実行して、 OK
が表示させるということです。
解説
早速、/home/admin/wtfit
を実行します。
admin@ip-172-31-47-197:/$ /home/admin/wtfit
bash: /home/admin/wtfit: Permission denied
Permission(権限)が無いため動きません。
ls -l
で、 /home/admin/wtfit
の権限を確認します。
admin@ip-172-31-47-197:/$ ls -l /home/admin/wtfit
-rw-r--r-- 1 admin admin 6381234 Sep 13 18:17 /home/admin/wtfit
-rw-r--r--r
となっており、4文字目が -
で x
ではないため、実行権限がありません。
chmod +x
で、実行権限を与えます。
admin@ip-172-31-47-197:/$ chmod +x /home/admin/wtfit
bash: /usr/bin/chmod: Permission denied
おっと、 /usr/bin/chmod
も Permission(権限)が無いと言われます。
こちらも ls -l
で権限を確認します。
admin@ip-172-31-45-197:~$ ls -l /usr/bin/chmod
-rw-r--r-- 1 root root 64448 Sep 24 2020 /usr/bin/chmod
確かに、 /usr/bin/chmod
も実行権限がありません。
chmod
が使えない状況で 実行権限を与える方法をググると、 How to execute Linux binary without execute permission の方法が見つかったので、これを試します。
# /lib64/ld-linux-x86-64.so.2 で chmod を実行。 正しく動いています。
admin@ip-172-31-45-197:~$ /lib64/ld-linux-x86-64.so.2 /usr/bin/chmod
/usr/bin/chmod: missing operand
Try '/usr/bin/chmod --help' for more information.
# chmod で、chmod に 実行権限を与えます。
admin@ip-172-31-45-197:~$ sudo /lib64/ld-linux-x86-64.so.2 /usr/bin/chmod +x /usr/bin/chmod
# 確認
admin@ip-172-31-45-197:~$ ls -l /usr/bin/chmod
-rwxr-xr-x 1 root root 64448 Sep 24 2020 /usr/bin/chmod
chmod
が動くようになったので、改めて、 /home/admin/wtfit
に実行権限を与えて、実行します。
# /home/admin/wtfitに 実行権限を与える。
admin@ip-172-31-45-197:~$ ./chmod +x /home/admin/wtfit
# /home/admin/wtfitを実行
admin@ip-172-31-45-197:~$ /home/admin/wtfit
ERROR: can't open config file
エラーとなりました。
ERROR: can't open config file
config fileが openできないと言っています。 config file とは具体的にどのファイルのことでしょうか?
それを調べるために strace
コマンドで、/home/admin/wtfit
プログラムを調べます。
strace
コマンドは、プログラムがどのようなシステムコールを呼び出しているかを調べることができるツールです。 参考
admin@ip-172-31-45-197:~$ cd /home/admin
admin@ip-172-31-45-197:~$ strace ./wtfit
rt_sigreturn({mask=[]}) = 0
futex(0xc000034548, FUTEX_WAKE_PRIVATE, 1) = 1
futex(0xc000034548, FUTEX_WAKE_PRIVATE, 1) = 1
futex(0xc000034548, FUTEX_WAKE_PRIVATE, 1) = 1
fcntl(0, F_GETFL) = 0x8002 (flags O_RDWR|O_LARGEFILE)
futex(0xc000034548, FUTEX_WAKE_PRIVATE, 1) = 1
mmap(NULL, 262144, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fed4b1bc000
fcntl(1, F_GETFL) = 0x8002 (flags O_RDWR|O_LARGEFILE)
fcntl(2, F_GETFL) = 0x8002 (flags O_RDWR|O_LARGEFILE)
openat(AT_FDCWD, "/home/admin/wtfitconfig.conf", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
write(1, "ERROR: can't open config file\n", 30ERROR: can't open config file
) = 30
exit_group(1) = ?
+++ exited with 1 +++
openat(AT_FDCWD, "/home/admin/wtfitconfig.conf", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
write(1, "ERROR: can't open config file\n", 30ERROR: can't open config file
) = 30
/home/admin/wtfitconfig.conf
を開こうとしています。
touch
で/home/admin/wtfitconfig.conf
を作り、再度実行します。
# /home/admin/wtfitconfig.conf ファイルを作成
admin@ip-172-31-45-179:~$ touch /home/admin/wtfitconfig.conf
# 再度 /home/admin/wtfitを実行
admin@ip-172-31-45-179:~$ ./wtfit
ERROR: can't connect to server
次はサーバに接続できないとのエラーが出ています。
再び、strace
で確認します。
admin@ip-172-31-45-179:~$ strace ./wtfit
close(3) = 0
futex(0xc000034548, FUTEX_WAKE_PRIVATE, 1) = 1
socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, IPPROTO_IP) = 3
connect(3, {sa_family=AF_INET, sin_port=htons(7777), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 EINPROGRESS (Operation now in progress)
epoll_ctl(4, EPOLL_CTL_ADD, 3, {EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLET, {u32=983903976, u64=139935313374952}}) = 0
write(6, "\0", 1) = 1
futex(0xc000034548, FUTEX_WAKE_PRIVATE, 1) = 1
getsockopt(3, SOL_SOCKET, SO_ERROR, [ECONNREFUSED], [4]) = 0
futex(0xc000034548, FUTEX_WAKE_PRIVATE, 1) = 1
epoll_ctl(4, EPOLL_CTL_DEL, 3, 0xc0000b5324) = 0
close(3) = 0
futex(0xc000034548, FUTEX_WAKE_PRIVATE, 1) = 1
futex(0xc000034548, FUTEX_WAKE_PRIVATE, 1) = 1
write(1, "ERROR: can't connect to server\n", 31ERROR: can't connect to server
) = 31
exit_group(1) = ?
+++ exited with 1 +++
connect(3, {sa_family=AF_INET, sin_port=htons(7777), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 EINPROGRESS (Operation now in progress)
IPアドレス 127.0.0.1
、 ポート番号 7777
にTCP接続しようとしていることがわかります。
問題ページの Open the server terminal in a new window.
をクリックして、ターミナルをもう一つ開き、nc
ツールで、 127.0.0.1:7777
のサーバを立てます。
# 2番目のターミナル
# 7777ポートで接続を待ち受ける。
admin@ip-172-31-45-179:/$ nc -l 7777
その後、最初のターミナル(1番目のターミナル)で、 /home/admin/wtfit
コマンドを実行すると、次のように表示されます。
# 2番目のターミナル
admin@ip-172-31-45-179:/$ nc -l 7777
GET / HTTP/1.1
Host: localhost:7777
User-Agent: Go-http-client/1.1
Accept-Encoding: gzip
これは、おなじみのHTTPリクエストです。 /home/admin/wtfit
は HTTPクライアントのようです。
手動でHTTPレスポンスを返しましょう。
# 2番目のターミナル
admin@ip-172-31-45-179:/$ nc -l 7777
GET / HTTP/1.1
Host: localhost:7777
User-Agent: Go-http-client/1.1
Accept-Encoding: gzip
HTTP/1.1 200 OK # これを入力する。
HTTP/1.1 200 OK
を入力すると、1番目のターミナルで動作している/home/admin/wtfit
側に、OK.
が表示されます。
1番目のターミナル
admin@ip-172-31-45-179:~$ ./wtfit
OK.
これで良さそうです。
2番目のターミナルで、 nc -l 7777
を入力し、Check My Solution
をクリックします。
GET / HTTP/1.1
Host: localhost:7777
User-Agent: Go-http-client/1.1
Accept-Encoding: gzip
が表示された直後に HTTP/1.1 200 OK
を入力すればよいのですが、駄目です。Solution is incorrect or the server agent can't respond properly (something broke).
をなります。人手でレスポンスを入力するのでは間に合わないようです。
python3 が使えるようなので、python3 で、HTTPサーバを起動させます。
# 2番目のターミナル
admin@ip-172-31-45-179:/$ python3 -m http.server 7777
Serving HTTP on 0.0.0.0 port 7777 (http://0.0.0.0:7777/) ...
改めて、 Check My Solution
をクリックすると、パスします。
Discussion