SECCON 2018 Quals - QRChecker
問題文
QR Checker
http://qrchecker.pwn.seccon.jp/
ソースコードが公開されている。
#!/usr/bin/env python3 import sys, io, cgi, os from PIL import Image import zbarlight print("Content-Type: text/html") print("") codes = set() sizes = [500, 250, 100, 50] print('<html><body>') print('<form action="' + os.path.basename(__file__) + '" method="post" enctype="multipart/form-data">') print('<input type="file" name="uploadFile"/>') print('<input type="submit" value="submit"/>') print('</form>') print('<pre>') try: form = cgi.FieldStorage() data = form["uploadFile"].file.read(1024 * 256) image= Image.open(io.BytesIO(data)) for sz in sizes: image = image.resize((sz, sz)) result= zbarlight.scan_codes('qrcode', image) if result == None: break if 1 < len(result): break codes.add(result[0]) for c in sorted(list(codes)): print(c.decode()) if 1 < len(codes): print("SECCON{" + open("flag").read().rstrip() + "}") except: pass print('</pre>') print('</body></html>')
writeup
毎年お馴染みらしい、QRコードの問題。
ソースコードを読み解くと、1つのQRコード画像を500x500、250x250、100x100、50x50にリサイズし、2種類以上の読み取り結果が得られたらフラグをゲットできるようだ。
大きな画像を縮小すると、画像が粗くなったりつぶれたりするので、その現象を使用するのだろうか。
ここで、18年6月くらいにQRコードの脆弱性という記事を読んだことを思い出す。
『きまぐれQRコード』ができます!?【続報】気を付けろ!QRコードに脆弱性?(森井昌克) - 個人 - Yahoo!ニュース
QRコードの誤り訂正の領域に、グレーのセルがある。このセルが白と判定される場合と黒と判定される場合とで、読み取り結果が変わる。
こちらの記事のQRコード画像を拝借して読み取らせてみる。
まずは、ローカルで実行可能な環境を用意するため、ライブラリをインストール。
root@kali:~# sudo apt-get install libzbar-dev root@kali:~# pip install zbarlight
ローカル実行するためのコードはこちら。
#!/usr/bin/env python3 import sys, io, cgi, os from PIL import Image import zbarlight codes = set() sizes = [500, 250, 100, 50] f = open(sys.argv[1], 'rb') data = f.read(1024 * 256) image= Image.open(io.BytesIO(data)) for sz in sizes: image = image.resize((sz, sz)) #image.save('qr_{}.png'.format(str(sz))) result= zbarlight.scan_codes('qrcode', image) if result == None: break if 1 < len(result): break print(sz) print(result[0]) codes.add(result[0]) for c in sorted(list(codes)): print(c.decode()) if 1 < len(codes): print("SECCON{SUCCESS!!}")
QRコード画像
実行結果
root@kali:~# python qr.py qr_org.png 500 b'http://srv.prof-morii.net/~lab' 250 b'http://srv.prof-morii.net/~lab' 100 b'http://srv.prof-morii.net/~lab' 50 b'http://srv.prof-morii.net/~lab' http://srv.prof-morii.net/~lab
そのままでは1種類の読み取り結果しか得られなかった。
そこで、画像サイズを変えたり、グレーの部分をGIMPで適当に塗ったりして調整し、Try&Errorしてみる。
最終的に以下の画像で成功した。
root@kali:~# python qr.py qr_success.png 500 b'http://srv.prof-morii.net/~lob' 250 b'http://srv.prof-morii.net/~lob' 100 b'http://srv.prof-morii.net/~lob' 50 b'http://srv.prof-morii.net/~lab' http://srv.prof-morii.net/~lab http://srv.prof-morii.net/~lob SECCON{SUCCESS!!}
画像をアップロードする。
フラグゲット
SECCON{50d7bc7542b5837a7c5b94cf2446b848}