変数管理がダルい!!!!!
皆さん、Hack The Boxをやるときには、IPアドレスやホスト名などを変数に入れて使用することがあると思います。
export IP=192.0.2.1
export RHOST=example.htb
そして、/etc/hostsを書き換えて、ブラウザとかでアクセスが出来るようにしますよね。
192.0.2.1 example.htb
これ、地味にめんどくないですか????
例えば、新しいタブを開いてリバースシェルを立ち上げるときも、
IP=192.0.2.1
nc -nlvp $IP
などとする必要があり地味にめんどいです(リバースシェルの待ち受け程度ならわざわざ変数で書いてないかも知れませんが、上記に限らずとも複数タブを使用する場面は割とありますよね)。
また、やっているマシンの有効期限が切れてしまうと、マシンを新しく作り直す必要があります。マシンを作り直すと、変数の設定や/etc/hostsの設定をイチからやり直さなければいけません!!!
私がとった方法
概要
ディレクトリごとに環境変数を管理できる、direnvというツールがあります。これを使って、HTBのマシンごとに変数を管理することにしました。
参照先ではわざわざmakeしてますが、今はaptで入れられます。
sudo apt install direnv
あまりお行儀のよい方法ではないかも知れませんが、このdirenvで使用される.envrcというファイルに、/etc/hostsの書き換えを行うシェルスクリプトを記述することにしました。
攻撃するマシンごとにディレクトリを作成し、以下のシェルスクリプトを.envrcというファイル名でディレクトリの中に保存します。すると、.envrcを作成したディレクトリ以下を、そのマシン専用の環境として使用することが出来ます。
# export IP=<IPアドレス>
export RHOSTS=<ホスト名(カンマ区切り)>
# example:
# export RHOSTS="test.htb"
# or
# export RHOSTS="test.htb,test.htc"
export LHOST=$(ip -4 addr show tun0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}')
IFS=',' read -ra RHOSTS_SPLIT <<< "$RHOSTS"
RHOSTS_ARR=()
for h in "${RHOSTS_SPLIT[@]}"; do
[ -n "$h" ] && RHOSTS_ARR+=("$h")
done
if [[ "$RHOSTS" == *","* ]]; then
for i in "${!RHOSTS_ARR[@]}"; do
export "RHOSTS$i=${RHOSTS_ARR[$i]}"
done
else
if [ -n "$RHOSTS" ]; then
export RHOSTS0="$RHOSTS"
fi
fi
if [ ${#RHOSTS_ARR[@]} -gt 0 ]; then
for host in "${RHOSTS_ARR[@]}"; do
[ -n "$host" ] && sudo sed -i -E "/[[:space:]]$host([[:space:]]|$)/d" /etc/hosts
done
fi
if [ -n "$IP" ]; then
sudo sed -i -E "/^$IP[[:space:]]+/d" /etc/hosts
fi
if [ -z "$IP" ] || [ ${#RHOSTS_ARR[@]} -eq 0 ]; then
echo "[*] Cleanup complete (IP or RHOSTS was empty)."
return 0
fi
NEW_ENTRY="$IP ${RHOSTS_ARR[*]}"
if grep -q "127.0.1.1" /etc/hosts; then
sudo sed -i "/127.0.1.1/a $NEW_ENTRY" /etc/hosts
else
sudo sed -i "1i $NEW_ENTRY" /etc/hosts
fi
echo "[*] Updated /etc/hosts: $NEW_ENTRY"
使い方の流れ
1. .envrcを作成する
mkdir htbenv
cd htbenv
vim .envrc #上記の内容をコピーして貼り付けます
2. GitHubなどでアップロードしておく
3. マシン名をディレクトリにして、リポジトリをクローンする
マシン名が「HappyMachine」とかであれば、
git clone git@github.com:<ユーザ名>/<リポジトリ名>.git ~/happy_machine
4. クローンしたディレクトリに入る
cd ~/happy_machine
5. IPやRHOSTSを書き換える
vimなどのテキストエディタで、.envrcの上から2行(export IPとexport RHOSTSの値)を書き換えます。
export IP=192.0.2.1
# 複数のホスト名を使いたい場合
export RHOSTS=(example.htb example.htc)
# 単一ホストの場合
export RHOSTS=example.htb
後述しますが、ここで設定したIP/RHOSTSの値は、/etc/hoostsの書き換えの際に使用されます。IP/RHOSTSのどちらかが空の場合は、/etc/hostsにそのIPアドレス/ホスト名のエントリが書かれないようになっています。したがって、nmapの段階など、まだホスト名がわからないときは、RHOSTSを空欄にしておきましょう。
6. direnv allowする
direnv allow
今後そのディレクトリの中では、以下の環境変数が使用できます。
IP: 攻撃先のIPアドレス
RHOSTS: 攻撃先のホスト名(カンマ区切り)
RHOSTS数字(例:RHOSTS0,RHOSTS1): RHOSTSをカンマで区切った各要素
LHOST: 攻撃元のホスト名(リバースシェルなどで使用)
また、/etc/hostsに、上記のIPアドレスとホスト名の組が登録されます。
今後IPやRHOSTSを書き換えたい場合は、5.6.の手順を繰り返せばOKです(IP/RHOSTS書き換え→direnv allow)。
スクリプトの解説
このスクリプトは、指定されたIPアドレスと1つ以上のホスト名(RHOSTS)を /etc/hosts に登録します。既存の古いエントリーを削除してから新しい情報を挿入するため、ファイルが汚れるのを防ぐ設計になっています。
1. 環境変数のセットアップ
export LHOST=$(ip -4 addr show tun0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}')
- LHOST: VPN(
tun0インターフェース)の自分自身のIPアドレスを自動取得します。 - リバースシェルの待ち受け時などに利用することを想定しています。
2. RHOSTS の配列作成
RHOSTS_ARR=()
for h in "${RHOSTS_SPLIT[@]}"; do
[ -n "$h" ] && RHOSTS_ARR+=("$h")
done
if [[ "$RHOSTS" == *","* ]]; then
for i in "${!RHOSTS_ARR[@]}"; do
export "RHOSTS$i=${RHOSTS_ARR[$i]}"
done
else
if [ -n "$RHOSTS" ]; then
export RHOSTS0="$RHOSTS"
fi
fi
マシンによっては、ひとつのIPアドレスに対して複数のホスト名を使用することがあります。これに対応するために、ホスト名をカンマ区切りで複数登録できるようにしています。
3. 重複・競合エントリの削除
冪等性を保つために、まずは重複・競合エントリを削除します。
ホスト名による削除
if [ ${#RHOSTS_ARR[@]} -gt 0 ]; then
for host in "${RHOSTS_ARR[@]}"; do
[ -n "$host" ] && sudo sed -i -E "/[[:space:]]$host([[:space:]]|$)/d" /etc/hosts
done
fi
IPアドレスによる削除
if [ -n "$IP" ]; then
sudo sed -i -E "/^$IP[[:space:]]+/d" /etc/hosts
fi
4. 処理の分岐(削除のみか、挿入まで行うか)
if [ -z "$IP" ] || [ ${#RHOSTS_ARR[@]} -eq 0 ]; then
echo "[*] Cleanup complete (IP or RHOSTS was empty)."
return 0
fi
- IPまたはRHOSTSのどちらかが空の場合: ここまでの削除処理だけを実行して終了します。
- 両方揃っている場合: 次の挿入ステップへ進みます。
5. 新しいエントリの挿入
NEW_ENTRY="$IP ${RHOSTS_ARR[*]}"
if grep -q "127.0.1.1" /etc/hosts; then
sudo sed -i "/127.0.1.1/a $NEW_ENTRY" /etc/hosts
else
sudo sed -i "1i $NEW_ENTRY" /etc/hosts
fi
/etc/hostsに、IPアドレスとホストの組み合わせを記入します。