2019年08月18日

セキュリティ・キャンプ2019で使用した、熊猫のテキストを公開しました。

熊猫がプログラミングに出会ってから25年となった今年は、不具合を修正できるようにするための試行錯誤について扱いました。

不具合を踏んでクラッシュした場合、メモリダンプを取得して原因を解析することが多いかと思います。しかし、 syzbot を用いたファジングテストでは、メモリダンプを取得することが(現時点では)不可能です。また、ハングアップやストールの場合は、仮にメモリダンプを取得できたとしても、時間経過に伴う状態変化をメモリダンプから知ることはできないという限界があります。そのため、 printf() デバッグに頼らざるを得ない訳ですが、複数のスレッドが同時に printf() を呼んでしまうことで複数のメッセージが混ざってしまい、個々のメッセージを解析できなくなるという問題もあります。

そんな厳しい状況で、問題が発生した時に必要な情報をいかにして取得できるようにするかという、とても複雑で面倒な問題に熊猫は取り組んできました。講義資料は、( Linux カーネルにおける printf() に相当する)printk() を巡る試行錯誤をメインに、メモリ管理サブシステム開発者との大バトルや、ある不具合が修正されたと思ったら別の不具合が発見されたりする沼など、盛りだくさんです。とても4時間では紹介しきれません〜。(笑)

今年は、担当講義の時間以外はZトラックにお邪魔していたため、思わず突っ込む側になってしまいました。熊猫はマルウェアを解析した経験はありませんが、講義の中で strace による動的解析が紹介されていたので、ちゃっかり AKARI による追跡手法を紹介することができました。

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

2019年04月27日

Google Open Source Peer Bonus を受賞しました。

サポートセンタに勤務していた時に偶然発見してしまったメモリ管理の闇が原因で、現在でも Linux カーネルのバグハンティングを続けている訳ですが、ここ1年半ほど syzbot が見つけた不具合を退治していたところ、その貢献により Google Open Source Peer Bonus を受賞してしまいました。

受賞理由の1つでもある printk() の改善が来月公開される Linux 5.1 に含まれることから、今年のセキュリティ・キャンプ全国大会では、この体験談を The SYZBOT CTFとして語ることになっています。

3年前のセキュリティ・キャンプ全国大会で語った The OOM CTF では、受講者全員の思考が停止してしまうほどの脳内 Denial of Service 攻撃になってしまいました。
現在、今年の講義で取り上げるトピックを探すためにメールのアーカイブを読み返しているところなのですが、対象範囲がメモリ管理サブシステムだけでなく Linux カーネル全体となっています。そのため、今年は3年前を超える難易度となっており、果たして受講希望者が現れてくれるのかどうか心配しています。まずはキャンプに参加してくれないことには始まりませんので、たくさんの応募をお待ちしております。

posted by 熊猫さくら at 15:57| Comment(2) | TrackBack(0) | Linux

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

2018年08月21日

セキュリティ・キャンプ2018で使用した、熊猫のテキストを公開しました。

直ちにアップデートを適用するなどの対処を迫られるような影響範囲の大きな脆弱性が増えてきている感触がある昨今、自分が管理している Linux システムの概要を知っておくことは、障害や脆弱性への対処を行う上で有用であると考えます。

そこで、今年のキャンプでは、サポートセンタで故障解析に携わった経験を基に、 Linux システムに関するトラブルをOS視点で調査しながら、スムーズな問題解決を行うために必要なことについて扱いました。演習で使用した仮想マシンイメージ( SHA256: f139fe85117d871ff1e87ab79b9ac891555b097f8bf6976f50a051920a687967 )も公開していますので、実際に手を動かして体験してみてください。

ちなみに、同日に開催されたセキュリティ・コアキャンプ2018の方では、一昨年度の講義で扱ったメモリ管理の闇と、その後の2年間でどこまで進んだのかについて扱いました。振り返ってみると、「しょ〜もないミス」を繰り返しているんだなぁと感じます。

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

2018年01月29日

Linux 4.15 が封印解除されました。

年明け早々 Meltdown/Spectre で大騒ぎになりましたが、 Meltdown/Spectre 対応としてみんなが一斉にカーネルのアップデートを行った結果、「アップデートしたらカーネルパニックやフリーズなどが発生するようになった」という不具合報告が大量に発生して、 Bugzilla や Launchpad が大変な状況になっているようです。
メモリ管理の闇と戦っていた熊猫も、今月ばかりは、アップデートに伴う不具合報告のうち、主に Meltdown/Spectre に起因しない不具合(アップデートして発生したから Meltdown/Spectre 対策の修正が原因かと思いきや、実は全然関係ない問題だったというケース)の切り分けや修正を手伝っていました。
でも、カーネルのトラブルについて情報を取得するのに不慣れな人がほとんどで、カーネルパニック/フリーズ時のメッセージを取得できていなかったり、バージョン情報など調査に必要な情報を提示してくれなかったりと、何が起きているのか不明な不具合報告が多かったのが残念です。
まだまだ、OSレベルのトラブルに対処するノウハウは共有できていないということなんですねぇ。

先月 CELF ジャンボリーで「メモリ管理の闇」について一緒に戦ってくれる協力者を募集する発表をした際の動画が公開されています。内容は、昨年度のセキュリティ・キャンプの講義のダイジェスト+その後 Linux 4.15 までにどこまで進んだかの報告です。
どうもメモリ枯渇時の挙動を考えていないコードが多いようで、メモリ枯渇時にハングアップするバグを退治していた筈が、次第にメモリ割り当てを伴う処理全般についてバグ退治をする羽目になってきています。発表後も、(年明け早々に遭遇して 4.15-rc9 の後に修正された)メモリ圧迫時にランダムなクラッシュを引き起こすバグなど、 4.15 が封印解除されるぎりぎりまで、いろいろなバグを退治していました。

さて、封印解除といえば「カードキャプターさくら」ですね。新編が始まって「はにゃ〜ん♪」状態です。
Linux「はにゃ〜ん♪」化計画というのがあるのですが、カードを捕まえるときの掛け声が「セキュア」というのは、 TOMOYO Linux が登場する前兆だったりするのでしょうか?(笑)

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

2017年11月19日

Linux カーネルのメモリ管理サブシステムの5つの特徴

  1. メモリ割り当て処理が先に進むことを保証しない
  2. 問題が発生する可能性があっても現実に起こるまでは対処しない
  3. 故意/悪意あるいはストレステストにより発生する問題には対処しない
  4. 自力で真犯人を逮捕できない一般人は相手にしない
  5. 他のカーネル開発者の関心を惹かない問題は解決されない

「え〜っ!?」って思われましたでしょうか?でも、そういう世界なんだということが解ってきました。

Linux 4.9 で追加されてしまった warn_alloc() によるハングアップを「故意/悪意あるいはストレステストでなくても現実に起こる問題」として削除するのに丸1年かかりました。いやはや、疲れます。

「 Linux システムがハングアップしたらメモリ管理を疑え!?」という諺は、まだ有効です。意図的なストレスを掛けることで発生する問題は全力で無視されてしまうため、実際のシステムで使われている負荷を掛けることで発生することが重要です。そのためには、利用者の皆様のご理解・ご協力が欠かせません。情報の取得方法を習得して、ハングアップを見つけたら、どんどん報告してくださいますよう、お願いいたします。

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

2017年10月24日

Apache HTTP Server 2.4.29 で修正された Out Of Memory 自爆バグについて

仕事上、例えば vmcore のような、数ギガバイトから数十ギガバイトになる可能性のある巨大なファイルを転送する必要に迫られることがあります。しかし、セキュリティ上の理由でインターネット上のサービスを利用できないという制約があるため、いっそのこと自作してしまえと思い、大容量ファイルのアップロード/ダウンロードを行うためのプログラムを試作することにしました。その際、スクリプト言語などに依存してしまうとEOLへの対応が必要になるため、10年20年先も無改造で使い続けることができるであろうC言語で、そして、メモリリークや Web サーバ本体のバージョンアップの影響を受けないようにするため、リクエスト毎に fork()/execve() する Apache のCGIとして動作するプログラムとして開発することにしました。

しかし、たまにリクエストがエラーになったり、システムの動作が極端に遅くなったりと、どうも様子がおかしいことがありました。発生条件を切り分けていったところ、何と「スリープ処理を入れずに大量のレスポンスの送信を行うだけ」で発生していることが判明しました。親プロセスである Apache のワーカープロセスが、子プロセスであるCGIプログラムの出力を全てメモリ上に保持しようとしてしまい、 OOM killer に殺されるか、さもなくば、後続のリクエストに対する fork() ができなくなるというサービス拒否状態に陥っていたのです。

おいおい、メモリ管理で悩みたくないから子プロセスを使うという選択をしたのに、親プロセスが盛大にメモリを食い潰してどうするのよ〜?

/〜(^x^)〜/

ちなみに、RHELへのバックポートは httpd-2.4.6-76.el7 に含まれる予定になっているため、 RHEL 7.5 のリリース時に修正されるものと予想しています。

posted by 熊猫さくら at 22:31| Comment(0) | TrackBack(0) | Linux

2017年08月20日

セキュリティ・キャンプ2017で使用した、熊猫のテキストを公開しました。

昨年あたりからLSMを巡る動きが活発になってきたので、今年のセキュリティ・キャンプでは、 ウイルス対策ソフトをLSMから使うという 実習を行いました。

3年間のトラブルシューティングと、その後2年間のメモリ管理を巡る戦いにより、LSMの動向を5年間全然追いかけていなかったため、紺屋の白袴状態でした。 そのため、当初はLSMメーリングリストのアーカイブを読み直して、どのような挑戦が行われてきたのかを纏めてみるつもりでした。しかし、今年に入ってからも 「 Linux カーネルのメモリ管理機構の闇」を巡る死闘が続いており、リソースの大部分がメモリ管理機構のバグ退治に費やされてしまうという、ブラックホールから 逃げ出せない状況下での講義準備となりました。講義資料の中に OOM killer の話が何度も出てきたのは、そのせいでしょうか?(笑)

今年のキャンプでは、 DirtyCOW の件で巻き添えを喰らったり WikiPedia からブログリンク+本名暴露攻撃を喰らったりと有名ながちゃぴん先生とか、 Ryzen SEGV Battleという貴重な経験をした Sat 先生とかに会うことができて、楽しかったです。

posted by 熊猫さくら at 15:09| Comment(0) | TrackBack(0) | Linux

2016年12月31日

Linux 4.9 が封印解除されたけれども・・・

今年はずっと「 Linux カーネルのメモリ管理機構の闇」と戦い続けてきました。

Linux カーネルのメモリ管理機構は「他の誰かが自分のために進捗を出してくれているから自分は余計なことを考えなくていい」という楽観論で動いています。そして、全員が同じ考えで動いたとき、誰も進捗を出せなくなり、システムは静かにハングアップしてしまいます。なんだか、責任の所在が不明な、某市場移転問題みたいですねぇ。

Linux 4.6 で OOM reaper が導入され、 Linux 4.9 では「 OOM killer が発動できる限りは OOM livelock 状態に陥らないことを証明できる」ようになる・・・ことを目指していました。しかし、誰も進捗を出せなくなったことを知らせてくれる仕組みとして、ストールしている間は10秒毎に警告を出力するという楽観的な修正が取り込まれたことにより、 Linux 4.8 までは存在しなかった「ロックを獲得したままバッファが空になるまで永遠に待ち続けるA v.s. ロックを獲得できないことでバッファへの追加を永遠に続けるA以外の全員」という新しい OOM livelock 状態が発生してしまいました。よって、残念ながら「 OOM livelock 状態に陥らないこと」を証明できませんでした。

この問題は printk() がバッファが空になるまで永遠に待ち続けることが原因ということにされたため、バッファを空にする処理を専用のカーネルスレッドにオフロードすることで解消される見込みです。しかし、本当の原因は「ロックを獲得したままスリープしてしまうA v.s. ロックを獲得できないままビジーループをしてしまうA以外の全員」であるため、「ロックを獲得できなかった場合はスリープすることで、ロックを獲得しているAの処理を先へと進める」というのが正しい修正だと思うのですが、そのような修正を加えることにより予期せぬ副作用が発生することを恐れているため、採用される見込みはありません。問題を指摘しても、「 DoS 攻撃を受けていて手遅れだ」という返事。原因がカーネル側にあり、それを修正する方法が存在していても、想定を超える負荷が掛かったら諦めるしかないという、セキュリティとトラブルシューティングをやっている人の視点としては納得いかない世界なのです。こんな調子では、 DirtyCOW のような脆弱性が見つかるのも、当然かもなぁ。

ストールしている間は10秒毎に警告を出力するという楽観的な修正には、全員が同じ考えで動いた場合には機能しないという致命的な欠陥があり、問題が発生しているかもしれないことを知らせるという watchdog としての役割を果たせません。この処理を、専用のカーネルスレッドにオフロードすることで、全員が同じ考えで動いてしまった場合でも機能するようにするという提案を続けています。果たして、採用されるのでしょうか?

posted by 熊猫さくら at 11:34| Comment(0) | TrackBack(0) | Linux

2016年11月05日

セキュリティ・キャンプ2016で使用した、熊猫のテキストを公開しました。

RHEL 7.3 が封印解除されたので、自主規制を解除します。

今年のセキュリティ・キャンプでは、 Linux カーネルのメモリ管理機構の闇について扱いました。3年超の期間を費やし、3000通超の関連メールを送受信し、そして、今年1月からは会社の業務時間の大部分も使わせてもらいながら対応した、膨大な活動履歴の中から抽出したものです。

講義資料では、20年前から存在していたと考えられる脆弱性である CVE-2013-4312 および CVE-2016-2847 の発見から始まり、ずるずると闇に引き込まれていき、幾つかの問題について光を取り戻すまでを描いています。

CVE-2013-4312 および CVE-2016-2847 については RHEL 7.3 のカーネルで修正されていますので、信頼できないユーザがログインする可能性のあるシステムではカーネルをアップデートしてくださいね。先月、 DirtyCOW ( CVE-2016-5195 )への対処でカーネルをアップデートしたばかりだとは思いますが。

メモリ管理機構に起因したシステムのハングアップが発生しても、それを平均的なシステム管理者でも認知できる仕組みが存在しないため、どれくらいの頻度で発生しているのかについての情報はありません。サポートセンタに「今回のハングアップに関して、メモリ管理機構が原因の可能性はあるか?」と照会しても、「判断できない」としか答えられないのです。もし、「無い」とか「低い」とか回答するようなサポートセンタを見つけたら、この資料を見せてやってくださいな。(笑)

posted by 熊猫さくら at 13:30| Comment(0) | TrackBack(0) | Linux