
CVE-2017-8291 (GhostButt) の教育用PoC。Python PIL/Pillow EPS画像処理を介したリモートコマンド実行を示し、GhostScriptサンドボックス回避を伴います。
Python PIL (Pillow) は、Python で人気の画像処理ライブラリです。さまざまな画像形式をサポートし、強力な画像操作機能を提供します。
Python 画像処理モジュール PIL (Pillow) は、内部で GhostScript を呼び出して EPS 画像を処理するため、GhostButt 脆弱性 (CVE-2017-8291) の影響を受けます。この脆弱性により、攻撃者は対象システム上で任意のコマンドを実行できます。
PIL が画像を処理する際、ファイルヘッダー (マジックバイト) に基づいて画像タイプを判断します。EPS ファイル (ヘッダーが %!PS で始まる) を検出すると、そのファイルを PIL/EpsImagePlugin.py に渡して処理します。
このモジュールでは、PIL はシステムの GhostScript コマンド (gs) を呼び出して画像ファイルを処理します。
command = ["gs",
"-q", # quiet mode
"-g%dx%d" % size, # set output geometry (pixels)
"-r%fx%f" % res, # set input DPI (dots per inch)
"-dBATCH", # exit after processing
"-dNOPAUSE", # don't pause between pages,
"-dSAFER", # safe mode
"-sDEVICE=ppmraw", # ppm driver
"-sOutputFile=%s" % outfile, # output file
"-c", "%d %d translate" % (-bbox[0], -bbox[1]),
# adjust for image origin
"-f", infile, # input file
]
# Code to check if GhostScript is installed is omitted
try:
with open(os.devnull, 'w+b') as devnull:
subprocess.check_call(command, stdin=devnull, stdout=devnull)
im = Image.open(outfile)
-dSAFER フラグ (セーフモード) が設定されているにもかかわらず、GhostScript のサンドボックスバイパス脆弱性 (GhostButt CVE-2017-8291) により、この安全機構が回避され、任意のコマンド実行が可能になります。
本稿執筆時点では、最新の公式 GhostScript バージョン 9.21 でもこの脆弱性の影響を受けます。そのため、オペレーティングシステムに GhostScript がインストールされている限り、PIL はコマンド実行の影響を受けます。
参考資料:
以下のコマンドを実行して、CVE-2017-8291 脆弱性の影響を受ける Web アプリケーションを起動します。
docker compose up -d
起動後、http://your-ip:8000/ にアクセスしてアップロードページを開きます。
このアプリケーションの通常機能では、ユーザーは PNG ファイルをアップロードできます。バックエンドは PIL を使用して画像を読み込み、その寸法を出力します。しかし、実行可能な EPS ファイルの拡張子を PNG に変更してアップロードすることで、この脆弱性を悪用できます。バックエンドは拡張子ではなくファイルヘッダーに基づいて画像タイプを判断するため、ファイル拡張子のチェックをバイパスできます。
例えば、poc.png をアップロードすると、サーバー上で touch /tmp/aaaaa コマンドが実行されます。POC 内のコマンドをリバースシェルコマンドに変更することで、サーバーへのシェルアクセスを取得できます。
