pyjail wiki

LITCTF 2023 - Obligatory PyJail

Challenge

__getattribute__ がカスタマイズされた環境。

class RestrictedObject:
def __getattribute__(self, name):
if name.startswith('_'):
raise AttributeError("Access denied")
return super().__getattribute__(name)
# オブジェクトが制限された環境で実行
code = input()
exec(code, {'obj': RestrictedObject()})

Solution

getattribute のバイパス

object.__getattribute__ を直接呼び出す:

object.__getattribute__(obj, '__class__')

type() の使用

type(obj).__bases__

getattr との違い

# getattr は __getattribute__ を呼ぶ
getattr(obj, '__class__') # 失敗
# object.__getattribute__ は直接アクセス
object.__getattribute__(obj, '__class__') # 成功

Technical Details

属性アクセスの仕組み

obj.attr
# 内部的に:
type(obj).__getattribute__(obj, 'attr')

オーバーライドのバイパス

# カスタム __getattribute__ を迂回
object.__getattribute__(obj, attr)
# または super() を使用
super(type(obj), obj).__getattribute__(attr)

MRO の確認

type(obj).__mro__
# [<class 'RestrictedObject'>, <class 'object'>]

Alternative Solutions

別解1: vars() の使用

vars(obj) # __dict__ にアクセス

別解2: type のメソッド

type.__getattribute__(type(obj), '__bases__')

Flag

LITCTF{...}

References

  • LITCTF 2023 Official
  • Python Data Model