shinobe179の日記

@shinobe179 の技術メモ・やらかし録

【Python】テキストファイルを開いて for で読み込むときは改行コードに注意しましょう(自戒

はじめに

あまりに初歩的過ぎて書くまでもないと思ったけど、そういうのだからこそ(自分のために)残しておく価値があると言い聞かせて書く。とは言え初歩的過ぎて凹んでいるので Twitter に流すのはやめておこうと思う。

結論

テキストファイルを for 文で 1 行ずつ読み込むときは改行コードがくっついてくるので必要に応じて処理する。

発端

CTF for Beginners 2020 の Spy に挑戦している最中、事前情報として提示された社員名簿 (employee.txt) を 1 行ずつ for 文で読み込んでログインを試行するスクリプトを組んだ。

import requests
import string
import json

URL = 'https://spy.quals.beginners.seccon.jp/'
with open('employees.txt') as f:
    for u in f:
        data = {
            'name': u,
            'password': ''
        }
        r = requests.post(URL, data=data)
        print(f'status: {r.status_code}, user: {u}, time: {r.text}') # 所要時間だけパースするのが面倒なので、 HTML ごとテキストに書き出して別途 grep した

見立てが正しければ、システムにアカウントが存在する場合とそうでない場合とで、ログイン処理にかかる時間に差が生じるはずだが、有意な差は得られなかった。しかし、手作業で 1 アカウントずつ確認していったら有意差が確認できた。結局、 flag は手作業頼りで取った。

原因

flag を取った後に data を print したら以下のようになっていた。 \n が含まれているせいで全アカウント存在しないものとして扱われたから、有意差が得られなかったということが分かった。

$ python3 enumerate.py
{'name': 'Arthur\n', 'password': ''}
{'name': 'Barbara\n', 'password': ''}
{'name': 'Christine\n', 'password': ''}
...

対策

rstrip()\n を除去すればよい。そもそも予想通りでない時点で print デバッグすればよかったし、 VSCode とか IDE を使っていればすぐに気づけた気がする。

import requests
import string
import json

URL = 'https://spy.quals.beginners.seccon.jp/'
with open('employees.txt') as f:
    for u in f:
        data = {
            'name': u.rstrip(),
            'password': ''
        }
        r = requests.post(URL, data=data)
        print(f'status: {r.status_code}, user: {u}, time: {r.text}') 

参考

qiita.com