コーヒーを飲む量をかなり減らした

在宅生活が本格化してからは多い時では1日10杯以上コーヒーを飲んでいたけど、さすがに飲みすぎなので1日1杯に減らした話。

2年以上ぶりにブログを書いてるんだけど、ほんとに個人的などうでもいい話です。このブログにはテクニカルな話は今後もほとんど書くことはないと思うので、テクニカルな話が読みたい人は会社のエンジニアブログを読んでください!(それもあんまりテクニカルな内容じゃないけど)

もともとコーヒーが好きで、あんまり覚えてないんだけどたしか小学校3,4年生くらいのころから日常的にコーヒーを飲むようになったような気がする。親が飲んでたコーヒーがいい香りだったのでわけてもらって飲み始めたのがきっかけだったような記憶が。
で、コロナ禍以前はオフィスで自分で淹れたりバリスタの研修を受けた同僚に淹れてもらったりで毎日6,7杯は飲んでた。朝起きてコーヒー飲んで、会社についたら1杯、午前中にもう1杯、ランチ後に1杯、みたいな。ニコチン中毒な人と変わらない行動パターン。

学校や施設などで終日研修みたいなときには、近くでコーヒーを確保できる店があるかを現地到着後まず確認したり、そういった店が見当たらないときには缶コーヒーの甘さにうんざりしながらもとりあえずカフェイン摂取を優先させたり。アルコール中毒な人と変わらない行動パターン。

コロナにより在宅勤務体制になって以降はさらにひどく、いつでもコーヒーが飲める状態=いつでもコーヒーを飲んでいる状態になって、カップが空になったら次のコーヒーを淹れてるみたいな勢い。1日の水分摂取が全部コーヒーっていうのも当たり前な生活。たぶん毎日2リットル以上コーヒーを飲んでた。

で、べつにカフェインをとりすぎて眠れないなんてことはなくって、「まだあまり眠くないけどこれ以上起きてると明日に差し障るからとりあえず横になるか」って布団に入ったら、以降まったく記憶がないくらい瞬間的に眠りに落ちてるみたいな毎日。なので睡眠という点に関しては特にカフェインとりすぎて困るみたいなことはなかったんだけど、土日に頭痛が起こるのがひどくなってきて、これは何とかしないとなと思って徐々にコーヒーの量を減らした。

もともと中高生くらいから、ときどき土日の午後に頭痛が起こることがあって、特に外出してるときによく発生するなと思ってたんだけど、そこまでひどい頭痛でもなく発生頻度も高くないし1時間もすれば治まるのでそんなものか程度にしか考えてなかった。ここ数年は2,3週間に1回くらいは発生するしそれなりにひどい頭痛なので色々原因を考えてみると、土日は平日と行動パターンが違い、外出してるときは特に、コーヒーを飲む量が少なくなり午後になるとカフェインが足りなくなって頭痛が発生しているようだと思い至った。なので、カフェインが足りないんだったら摂取すればいいってことで、土日も外出先で積極的にコーヒーを飲むようにしてたんだけど、うっかりコーヒーを数時間飲み忘れると午後には頭痛に襲われる、みたいな感じだった。

で、コロナ禍での在宅生活だと、外出しないものの頭痛の発生頻度はさらに上がり、平日でも夕方になると頭痛が起こる日が増えてきたり、痛みもひどく頭痛薬を飲むか濃いコーヒーを急いで飲むか寝るかみたいな、明らかにこのままではよくないなって状態になってしまった。

そんなわけで、これはカフェインの量を減らすしかないと一念発起し、1か月くらい時間をかけながらコーヒーを飲む量を徐々に減らし、今は朝に1杯飲むくらいになった。昼にデカフェを飲むことはあるけど。

結果的に、この数か月は頭痛もほぼ発生しておらず、まあそりゃそうだよねって感じです。そんなわけで、みなさんもコーヒーの飲みすぎには気を付けましょう。

 

alertを出したいんだ俺たちは

利用者に対してメッセージを意識的に伝えたり、あるいは何かしらの行動を促すために、ダイアログボックスを表示するための機能がブラウザーには複数実装されている。alertの聖地、兵庫県出身者として、その手の機能を以下にまとめた。

機能 UIの占有など 機能、特徴
javascriptの window.alert メソッド タブモーダル 任意のメッセージが表示可能。繰り返し表示される場合にそれを抑止する機能がほとんどのブラウザーに実装されている。
javascriptの window.prompt メソッド タブモーダル 任意のメッセージが表示可能。任意の1行テキストが入力できる。繰り返し表示される場合にそれを抑止する機能がほとんどのブラウザーに実装されている。
javascriptの window.confirm メソッド タブモーダル 任意のメッセージが表示可能。OK、キャンセルのボタンを持つ。繰り返し表示される場合にそれを抑止する機能がほとんどのブラウザーに実装されている。
HTML5の <dialog> 要素 タブモーダル 任意のUIをHTMLで作成可能。showModal メソッドで表示させた場合、close メソッドを呼び出して明示的にダイアログを閉じるまでHTML内への操作はできない。一部ブラウザーでのみサポートされている。
BASIC認証のログインダイアログ タブモーダル HTTPで401応答を返すことで表示されるログインダイアログ。realmで指定可能な文字種が限定的であり、またrealmで指定した文字列が表示されるブラウザーと表示されないブラウザーがあるため、任意メッセージの表示には不向き。繰り返し表示を抑制する機能はないため、何度も繰り返して表示させない方がいい。
javascriptの window.print メソッド ウィンドウモーダル。一部のブラウザーではタブモーダル javascriptから window.print() することで表示される、印刷を促すダイアログ。任意メッセージの表示はできない*1。多くのブラウザーではウィンドウモーダルで表示されるため、他のタブに切り替えてそのページを閉じるということは難しい。繰り返し表示を抑制する機能はないため、何度も繰り返して表示させない方がいい。
Edge、IEの ms-get-started: プロトコルや calculator: プロトコル ウィンドウモーダル これらのプロトコルスキームを window.open すると、外部のアプリに切り替えていいかのダイアログが表示される。任意メッセージの表示には不向き。ウィンドウモーダルで表示されるため、他のタブに切り替えてそのページを閉じるということは難しい。繰り返し表示を抑制する機能はない。Edgeの場合、ダイアログが表示されるごとにFile Picke UI Hostというプロセスが起動する。ダイアログを閉じていなくても複数のダイアログを連続して表示可能。これらの特徴から、ループ内から繰り返しダイアログを表示するのは非常に煩わしいため、そのようなコードは避けた方がいい。

他にも色々あるけれど、とりあえず人間に対して任意のメッセージを伝えるにはalertがいちばん使いやすいのでこれからも積極的に使っていきたいところ。

*1:CSSの指定により印刷プレビューでのみ何かしらのメッセージを伝えることは可能

[雑記] コミックマーケット93向けに本を書きました

@nash_fsさんに誘われて、明日のコミックマーケット93で合同誌「WebMix」に記事を書きました。

掲載内容は

です。

[Joke] ローカルネットワークに対するクロスオリジンの攻撃からシステムを守る簡単な方法

インターネット上に公開されているわなサイトを経由して社内イントラネットなどのローカルネットワークへXSSやCSRFなどのクロスオリジンでの攻撃を仕掛けようという試みは古くから存在します。現実にこれらが行われたという話は聞いたことはありませんが、理論上は可能であるという話をよく聞きます。対策としてまず検討すべきは、社内システムであっても通常のシステム同様に脆弱性を生まないようセキュアなものにするということです。それらが難しい場合には、少しの手間でローカルネットワークに対するクロスオリジンでの攻撃を低減させることができます。

フィドラでクロスオリジンからの攻撃を低減させる手順

Fiddler を起動し「Rules」メニューから「Customize Rules...」をクリックします。エディターが立ち上がってルール用のFiddlerScriptの編集画面が出てきますので、以下を追記します。

function isLocalServer(host:String):Boolean {
    // TODO: 環境に合わせてここを修正して下さい
    const localServers = ["server-name-1", "server-name-2"];
    var re = /^([\d]{1,3})\.([\d]{1,3})\.([\d]{1,3})\.([\d]{1,3})$/;
    var m = re.exec(host);
    var i;
    // プライベートIPアドレスのホストはローカルのサーバーとみなす
    if (m !== null) {
        m[1] = m[1]|0;
        m[2] = m[2]|0;
        m[3] = m[3]|0;
        m[4] = m[4]|0;
        if (m[1] > 255 || m[2] > 255 || m[3] > 255 || m[4] > 255) return false;
        if (m[1] === 10) return true;
        if (m[1] === 172 && (m[2] >= 16 && m[2] <= 31)) return true;
        if (m[1] === 192 && m[2] === 168) return true;
    }
    // ローカルサーバーの一覧に存在するかチェック
    for (i = 0; i < localServers.length; i++) {
        if (host.Equals(localServers[i]) ){
            return true;
        }
    }
    return false;
}

class Handlers
{

    // 省略

    static function OnBeforeRequest(oSession: Session) {

        // 省略
       
        // ターゲットがローカルサーバー
        if (isLocalServer(oSession.hostname)) {
            var from = oSession.oRequest.headers["origin"];
            if (from !== "") {
                from = from.replace(/^https?:\/\//,"");
            } else {
                var m = /\/\/([^\/]+)\//.exec(oSession.oRequest.headers["Referer"]);
                if (m !== null) {
                    from = m[1].replace( /^[^@]+@/,"");
                }
            }
            // 呼び出し元がローカルサーバーではない
            if (!isLocalServer(from)) {
                FiddlerApplication.Log.LogFormat("Blocked {0} from {1}", oSession.fullUrl, from);
                oSession.utilCreateResponseAndBypassServer();
                oSession.oResponse.headers.Add("Content-Type", "text/plain");
                oSession.oResponse.headers.HTTPResponseCode = 404 ;
                oSession.oResponse.headers.HTTPResponseStatus = "404 Not Found";
            }
        }
    }
}

たったこれだけで、外部のわなサイトを経由したクロスオリジンの攻撃からローカルシステムをある程度守れます。

まとめ

やっていることは、通常は社外の公開サーバーをRefererやOriginとして社内に対してリクエストが発行されることはないので、それを検知した場合に404応答を返しているだけです。ただし、もちろんのことながら、ReferrerやOriginがつかない状況も頻繁に発生するので、そういった場合にはこの方法では攻撃を防ぐことはできません。繰り返しになりますが、社内システムであっても社外のシステム同様にきちんと脆弱性への根本的な対策を行っておくべきでしょう。

サイボウズ バグハンター合宿に行ってきた

先週の11月3日-4日に開催されたサイボウズ バグハンター合宿に参加してきた。

3年前は個人戦だったけれど今回はチーム戦ということに加え、クソつまらない脆弱性を多数報告した場合は評価が下がる採点方式だったので、最初はチームの足を引っ張らないようホームラン級のバグを探そうとしたけれど、最近すっかり技術的なことをやっていないのでなかなかそういうバグも見つけることができず、ゼロよりマシだろうということで結局わりとくだらないバグをいくつか報告した次第。とはいえ、他の人はあまりやらないだろうなという「クロスオリジンでの情報漏えい」みたいな自分としては好きなタイプのバグをひとつ見つけて報告することができたので、その点は満足。結果的にチーム順位は最下位、個人順位ではかろうじて10位に入るという感じでした(下から数えた方が早い)。Masato Kinugawaさん強すぎ。

いろんな攻撃手法に関して、以前なら自分の技として適切な場面でそれを取り出して使えることが多かったけれど、だんだんと手を動かす時間が減るにつれ他の人の攻撃例を見て「ああ、そうか。そこでその攻撃手法が使えたんだ!」みたいな感覚になっていってたんだけど、さらに今回は「なにそれ。そんな攻撃方法あったのか」みたいに全く知らない技がいくつもあったりして、すっかり時代においていかれた感を味わってきた。

実際にサイトを検証するのは、CTFと違って「問題のための問題」みたいなのではなく、実際に生きて動いてるWebサイトなのでどれだけ不合理で不自然なかたちであっても脆弱性が存在すればそれは現実のものなわけだし、あるいは特定の挙動についてあるサービスではサービスの提供方針として脆弱性として認定されるものが他のサービスでは脆弱性とは認定されないというような運用指針に寄るものがあったり、そういう点でリアルな世界なので学びも大きいし超楽しかった。

次回が開催されるのかはわからないけれど、もし開催されるのであれば次は事前にちゃんと予習復習をして、もうちょっと人権をちゃんと確保したい。

[SECURITY] podcast 第1回 セキュリティの『アレ』

@ntsujiさん、@MasafumiNegishiさん、mtakeshiさんのポッドキャスト「セキュリティの『アレ』」の収録にお邪魔してきました!

人に聞かせるために話すっていうよりは、辻さん根岸さんに解説してもらいながら3人との会話を自分自身が楽しむみたいな感じでした。ゆるゆるグデグデな感じですけどよろしくお願いします!

安全な脆弱性の作り方

この記事は 「脆弱性"&'<<>\ Advent Calendar 2016」16日目の記事です。具体的な脆弱性の話でなくてすみません。いろいろコードを書いていると、安全に脆弱性を発生させたくなるときがあります。って書くとさっぱり意味がわからないと思いますが、セキュリティの講義のための演習環境とかそういうやつです。

受講生自身の手でWebアプリケーションの脆弱性を探してもらうような演習では、検査対象となる脆弱性を含むWebアプリケーションを用意する必要があります。こういった「脆弱なWebアプリケーション」は例えば Broken Web Applications Project のようなものを代表にいくつかのものがありますが、これらはUIが英語であったり、あまりにもメジャーすぎて受講生も触っている可能性があったりと、場合によっては利用が難しいことがあります。特に、単一のWebサーバに対して複数の受講生が一斉に検査を行うような講義形態を採る場合(各自が手元でVMを立てて一人で検査を進めるよりも、同じサーバに全員でアクセスするほうが講義が盛り上がるのです)、環境に対して破壊的な脆弱性が存在していては演習そのものが中座してしまう可能性があります。

そこで、こういった講義を行う際には私はその講義の受講生のレベルなどに合わせて調整した脆弱なWebアプリケーションを都度自分で書いているのですが、そのときに「脆弱性があっても安全になるように」いくつか気を付けている点があります。今日はそういった点についてメモ書きとして記しておきます。

SQLインジェクションではデータベースを破壊できないよう読み取りのみに制限しておく
以前、演習の早い段階で参加者の一人がSQLインジェクションで他の参加者のパスワードを変更してしまったために他の参加者は演習を進めることができなくなったということがありました。それ以降は、SQLインジェクションを仕込むときにはデータベースの読み取りはできるが更新や削除といった破壊的な操作はできないように権限などを適切に設定する等の対策を行ってSQLインジェクションを含ませるようにしています。
CSRFは発生してもユーザーの妨げにならないものに限定する
以前の演習で、ログアウト機能にCSRFがある かつ ログイン直後に表示される個所で自由に画像ソースのURLを設定できる(これは脆弱性ではなくアプリケーションの機能) というのを組みあわせて、ログインすると直後に強制的にログアウトさせられてしまうという罠を参加者が仕込んだことがあり、その場合もやはり演習がそれ以降進まなくなってしまいました。ですので、CSRFを仕込む場合にはCSRFによって機能が呼び出されたとしても以降のユーザー操作に影響を与えない、例えばお問合せフォームの送信やニックネームの変更など、といった個所に限定するようにしています。
XSSもCSRF同様にユーザーの妨げにならない個所に限定する
XSSを仕込んでおく場合も、CSRF同様に仮に悪用されてもユーザーの操作の妨げとならないような個所だけで発生するようにしておきます。例えば、XSSの発生する個所をユーザー操作の必要な個所に限定する、蓄積型のXSSであっても例えばそのメッセージを開く前に削除できるようにする、といった感じです。
OSコマンドインジェクションは入れない
OSコマンドインジェクションは環境を破壊してしまう恐れが強く、特に参加者がそのことを把握していないような場合には何が起こるかわからないので、基本的には脆弱性としては含ませないようにします。
セッションアダプションは積極的に採用
攻撃者の用意したセッションIDを利用者に強制させるセッションアダプションはユーザーによって回避可能であり操作不能となるようなことがないため、実装上無理がない限りは脆弱性として積極的に取り込んでいきます。
オープンリダイレクタも積極的に採用
たいていの場合、オープンリダイレクタも演習の妨げとなるような致命的な問題が発生しにくいため、積極的に組み込んでいきます。ただし、そのリダイレクタが永続的かつユーザーの操作なしに有効となってしまいユーザーが以降の演習ができなくなるといったような個所には絶対に含まれないように注意が必要です。
安全でない暗号
対象となるWebアプリケーションにそれっぽいセキュリティポリシーの文面を掲載しておき、例えばそこに「このサービスは通信経路上が暗号化されているため安心してご利用頂けます」等を記載しつつhttpでアプリケーションをサーブするといった、技術的でない脆弱性を含ませておきます。これは他の脆弱性と違い環境を破壊されないので安全であり安心してサービスを提供できます!

これ以外にも「HTMLコメントやJSコメントに機密情報(らしきもの)を記載しておく」といった小さな脆弱性を含ませることもあります。
それにしても思うのは、このような脆弱性を自然なかたちで作りこむのはそれなりに難しいのに、世の中のWebアプリケーションではもっと信じられないような脆弱性が普通に存在していたりして、一方でこれだけ頑張って安全に配慮して脆弱性を作っているにも関わらず、ちょっとしたバグを利用して Masato Kinugawa さんにサーバ上で電卓を立ち上げられてしまうことがあったりと、なかなか世の中難しいなというところです。