Index
PythonのプロキシとRust/cJSONバックエンドでJSONキーの解釈がずれている。プロキシは username 以外のform keyに -custom を付けたうえで、ランダムな username を別途追加する。
username%00=Admin を送るとPython側では username\0 という別キー扱いになり、JSONには username\0-custom が入る。一方cJSON側ではNUL終端でキーが username に見えるため、先に現れたAdminが採用されて認証を通過する。
サーバはNode.jsの http2.createServer() で動く平文HTTP/2、つまりh2cだった。普通のHTTP/1.1クライアントでアクセスしてもプロトコルが合わない。
HTTP/2 connection prefaceとSETTINGSを送れるクライアントを使って、h2cで / をGETする。Pythonの h2 ライブラリやh2c対応クライアントを使えばDATA frame内にフラグが返る。
flag.png が16バイト周期のxor鍵で暗号化されている。PNGの先頭16バイトはシグネチャとIHDRの固定部分で既知なので、暗号文の先頭とxorすれば鍵全体がそのまま出る。
得た16バイト鍵をファイル全体に繰り返しxorして復号する。復元されたPNGを開き、画像内の文字を読めばフラグになる。
管理botは指定URLを訪問し、titleに AlpacaHack が含まれるページなら、メール欄に固定メールアドレス、パスワード欄にFLAGを入力する。スクリプト実行自体は攻撃者ページ上で可能。
外部に置いたページへbotを誘導し、<title> と input[name=email]、input[name=password] を用意する。password inputの input イベントで値をcollectorへ送れば、botが入力したFLAGを回収できる。
入力パスを os.path.abspath したあと、/flag.txt との完全一致や /proc を含むかだけを拒否してから cat する。Python/POSIXでは先頭スラッシュがちょうど2個のパスはそのまま保存される。
//flag.txt を渡すと、文字列としては /flag.txt と一致しないためチェックを抜ける。一方Linux上の実際のファイル参照では /flag.txt と同じ場所を指すので、cat がフラグを表示する。
CPythonのオブジェクトアドレスリークと1バイト任意書き込みを使う問題。フラグ表示ループの上限は len("Alpaca{") で、小さい整数7のオブジェクトが参照される。
CPythonは小さい整数をキャッシュするため、id(0) から整数7の ob_digit 位置を計算できる。その1バイトを書き換えるとループ上限が伸び、より多くの文字が表示される。必要に応じて別接続でもう一箇所を調整し、欠けた位置を補って復元する。