2018年12月30日

SECCON 2018 国際決勝 CTF での Programming Quiz について

先週開催された SECCON 2018 でのCTFで、プログラミング/システム管理に関するクイズを出題しました。一見すると「え?そんなの不可能では?」と思われる内容の詰め合わせです。その際に使用した環境を再構築するための tar ball が公開されていますので、興味のある方はお試しください。ヒントは server5-hints.txt に、想定解法は steps.txt に書いてあります。

SECCON 2015 オンライン CTF のときはガチガチに制限された環境でしたが、今回は King Of the Hill 形式の攻防戦ということで、できるだけ制限の緩い環境で遊んでもらうことにしました。以下が、使用した CaitSith のポリシーです。 strace 等を使うと一瞬で正解できてしまうので、 CaitSith の他に、 ptrace を制限するモジュールも併用しました。

POLICY_VERSION=20120401
quota memory audit 16777216
quota memory query 1048576
quota audit[0] allowed=0 denied=1024 unmatched=0

10 acl execute task.uid=10000-100000
    audit 0
    10 deny path.perm=setuid
    10 deny path.perm=setgid path.gid!=1000-1007
    20 allow

10 acl read path.fsmagic=0x9FA0 task.uid=10000-100000 path.uid=10000-100000 task.uid!=path.uid
    audit 1
    10 deny

10 acl environ task.uid=1000-65535
    audit 0
    10 allow name="_"
    10 allow name="COLLECT_GCC"
    10 allow name="COLLECT_GCC_OPTIONS"
    10 allow name="COLLECT_LTO_WRAPPER"
    10 allow name="COMPILER_PATH"
    10 allow name="HOME"
    10 allow name="LANG"
    10 allow name="LESSOPEN"
    10 allow name="LIBRARY_PATH"
    10 allow name="LOGNAME"
    10 allow name="LS_COLORS"
    10 allow name="MAIL"
    10 allow name="OLDPWD"
    10 allow name="PATH"
    10 allow name="PWD"
    10 allow name="PYTHONINSPECT"
    10 allow name="SHELL"
    10 allow name="SHLVL"
    10 allow name="SSH_CLIENT"
    10 allow name="SSH_CONNECTION"
    10 allow name="SSH_ORIGINAL_COMMAND"
    10 allow name="SSH_TTY"
    10 allow name="TERM"
    10 allow name="USER"
    10 allow name="XDG_RUNTIME_DIR"
    10 allow name="XDG_SESSION_ID"
    10 allow name="LC_CTYPE"
    10 allow name="LC_ALL"
    10 allow name="LC_NUMERIC"
    10 allow name="LC_TIME"
    10 allow name="LC_COLLATE"
    10 allow name="LC_MONETARY"
    10 allow name="LC_MESSAGES"
    10 allow name="LC_PAPER"
    10 allow name="LC_NAME"
    10 allow name="LC_ADDRESS"
    10 allow name="LC_TELEPHONE"
    10 allow name="LC_MEASUREMENT"
    10 allow name="LC_IDENTIFICATION"
    10 allow name="LANGUAGE"
    10 allow name="XMODIFIERS"
    10 allow name="HOSTNAME"
    10 allow name="LINES"
    10 allow name="MAN_NO_LOCALE_WARNING"
    10 allow name="MAN_ORIG_LESS"
    10 allow name="LESSCHARSET"
    10 allow name="COLUMNS"
    10 allow name="MAN_PN"
    10 allow name="GROFF_BIN_PATH"
    10 allow name="HISTSIZE"
    10 allow name="LESS"
    20 deny

さて、1日目の競技が終了した時点で、チームDCUAから「問題サーバにバグがある」という指摘がありました。 /bin/seccon_login を root:seccon で 4710 にしていたのですが、 seccon ユーザのパスワードが既知なので、 su - seccon で再び seccon ユーザになってから環境変数 SSH_CONNECTION を書き換えて /bin/seccon_login を実行することにより、任意のチームとしてログインできてしまうという指摘でした。

なりすましログインにより他チームが解いたクイズの答えを盗み見たり、自チーム以外はじゃんけんに参加しないようにしたりすることができてしまうため、事実上サーバ5を占拠し続けることができてしまうバグです。

普通はセキュアOSをガチガチに固めるために使用するものですが、今回はできるだけユルユルに使うことを目標としていたため、sshログイン以外の方法で seccon ユーザになれるということを見落としていたのです。そのため、2日目の競技開始前に、クイズに不要な setuid / setgid プログラムの実行許可を与えないようにするというポリシー修正(上記の 10 acl execute task.uid=10000-100000 エントリ部分の追加)を行いました。

まぁ、攻防戦としては「気づいたもの勝ち」という点で、なりすましができるままにしておいたほうが面白かったかもしれませんが。

posted by 熊猫さくら at 23:36| Comment(0) | TrackBack(0) | CaitSith

2016年10月05日

CaitSith 0.1.17 / 0.2 が公開されました。

熊猫にとって今年最大のイベントであるセキュリティ・キャンプ全国大会2016と会社のインターンシップ期間が終わり、 Linux 4.8 もリリースされたことで、ようやく肩の荷が下りました。そのため、 CaitSith をメインライン化するための活動を開始しました。

https://ja.osdn.net/projects/tomoyo/lists/archive/users/2016-September/001008.html
https://ja.osdn.net/projects/tomoyo/lists/archive/users/2016-October/001009.html

posted by 熊猫さくら at 23:04| Comment(0) | TrackBack(0) | CaitSith

2015年12月15日

SECCON 2015 オンライン CTF での Command-Line Quiz について

telnet でログインしたらシェルが与えられるのに、自由にファイルを読むことができない不思議なシェル環境、あの問題は CaitSith の機能を用いて実現しました。

CaitSith login: root
Password:
$ id
uid=10000 gid=10000 groups=10000
$ ls -l
drwxr-xr-x    2 root     0            1880 Dec  5 05:18 bin
drwxr-xr-x    3 root     0             180 Dec  5 05:02 dev
drwxr-xr-x    2 root     0             100 Dec  5 05:02 etc
-rw-r--r--    1 600      0              87 Dec  5 04:48 flags.txt
-rwx------    1 root     0           13750 Dec  5 05:01 init
drwxr-xr-x    2 root     0              80 Dec  5 05:02 lib
-rwxr-xr-x  313 root     0          831112 Feb 19  2015 linuxrc
dr-xr-xr-x   73 root     0               0 Dec  5 05:18 proc
drwxr-xr-x    2 root     0            1180 Dec  5 05:18 sbin
-rw-r--r--    1 100      0             262 Dec  5 04:48 stage1.txt
-rw-r--r--    1 200      0             265 Dec  5 04:48 stage2.txt
-rw-r--r--    1 300      0             270 Dec  5 04:48 stage3.txt
-rw-r--r--    1 400      0             247 Dec  5 04:48 stage4.txt
-rw-r--r--    1 500      0             280 Dec  5 04:48 stage5.txt
drwxrwxrwt    2 10000    10000          60 Dec 15 13:57 tmp
drwxr-xr-x    4 root     0              80 Dec  5 05:02 usr
$ cat *.txt
cat: can't open 'flags.txt': Operation not permitted
What command do you use when you want to read only top lines of a text file?

Set your answer to environment variable named stage1 and execute a shell.

  $ stage1=$your_answer_here sh

If your answer is what I meant, you will be able to access stage2.txt file.
cat: can't open 'stage2.txt': Operation not permitted
cat: can't open 'stage3.txt': Operation not permitted
cat: can't open 'stage4.txt': Operation not permitted
cat: can't open 'stage5.txt': Operation not permitted
$ stage1=head sh
$ cat *.txt
cat: can't open 'flags.txt': Operation not permitted
cat: can't open 'stage1.txt': Operation not permitted
What command do you use when you want to read only bottom lines of a text file?

Set your answer to environment variable named stage2 and execute a shell.

  $ stage2=$your_answer_here sh

If your answer is what I meant, you will be able to access stage3.txt file.
cat: can't open 'stage3.txt': Operation not permitted
cat: can't open 'stage4.txt': Operation not permitted
cat: can't open 'stage5.txt': Operation not permitted
$ stage2=tail sh
$ cat *.txt
cat: can't open 'flags.txt': Operation not permitted
cat: can't open 'stage1.txt': Operation not permitted
cat: can't open 'stage2.txt': Operation not permitted
What command do you use when you want to pick up lines that match specific patterns?

Set your answer to environment variable named stage3 and execute a shell.

  $ stage3=$your_answer_here sh

If your answer is what I meant, you will be able to access stage4.txt file.
cat: can't open 'stage4.txt': Operation not permitted
cat: can't open 'stage5.txt': Operation not permitted
$ stage3=grep sh
$ cat *.txt
cat: can't open 'flags.txt': Operation not permitted
cat: can't open 'stage1.txt': Operation not permitted
cat: can't open 'stage2.txt': Operation not permitted
cat: can't open 'stage3.txt': Operation not permitted
What command do you use when you want to process a text file?

Set your answer to environment variable named stage4 and execute a shell.

  $ stage4=$your_answer_here sh

If your answer is what I meant, you will be able to access stage5.txt file.
cat: can't open 'stage5.txt': Operation not permitted
$ stage4=awk sh
$ cat *.txt
cat: can't open 'flags.txt': Operation not permitted
cat: can't open 'stage1.txt': Operation not permitted
cat: can't open 'stage2.txt': Operation not permitted
cat: can't open 'stage3.txt': Operation not permitted
cat: can't open 'stage4.txt': Operation not permitted
OK. You reached the final stage. The flag word is in flags.txt file.

flags.txt can be read by only one specific program which is available
in this server. The program for reading flags.txt is one of commands
you can use for processing a text file. Please find it. Good luck. ;-)
$ sed "" flags.txt
OK. You have read all .txt files. The flag word is shown below.

SECCON{CaitSith@AQUA}
$

シェルを起動するたびに読めるファイルが変化したり、環境変数の内容に応じてアクセスの可否が決まったりというのは、 TOMOYO / AKARI / CaitSith ならではのアクセス制限です。どのようなルールを使っていたのかを、ここで紹介します。

POLICY_VERSION=20120401

10 acl execute task.uid!=0 task.domain="<kernel>"
    10 allow transition="stage1"
    20 deny

10 acl execute task.domain="stage1"
    10 allow envp["stage1"]="head" transition="stage2"
    20 allow

10 acl execute task.domain="stage2"
    10 allow envp["stage2"]="tail" transition="stage3"
    20 allow

10 acl execute task.domain="stage3"
    10 allow envp["stage3"]="grep" transition="stage4"
    20 allow

10 acl execute task.domain="stage4"
    10 allow envp["stage4"]="awk" transition="stage5"
    20 allow

10 acl read path.uid=100
    10 allow task.domain="stage1"
    20 deny

10 acl read path.uid=200
    10 allow task.domain="stage2"
    20 deny

10 acl read path.uid=300
    10 allow task.domain="stage3"
    20 deny

10 acl read path.uid=400
    10 allow task.domain="stage4"
    20 deny

10 acl read path.uid=500
    10 allow task.domain="stage5"
    20 deny

10 acl read path.uid=600
    10 allow task.exe="/bin/sed" task.domain="stage5"
    20 deny

10 acl inet_stream_connect task.uid!=0
    10 deny

10 acl inet_stream_listen
    10 allow port=23
    20 deny

10 acl inet_dgram_send task.uid!=0
    10 allow port=53 ip=133.242.0.3
    10 allow port=53 ip=133.242.0.4
    20 deny

最初の規則は、一般ユーザ(UIDが0ではないプロセス)かつドメインが <kernel> であるプロセスからプログラムが実行された場合、 stage1 ドメインへ遷移するという指定です。これは、 root ユーザとしてログイン後、ログインシェルから一般ユーザのユーザIDが割り当てられて、シェルが開始されることにより stage1 ドメインに遷移するという動作に対応します。

次の規則は、ドメインが stage1 であるプロセスからプログラムが実行された場合、環境変数 stage1 の値が head であれば stage2 ドメインに遷移し、それ以外の場合には、ドメインを遷移せずにプログラムを実行するという指定です。これは、 stage1.txt の回答が head であれば stage2 へ進むことができ、そうでなければ stage2 へは進めないという動作に対応します。普通のアクセス制御では許可する場合を列挙したら残りは全て拒否するものですが、ここでは意図的に全てを許可するように指定しています。これにより、正解でも不正解でもシェルが実行できるため、総当たり攻撃による突破を困難にしています。

以下同様に、ドメインが stage2 であるプロセスからプログラムが実行された場合、環境変数 stage2 の値が tail であれば stage3 ドメインに遷移、ドメインが stage3 であるプロセスからプログラムが実行された場合、環境変数 stage3 の値が grep であれば stage4 ドメインに遷移、ドメインが stage4 であるプロセスからプログラムが実行された場合、環境変数 stage4 の値が awk であれば stage5 ドメインに遷移するという指定を行っています。

次に、それぞれのドメインでどのファイルを読めるかについての指定を行います。パス名ベースのアクセス制御の弱点である、パス名が変化するとアクセスの可否も変化してしまうという問題を回避するため、ファイルの所有者IDをキーとして許可を与えるようにしています。この方法なら、細かくリネームやハードリンクなどの作成を制限する必要がありません。パス名以外をキーに指定できる CaitSith の利点が生かせる指定です。

具体的には、所有者IDが100のファイルは、ドメインが stage1 であるプロセスからのみ読み出すことができるという指定を行っています。以下同様に、所有者IDが200のファイルはドメインが stage2 であるプロセスからのみ、所有者IDが300のファイルはドメインが stage3 であるプロセスからのみ、所有者IDが400のファイルはドメインが stage4 であるプロセスからのみ、所有者IDが500のファイルはドメインが stage5 であるプロセスからのみ読み出すことができるという指定を行っています。これらは、それぞれのステージで stage1.txt から stage5.txt までの何れか1個だけを読み出すことができるという動作に対応します。

所有者IDが600である flags.txt を読み出す許可だけは、少し異なる方法で指定しています。具体的には、プロセスのドメインが stage5 で、かつ、実行中のプログラムのパス名が /bin/sed である場合のみ読み出すことができるという指定を行っています。

その他、他のサーバへの攻撃に使われないようにするために、ネットワークの制限も行っています。具体的には、ユーザIDが0ではないプロセスは外向きのTCP接続を全面的に禁止しています。また、内向きのTCP接続はポート23のみを許可しています。ユーザIDが0ではないプロセスは、外向きのUDP接続として、DNSサーバである 133.242.0.3 および 133.242.0.4 のポート53のみを許可しています。

以上が、今回の出題で使われたルールです。もっと複雑なルールを指定することもできますが、エスパー問題化を回避するために、簡単なルールを指定しながら、ヒントも与えるようにしています。ヒントを削ってしまうと、攻略不可能なケロちゃんチェック問題になってしまいますからねぇ。

勝手にQ&A:

  • 何故 root ユーザでログインしているのにシェルのプロンプトが一般ユーザ用なの?→他の挑戦者への妨害を防ぐために、セッション毎に異なるユーザIDや /tmp ディレクトリを割り当てていたためです。

  • シェルログインさせておいて、スパムメールの発射台にされないの?→上述した通り、ネットワーク制限が掛かっているので発射台にはできないでしょう。

  • ハードディスクが見つからなかったのですが?→すべてオンメモリで動作しています。 initramfs 内の busybox により一通りの機能は提供されていました。そのため、 /init と、セッション隔離を行うためのログインシェルである /bin/loginshell 、それらが依存している ld-linux.so.2 と libc.so.6 だけを initramfs に追加し、 CaitSith のポリシーも含めて全て vmlinuz 内に埋め込みました。 vmlinuz ファイル1個だけで動作するので、 PXE で使うのも簡単です。

  • vmlinuz ファイル1個だけで動作する Linux 環境ってどうやって作るの?→今年のセキュリティ・キャンプの事前学習資料で扱っています。この資料で説明されている内容を参考に、NICドライバなど幾つかの機能を追加すればネットワーク接続もできるカーネルができあがります。

  • 何故 ssh ログインじゃないの?→準備時間が足りませんでした。(笑)

posted by 熊猫さくら at 23:07| Comment(0) | TrackBack(0) | CaitSith

2013年02月14日

AKARI 1.0.30 / CaitSith 0.1.9 が公開されました。

AKARI と CaitSith を同時に使えるようになりました。 LSM フックを見つける部分が別ファイルに切り出されたので、類似したモジュールを作る際に再利用しやすくなりました。

http://sourceforge.jp/projects/tomoyo/lists/archive/users/2013-February/000989.html

posted by 熊猫さくら at 23:32| Comment(0) | TrackBack(0) | CaitSith

2012年12月25日

CaitSith 0.1.7 が公開されました。

ポリシーのパーサを書き直して、柔軟な条件式を指定できるようになりました。また、メインライン提案への準備として AKARI と同様にLSMに対応した完全なカーネルモジュールとしてもコンパイルできるようにしました。

http://sourceforge.jp/projects/tomoyo/lists/archive/users/2012-December/000979.html

posted by 熊猫さくら at 20:24| Comment(0) | TrackBack(0) | CaitSith

2012年06月20日

CaitSith という名前の由来について

LinuxCon North America 2012 で CaitSith の発表をすることになったので、ドキュメントの整備と動作テストが終わってから書こうと思っていた記事を投入します。

今までのアクセス制限モジュールはプロセスの視点からルールを書くため、特定のプロセスの動作を制限するルールを書くことは簡単でした。しかし、特定の資源へのアクセスを制限するには全てのプロセスの動作を制限しなくてはならないため面倒でした。資源の視点からルールを書くことができれば、そんな必要も無くなります。 CaitSith はプロセス視点でも資源視点でもお好きなようにルールを書けるので、「でっかい自分ルール」を実現できます。

さらに、 CaitSith ではホワイトリスト方式だけでなくブラックリスト方式でルールを書くこともできるようになっており、デフォルトでは許可も拒否もしない「あらあらうふふ」状態な動作をします。

最初は TOMOYO 1.9 にするつもりでしたが、だんだん変更点が大きくなってきたので TOMOYO 3.0 にすることも考えました。しかし、考え方や使い方があまりにも違うので、そのまま TOMOYO という名称を付けると混乱すると判断し、新しい名前を割り当てることにしました。

サクッと1時間ほど考えて、最初は "Access Limiter Implementation Checking Interested Attributes" "Access Limiter Implementation Checking Interested Actions" "Access Limiter Implementation Checking In-kernel Attributes" の何れかの頭文字となる ALICIA さんにしようと決めました。しかし、「 Linux ALICIA 」で検索したところ、既に "Advanced LInux Crash-dump Interactive Analyzer" の略としての ALICIA さんが存在しており、しかも同じ Linux カーネルという分野なので、これでは無理だと判断しました。

そこでまた1時間ほど考えて、 "Characteristic action inspection tool. See if this helps." "Characteristic access inspection tool. See if this helps." "Characteristic access inspector to See if this helps." の何れかの頭文字となる CaitSith さんにしようと決めました。制限したい操作だけを制限するので、セキュリティの専門家には不人気かと思いますが、セキュリティの専門家ではない利用者からの需要はあるかもしれないので、調査の意味合いを込めて See if this helps. になりました。

posted by 熊猫さくら at 17:14| Comment(0) | TrackBack(0) | CaitSith

2012年04月01日

CaitSith プロジェクト始めました。

CaitSith は Linux 2.6.27 以降のカーネル向けのアクセス制限モジュールです。元々は TOMOYO Linux の次期バージョンとして作成していたものが、あまりにも考え方や使い方の変更が大きくなりすぎてしまったため、「もはや TOMOYO とは呼べない」ということで新しい名前を付けました。

今日、初版をリリースしました。
http://sourceforge.jp/projects/tomoyo/lists/archive/users/2012-April/000968.html

posted by 熊猫さくら at 23:43| Comment(0) | TrackBack(0) | CaitSith