ping を実行するのに CAP_NET_RAW は必要なくなっていた

必要がなくなっている、というか特定の条件では CAP_NET_RAW は不要という話。 ある講義で Capability について話す機会があり、いつもどおり CAP_NET_RAW が必要な ping を使った実験をしていたところ、環境によっては CAP_NET_RAW File Capability を与えなくても ping が実行できることに気づき、少し調べてみました。 どうも随分前に net.ipv4.ping_group_range というカーネルパラメータが追加されていたらしく、これを設定することで ICMP ソケットを扱うグループを指定できるため、 CAP_NET_RAW や setuid なしで実行できるようになっていたようでした。 以下、調べたことを書いておきます。 ubuntu 18.04 では CAP_NET_RAW なしでは動かないのに対し、ubuntu 20.04 では CAP_NET_RAW がなくても動くようでした。 まずは ubuntu 18.04 で確認してみます。 ubuntu@18.04:~$ uname -a Linux 18.04 4.15.0-109-generic #110-Ubuntu SMP Tue Jun 23 02:39:32 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux ubuntu@18.04:~$ cat /etc/lsb-release DISTRIB_ID=Ubuntu DISTRIB_RELEASE=18.04 DISTRIB_CODENAME=bionic DISTRIB_DESCRIPTION="Ubuntu 18.04.4 LTS" ubuntu@18.04:~$ cp `which ping` myping ubuntu@18.

Infra Study Meetup #6 で登壇した

@matsumotory さんからお誘いいただいて、登壇した。 https://forkwell.connpass.com/event/187694/ テーマは「インフラとセキュリティのこれから」ということで、コンテナや Kubernetes のセキュリティについて、DevSecOps の進め方などについて話した。 当日の様子は YouTube に上がっているので、どうぞ。また、使ったコマンドなどは gist にあります。 Infra Study の過去回を見るに、参加者層が幅広い印象を受けていたので、広く浅くセキュリティについて話そうと思った。 Docker などによって Linux コンテナは広く普及し、Linux コンテナの仕組みを理解している人も増える一方で、あまり Linux コンテナ自体(イメージではなく)のセキュリティについて触れている人はそう多くないと感じていた。 また、Kubernetes のセキュリティといえば PodSecurityPolicy 周りについて触れられることが多いが、そもそも Linux コンテナのセキュリティを知らなければ、これを適切に設定することは難しいだろう。加えて Kubernetes の Attack Surfaces やマネージド環境でのセキュリティについて日本語で触れられている記事も多くないので、そのあたりの啓蒙をしようと思い、これらについて話すことにした。 内容としては以前セキュリティ・ミニキャンプなどで行ったコンテナセキュリティの講義からいくつかピックアップしたものに加え、Kubernetes セキュリティについて付け加えた。 …とスライドの内容について書こうと思ったけど、動画を見てもらう方がいいので、ここでは割愛で。 Twitter の様子を見る限り、プラスな反応が多くてよかったと思う(Infra Study の参加者が優しいというのもあるが…)。 自分は質疑応答が本当に苦手で、想定質問をかなり考えて望んだのだけど、思った以上に DevSecOps や組織でのセキュリティ文化についての質問が多くて、想定していた質問は一個もこなかったw slido への質問 当日時間の関係で答えられなかった質問があるので、ここでいくつか回答しようと思う。 https://app.sli.do/event/n9r09kec/live/questions コンテナでイミュータブルだぜ、と言いつつyum updateとかapt upgradeしているかと思うのですが、イミュータブルを目指す環境とアップデートの頻度やライフサイクルの兼ね合いはどのように考えられていますか? コンテナで apt upgrade などをしたことがない… アップデートの頻度は自由に決めていいと思いますが、脆弱性に関してはリスクに応じてすぐに対応する必要があると思います。 イメージをスキャンして、アップデートもしくはパッチを適用して、イメージを再構築するパイプラインやジョブを作って自動化するのが「イミュータブルを目指す環境」には必要だと考えています。 加えるとコンテナ内で root で実行することはベストプラクティスではないので、そこも禁止するべきだと思っています。 脆弱性が頻繁に出るというのは、そもそも不要なパッケージが含まれていたりするケースもあるので、つまるところベストプラクティスを実践していくと、次第にセキュアになっていくと思います。 PaaSのセキュリティについてお聞きしたいです。

procfs の hidepid オプションについて調べた

profs の hidepid オプションの値 procfs のマウントオプションに hidepid というオプションがあることを知った。 man で確認すると 0~3 の値を取るらしい。 hidepid=n (since Linux 3.3) This option controls who can access the information in /proc/[pid] directories. The argument, n, is one of the following values: 0 Everybody may access all /proc/[pid] directories. This is the traditional behavior, and the default if this mount option is not specified. 1 Users may not access files and subdirectories inside any /proc/[pid] directories but their own (the /proc/[pid] directories themselves remain visible).

wazuh の Fluentd forwarder を使って agent の任意のファイルを td-agent に送る

wazuh agent が入っているホストの任意のファイルを td-agent に送る方法をメモしておく。 単純にログを収集するのであればホストに td-agent を入れればいいのだが、例えば管理している全てのホストにおいて、特定のログを収集したい場合、全部に td-agent を入れるのは面倒くさい。 (wazuh agent を全部入れるのも面倒じゃないか!というのは、それはそうなのだが…) wazuh には Fluentd forwarder という機能があって、わざわざ td-agent を追加で入れなくても ossec-logcollector と併用することで、リモート / ローカルの td-agent に forward することが可能。 https://documentation.wazuh.com/3.12/user-manual/capabilities/fluent-forwarder.html wazuh は閾値を使った監視に弱いが、これを使うことで例えば CloudWatch や BigQuery などの wazuh とは別のログ分析システムに送信することで、閾値を使った監視も可能になる。 まぁ td-agent が入っているならそれを使えばいいのだけど、あえて wazuh でやるメリットとしては Centralized configuration によって全 agent に対して集中的に管理ができるということかな。 使い方は上記ドキュメントの通りなのだが、メモ程度に書いておく。 まずは td-agent の設定。forward の設定と CloudWatch に送信する設定を入れておく。 <source> @type forward port 24224 bind 0.0.0.0 </source> <match **> @type cloudwatch_logs @id out_cloudwatch_logs log_group_name "#{ENV['LOG_GROUP_NAME']}" auto_create_stream true use_tag_as_stream true retention_in_days "#{ENV['RETENTION_IN_DAYS'] || 'nil'}" json_handler yajl log_rejected_request "#{ENV['LOG_REJECTED_REQUEST']}" </match> 続いて agent に fluentd-forwarder の設定を入れる。

複数の Pod でコマンドを実行できる kubectl-multi-exec を作った

Kubernetes で遊んでいると、指定した Pod 全てで同じコマンドを実行したいというケースがありました。 kubectl exec -l app=test のような感じで label を指定して実行できれば良いのですが、今はできません。 https://github.com/kubernetes/kubernetes/issues/8876 上記 issue にありますが、頑張ってシェル芸をするというのが現状です。 そんなに使うこともないし、わざわざ覚えるのも面倒なので kubectl plugin として PoC レベルですが作りました。 https://github.com/mrtc0/kubectl-multi-exec PATH が通っているところにバイナリをコピーして kubectl plugin でインストールを確認します。 ❯ kubectl plugin list The following compatible plugins are available: /usr/local/bin/kubectl-multi_exec 使い方ですが、例えば app=test というラベルを付けた Pod に対してコマンドを実行するには、次のように multi-exec サブコマンドで --selector option にラベルの key/value を指定することで、あとに続くコマンドが実行されます。 ❯ kubectl get pod -l 'app=test' NAME READY STATUS RESTARTS AGE test 1/1 Running 0 25s test2 1/1 Running 0 18s ❯ kubectl multi-exec --selector 'app=test' -- hostname test test2 ❯ kubectl multi-exec --selector 'app=test' -- uname -a Linux test 4.

アプリケーションを oauth2-proxy で保護して curl でアクセスするまで

追記 2020-05-13 この方法に問題があることをご指摘いただきました。本来関係ないクライアントがリソースサーバーにアクセスできる問題がありますので、取り急ぎこの方法は非推奨であることを書いておきます(では、どのようにすればいいのかというところをまた後日追記します)。 リソースサーバーと全く関係の無いクライアントが、全く関係のない文脈で正当に取得した ID トークンを用いて、リソースサーバーの API にアクセスできてしまうと思われます。リソース側が evil かどうかも関係なく、むしろリソースサーバーは騙される側ですね。図を参照してください。 pic.twitter.com/kKCZohOgu2 — Taka@Authlete, BaaS for OAuth 2.0 & OpenID Connect (@darutk) May 13, 2020 追記 2020-05-18 結論としてはこの方法は ID Token の扱いとしてはふさわしくなく、利用すべきでないと思い直しました。 自分の言葉足らずなところがありましたが、この方法は自身が管理している Internal 向けのアプリケーションに対して施すことを想定して書きました。 上記のツイートにリプライしていますが、Internal 向けで Client ID / Secret も漏洩しにくい状況で、認証するメールアドレスはドメインを絞った上であれば aud の検証が oauth2-proxy で行われている以上、セキュリティリスクは低いと思ってのことでした。 で、次の記事でもご意見をいただきました(この記事で参照されている記事やコメントが大変参考になります)。 https://ritou.hatenablog.com/entry/2020/05/17/194005 ID Token ではなくアクセストークンを使えというのはその通りであり、ID Token はセッション目的で使うものではないので、セッションはまた別で生成する必要があると思います。 ID Token もそれだけで IdP 側から情報を取得できるので、それを refresh を利用して多用するよりも認証後にセッションを自前で張る方が安全でしょう。 https://developers.google.com/identity/protocols/oauth2/openid-connect には次のようにあります。 After obtaining user information from the ID token, you should query your app’s user database.

fakeobj を利用して任意アドレスの読み書きを行う

前回は Memory Corrupution まで行ったので、今回は任意のアドレスを書き換えるまで行う。 任意アドレスを行うにあたって、次のようなメモリレイアウトを用意する。 これは PoC を参考に自分の理解のためにお絵かきしたもの。 今見返すと自分でも読めないし、これでわかる人いないと思うが… 簡単に説明すると、まずは outer というオブジェクトに hax という fakeobj を作る。 hax の butterfly は spray したオブジェクトの一つである victim を指すようにする。 その後 victim[1] や hax をゴニョゴニョすることで boxed と unboxed という2つの object が同じ butterfly ポインタを指すようになるという話。 重要なのは型の違いで、 victim は ArrayWithDouble なのに、そのさきが ArrayWithContiguous なので解釈がズレるという点。 まずは spray 部分からコードで見ていく。 var structure_spray = [] for (var i = 0; i < 1000; ++i) { var ary = [13.37]; ary.prop = 13.37; ary['p'+i] = 13.