以下是一個 完整的 Web API 示例,使用 Flask + YARA-Python 實現文件掃描功能,支持上傳文件并返回 YARA 規則匹配結果。
? 功能說明
- 提供一個
/scan
接口,支持文件上傳 - 使用預加載的 YARA 規則進行掃描
- 返回 JSON 格式的匹配結果
- 支持多規則、可擴展
📦 項目結構
yara-flask-api/
├── app.py # Flask 主程序
├── rules/ # YARA 規則目錄
│ ├── hello.yar
│ └── suspicious_pe.yar
├── uploads/ # 臨時存儲上傳文件(可選)
└── requirements.txt
1. 安裝依賴
創建 requirements.txt
:
flask
yara-python
安裝:
pip install -r requirements.txt
確保系統已安裝 YARA 開發庫:
- Ubuntu:
sudo apt-get install yara libyara-dev
- macOS:
brew install yara
2. 編寫 YARA 規則
rules/hello.yar
rule ContainsHello
{strings:$hello = "Hello" ascii nocasecondition:$hello
}
rules/suspicious_pe.yar
import "pe"rule SuspiciousPEScan
{meta:description = "Detects common suspicious PE imports"strings:$create_remote_thread = "CreateRemoteThread" fullword ascii$write_process_memory = "WriteProcessMemory" fullword asciicondition:pe.is_pe andany of them
}
3. Flask Web API 主程序 (app.py
)
import os
import yara
from flask import Flask, request, jsonify
from werkzeug.utils import secure_filename# 初始化 Flask 應用
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = 'uploads'
app.config['MAX_CONTENT_LENGTH'] = 10 * 1024 * 1024 # 10MB 限制# 確保目錄存在
os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)
os.makedirs('rules', exist_ok=True)# 編譯所有 .yar 規則
def load_yara_rules():try:rule_files = {}for filename in os.listdir('rules'):if filename.endswith('.yar'):filepath = os.path.join('rules', filename)rule_files[f"rule_{filename}"] = filepathrules = yara.compile(filepaths=rule_files)print(f"[+] 成功加載 {len(rule_files)} 條 YARA 規則")return rulesexcept yara.Error as e:print(f"[-] YARA 規則編譯失敗: {e}")return None# 全局加載規則
yara_rules = load_yara_rules()if not yara_rules:print("[-] 無法啟動:YARA 規則加載失敗")exit(1)# 根路徑
@app.route('/')
def index():return '''<h3>YARA 掃描 API 服務</h3><p>使用 POST /scan 上傳文件進行掃描</p>'''# 掃描接口
@app.route('/scan', methods=['POST'])
def scan_file():if 'file' not in request.files:return jsonify({"error": "未提供文件字段 'file'"}), 400file = request.files['file']if file.filename == '':return jsonify({"error": "未選擇文件"}), 400if file:filename = secure_filename(file.filename)filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)file.save(filepath)try:# 執行 YARA 掃描matches = yara_rules.match(filepath)result = {"filename": filename,"matches": []}for match in matches:indicators = []for string in match.strings:indicators.append({"offset": f"0x{string[0]:X}","identifier": string[1],"data": string[2].decode('utf-8', errors='replace')})result["matches"].append({"rule": match.rule,"tags": match.tags,"indicators": indicators})os.remove(filepath) # 掃描后刪除文件(可選)return jsonify(result), 200except Exception as e:os.remove(filepath)return jsonify({"error": f"掃描出錯: {str(e)}"}), 500return jsonify({"error": "未知錯誤"}), 500# 啟動服務
if __name__ == '__main__':print("🚀 啟動 YARA 掃描服務 http://127.0.0.1:5000")app.run(host='0.0.0.0', port=5000, debug=False)
4. 啟動服務
python app.py
服務將運行在:http://127.0.0.1:5000
5. 測試 API(使用 curl)
測試文本文件
echo "Hello, this is a test." > test.txt
curl -X POST -F "file=@test.txt" http://127.0.0.1:5000/scan
? 預期輸出(匹配 ContainsHello
):
{"filename": "test.txt","matches": [{"rule": "ContainsHello","tags": [],"indicators": [{"offset": "0x0","identifier": "$hello","data": "Hello"}]}]
}
測試 PE 文件(如 exe)
curl -X POST -F "file=@malware.exe" http://127.0.0.1:5000/scan
如果該 PE 文件調用了 CreateRemoteThread
,會觸發 SuspiciousPEScan
規則。
總結
這個 Flask + YARA 的 Web API 示例可以:
- 快速集成到 SOC、EDR、文件網關等系統
- 用于自動化惡意軟件檢測流水線
- 作為威脅情報分析的后端引擎