XSSになりたい

Webセキュリティとカメラと写真と

就職した話、ctf4bやる話、CSPの話

やぎはしゅです。しばらくブログを書いてなかったので近況報告を兼ねて更新します。


社会人になりました。

時の移ろいは早いもので、入社してもう2ヶ月になります。概ね楽しくやってます。
研修はけっこう退屈ですが頑張って知らないこと、新しいことを探しながら日々暮らしてます。今はあなたとJAVA, 今すぐダウンロードしてます。
LLばっかり書いてきたので型(゚Д゚)ウゼェェェってなったりしつつもまぁうまくやってます。
ちなみに研修はあと1ヶ月弱続きます。

最近の楽しみは寮の部屋で飲むコーヒーなんですが、備え付けの冷蔵庫がクソくて氷の確保ができていないのでアイスコーヒーが飲めず夏乗り切れるか不安です。誰か冷蔵庫買ってください。冷凍室付きのやつ。


今年もctf4bやります。

既にアナウンス済ですが、本年度もCTF for ビギナーズの運営メンバーとして活動します。
ただ今年は講義を担当することはなさそうです。就職してあまり自由に動けなくなったのと、属人的な運営になってしまうのを避けるために早々に抜けて後に席を譲りました。
私よりずっとできる人なのでまったく不安はないですが、札幌は受付係しつつ様子見てます。

本年度は一般向けに全8回、セキュリティ・キャンプ全国大会2015でキャンプ生向けに1回、計9回の開催を予定しています。
私は札幌と東京と大阪(とキャンプ)には参加する予定です。見かけたら声かけてください。

昨年度から始めてずいぶん大規模になったなぁと思います。とても感慨深いです。
バタバタと始まって始終バタバタしながら終わった2014年度でしたが、今年も引き続きバタバタしそうです。
まず運営が楽しくやるのが全てのスタートかな、と思ってます。今年もよろしくお願いします。


Firefox OS勉強会で話してきました。

CSPとFirefox OSを絡めた話をしてきました。
ざっくりとCSPの概要や注意点、加えて少しだけCSP Lv.2についても言及しつつな25分間でした。
今回は実際的な使い方についてはほとんど言及しないという方針を取ったので、あまり馴染みのない人でもちょうどよいレベルになったのかな、と思います。
unsafe-inlineの話でjavascriptスキームに言及するのを忘れていたので少し修正したスライドをアップロードし直しました。
何気に人前で話すのが久々で、序盤はまぁまぁ掴めていたとは思うんですが後半はやっぱり単調になってしまいました。反省反省。

この手のネタは単調になりやすいので気を使ってはいるんですが、内容を詰めていく過程でスライド自体が単調になってしまうのでなかなか難しいです。
最後まで勢いを保って喋れるよう頑張らないと…。

そういえば念願のOpen Web BoardをGETしました!!
テンションあがってきた

超うれしい。実機ってやっぱりテンションあがりますよね。
KDDIさんに感謝!!
次は普通の端末かな。Pixi3、日本で買えるのかなー。


まとめ。

  • とりあえず概ね元気
  • 今年もお外での活動は手広くやっていきたい
  • 仕事も早く一人前になれるよう頑張りたい

やぎはしゅ、大学卒業したってよ

退職エントリーならぬ卒業エントリーを書きます。

慶應義塾大学環境情報学部を卒業しました。

スーパーファミコンの略称みたいなキャンパスに4年間通ってました。
3月10日に成績が発表され、去る3月23日に学位記を無事受け取りましたのでご報告いたします。

タイトルからまぁ自分語り全開なので興味ない人はここでhistory.back() || window.close()してください。
なんとなく自分語りがしたいお年頃なんだなぁと生暖かい目で見守っていただければと思います。
なんかこう、とうとう学生じゃなくなったのかーと考えるとけっこう込み上げてくるものが(ない)。


入学前

受験生時代はそもそも商学全般がやりたくて大学を選んでいたため他に志望していたのはW大学商学部・社会科学部、M大学商学部、C大学経営学経営学科とかでした。万に一つも浪人はしないようにとのお達しだったのでM学院大学とかも受けましたが今となってはいい思い出です。
SFCに合格後もそれは変わらず、入学後はその辺のことをやりたいなーとざっくり思ってました。


3.11

ちょうど卒業式の日で、バタバタしたのを覚えてます。
なんやかんやあって入学が1ヶ月遅れになってだいぶ萎えました。
なんというか春休みってただでさえだいぶ暇なんですよ。
それがさらに1ヶ月伸びてしまったので、やることなくてぼけーっとしてたと思います。
東日本はどこも大変だったと思いますし仕方がないことなんですが節目にそれが起こると後に響きますねーやっぱり。
高校の入学式は嵐みたいな日で、卒業式は震災、成人式は大雪と、節目運はあまりない人生でした。


入学後

1ヶ月入学が遅れた分試験がなくなったり土曜日に各講義1回ずつ授業を実施したりといろんな影響があった1学期目でした。
いろいろ慣れない分試験がなかったのはおいしかったのかもしれません。
この頃の履修履歴を見るとマーケティング戦略とか取ってて「うわぁ…」って感じです。
なんか違うなぁという違和感を持ったのがこの時期でよかったと思います。
HTMLとかCSSとか触って楽しいなーときゃぴきゃぴやってたこの頃はなんかよかったです。


情報セキュリティとの出会い

「セキュリティやり始めたきっかけは?」と聞かれることが多いんですが、いろんな要因が絡んでいて説明するのが大変で、たいてい適当に取り繕って答えてきました。
最初から全部時系列順に説明すると

  • ひろたんHackmeっていう面白いサイトがあるよ!」←入学前
  • koukiさんという悪い人がいるサークルにちょっとだけ出入りするように。←入学直後
  • 「情報通信セキュリティとプライバシー」という授業を履修してkoukiさんと再びの出会い→koukiさん「僕と契約してXSS報告マシーンになってよ!」←1年生の秋学期
  • 「情報通信セキュリティとプライバシー」の担当である武田先生の研究室に行ってみるとそこにaspさんがいて、aspさんの卒論のテーマが面白かったので興味を持ってセキュリティやってみよう、ということに。←2年生の春

以上を経てセキュリティやり始めました。
しばらくはXSS報告マシーンとしてたくさん統計操作XSSを報告してました。
f:id:yagihashoo:20150317005302p:plain

いろいろやり始めた頃、つまり2年生の初夏に↑上で出てきた人達に「セキュリティ・キャンプっていうのがあるよ!」と言われてセキュキャンに応募しましたが落ちました。
今思うと落ちて当然というかなんというか、本当に何も知らん子だったので。。。
結局キャンプには1年後行けたわけですが、まぁそのときも本当に何も知らん子のままでしたし今も何も知らん子のままだと自分では思ってます。
人間一生勉強していかないとダメですね、ほんと。まだまだです。


キャンプ後

自分の中ではキャンプに参加したあたりが節目になっていて、それ以降はちょっとだけ真面目にいろいろなことに取り組むようになりました。
CTFやりたいなーと思ってキャンプ終わってすぐのSECCON CTFに出て8位(個人戦だった)取ったり、OWASP Nightとか行ってわいわいしたりしてました。
その年のSECCONは、周りにいた人達を誘って********というチームを結成して出てました。
東海大会で1位取って全国で7位取って、ととりあえず近くにいた人を集めて作ったチームとしてはまずまずいけたんじゃないかなーと思います。(今年は本当にダメダメでしたけど。各位いろいろ申し訳ない。)

横浜大会8位

東海大会優勝


就活

そうこうしてる間に就活生になって、リクルートスーツ着ていろんな会社を受けてました。
嘘です。スーツあんまり着ませんでした。
たぶん10社と少しくらい受けたんですが、縁あって情報セキュリティに関わるお仕事ができることになりました。

こういう言い方をすると割と月並に聞こえるし実際たぶん月並なんですけど、就活を通していろんなことを学べたのでよかったなぁと思います。
歪な型で固められてる日本の就活ですけど、やり方次第ではそれなりに活用できるし、結局のところ自分次第なのであんまりdisるようなものでもないと考えてます。
自分の就活を振り返ると、セミナーに参加して何回も面接して…みたいな普通の就活と、そうでない就活と、一応両方経験できたのがよかったと思います。
直接いろんな人に会って話を聞くとその業界の構造とかがきちんと見えてくるので非常に面白かったです。
昨年の今頃はたくさんの方にお世話になりました。ありがとうございました。


お外での活動

3年生の後半に入ると、だんだん大学に飽きてきて、お外で遊び回るようになりました。
ちょこちょこいろんなイベントに顔出して、ちょこちょこ勉強会に参加して…という具合で遊んでました。
いろいろやってるうちにCTF for Beginners(CTF for ビギナーズ)という勉強会の運営に誘われて、第1回開催から1ジャンル丸々担当してきました。
大変好評で、反響も大きく、運営の1人としてはとても嬉しく思います。(運営としての活動が認められて、JNSA特別賞を頂戴しました。)
これまでに5回の開催を経て、運営側にもたくさんのノウハウが蓄積され、スムーズな運営ができるようになりました。
一方で実施後のアンケートでのご意見・ご指摘がグサグサ刺さったりもしていて、企画・運営側の厳しさも痛感した次第です。
勉強会を運営している以上こちらが学びの場を提供しなければならないのはもちろんなのですが、運営側に立つことでの学びもまた大きかったです。
関係各位には大変お世話になりました。今後ともよろしくお願いいたします。


大学生活雑感

ここまで大学の話をあんまりしてないので掻い摘んで記しておきます。

学内でCNSコンサルタントというお仕事をしてました。けっこうな時間をそれに費やしてたと思います。
CNS GUIDEっていう新入生に配られる冊子の制作の取りまとめをしてた時期が一番キツかったです。
ちょうど前年度からISSN/ISBNが振られるようになってちょっとテンションあがりつつ作ってたのが懐かしいです。
新入生が最初に手に取るものなので、できるだけ良いものを作りたくて頑張ってました。
それでもまぁなかなかうまくいかないものだなぁというのが感想です。
神経質に完璧を追い求めるのも時には大事なんですが、もう少し大局的に完成された状態を目指すというのも必要だったと今思います。
SFCって比較的学生が自由にできて、物事を改善するのに学生がダイレクトに動ける基盤が整っていると思うのですが、CNSコンサルタントという組織はその傾向がとても強いです。
一応上部組織として湘南藤沢ITCがありますが、運営の主体はあくまで学生です。
光らせるも腐らせるも運営する学生の手腕次第です。ぜひいろいろなことに挑戦してください。

Instagram

学業の成績は普通です。成績証明書から計算するGPAでだいたい3.5強。
ただしKO大学の成績証明書には落とした科目が載らないので[以下自主規制]

研究については、決して優秀な学生ではなかったと思います。
あまり好きになれなかったのは残念ですが、たくさんの学びがありました。
無駄にせず、きちんと活かしていきたいです。


卒業式とか

最近夕方に起きる生活が続いていたので急に6時起きで完全に時差ボケでした。
結局日付が変わる少し前に帰宅したのでだいたい18時間動いていたことになります。
もっと言うと4時半くらいまでは起きていた気もするので23日だけで見るとたぶん1時間くらいしか寝てなry

とにかく起きて式に出て学位記いただいてきました!!
いろいろと思うところはありましたが言ってよかったです、卒業式。
やっと一区切りというか、なんというか。Take Off Rallyも行ってよかったです。
「こういうの来るキャラじゃないじゃんww」とか言われたりもしましたしまぁその通りなんですが行ってよかったです。
最後の日だけど新しい知り合いができたり、前々から話してみたかったけど話せてなかった人だったり、人が集まるのはいいことですね、ほんと。


SFC Student Award

SFC Student Awardという賞をいただきました。

Instagram

ざっくり言うと、いろいろ見つけて報告していたことに対しての表彰です。
大きいのから小さいのまでちょこちょこ見つけては報告して…を繰り返していたのですが、特に謝辞の掲載等もなく、「俺は別にいいけど今後続く人がやる気なくなりそう」と思っていたところへの表彰でした。
報告する側としては、Webページ上への謝辞の掲載など、微細なものでも客観的に見せられる何かがあれば外向きに出せるため、非常にありがたいです。
バグバウンティでもそうですが、こういった形でのリターンを設けることで、よりよいシステムを作るための基盤や雰囲気が作られていくと思います。
そのための前例を作れたという点で、SFCに残せたものはあるのかな、というのが私見です。
Award表彰にあたって動いてくださった方々にはとても感謝しています。ありがとうございました。
今後も精進してまいりたいと思います。

なんか本当はこの後にも長々と書いたのですが恥ずかしくなったのでやめます。
今後何かを報告する人は優しさを持ってincident@sfc.keio.ac.jpにメールで報告して欲しいなぁと切に願います。
なんだかんだ中の人が忙しかったり、諸コストが高すぎてそこそこヤバい脆弱性でもなかなか修正されないことも多いのですが、そういうのって仕方がないことですし、管理者が認識しているか否かという点で非常に大きな違いがあると思います。
ぜひ「どうせ直らないから」と高を括らずに報告してください。優先度の高いものはちゃんとすぐに動いてくれますよ。


4月から

某社でお世話になります。
研修についていけるかどうか不安で夜も眠れず昼に眠る生活を送っています。
とりあえずデータベーススペシャリストを取りたいので卒業しても日々勉強の毎日です。

console.log("Hello, " + (new Date()).getFullYear());

ごあいさつ

あけましておめでとうございます。
なんとなんと2015年ですね。
昨年中はいろいろな方に大変お世話になりました。
セキュリティ・キャンプやctf4bなど、いろいろ挑戦の機会があってとても充実した1年間でした。

2015年も引き続きよろしくお願いいたします。

初日の出

初日の出撮りに行ったんですけど雲に邪魔されたので仕方なくこんなもの撮って帰ってきました。

f:id:yagihashoo:20150101235357j:plain

結局XSSって何なの?

タイトルのような疑問にうまーく答えてくれる資料がないよなぁって思って書いてみるかーと思い立ったはいいものの徳丸さんのいい感じのスライドがすでにあった。
まぁ、そんなこともある。

XSSとは

XSS(Cross Site Scripting)は、あるWebページにアクセスした標的のブラウザ上で、攻撃者が任意のコードを実行し得るバグ、あるいはそれを用いた攻撃手法のことで、大きく分けて反射型XSS(Reflected XSS)・持続型/蓄積型XSS(Persistent/Stored XSS)・DOM Based XSSの3種類がある。

例えばPHPで記述された以下のようなWebページはXSSが可能であるといえる。

<?php
  header("Content-Type: text/html; charset=UTF-8");
  $input = filter_input(INPUT_GET, "q");
?>
<!DOCTYPE html>

<html>
  <head>
    <title>XSSサンプル</title>
  </head>
  
  <body>
    <form>
      <input type="text" name="q" value="<?= $input ?>">
      <input type="submit" value="search">
    </form>
<?php
  if($input):
?>
    <span><strong><?= $input ?>の検索結果</strong></span>
<?php
  endif;
?>
  </body>
</html>

このスクリプトが「http://localhost/xss.sample.php」で動いていると仮定して、「http://localhost/xss.sample.php?q=<script>alert('XSS')</script>」といったURLにアクセスすることで、上記PHPスクリプトが出力するHTMLは以下のようになり、結果としてscriptタグ中のalert('XSS')が開発者・運営者の意図しない形でページ上で実行されることになる。

<!DOCTYPE html>

<html>
  <head>
    <title>XSSサンプル</title>
  </head>

  <body>
    <form>
      <input type="text" name="q" value="<script>alert('XSS')</script>">
      <input type="submit" value="search">
    </form>
    <span><strong><script>alert('XSS')</script>の検索結果</strong></span>
  </body>
</html>

最もシンプルなXSSのサンプルを示したが、これによって何ができるのか、何が問題になるのかについては後述。


XSSの種類

大きく分けて3種類あるXSS、それぞれを簡単に説明する。

反射型XSS

HTTPリクエスト中に含まれる攻撃コードがそのままWebページ上で動作するXSS
典型的には検索フォームなど、GETリクエストのパラメータ中に含まれるscriptタグがWebページ上で動作するものなどが挙げられる。(先に紹介したサンプルもこの反射型XSSに分類される)
特定のクエリに対してのみ動作するXSSなので、攻撃者は何らかの手段を用いて標的を特定のURLに誘導しなければならない。
"特定のURL"というのは、例えば先のサンプルの「http://localhost/xss.sample.php?q=<script>alert('XSS')</script>」であったり、アクセスすることで脆弱なページにPOSTリクエストを自動的に送信するページのURLであったりする。
特定のURLへの誘導が必要という観点において、反射型XSSでは持続型XSSに比して攻撃成功までのハードルが低いといえる。

持続型/蓄積型XSS

HTTPリクエスト中に攻撃コードが含まれるか否かに関わらず、あるWebページ上で持続的に動作するXSS
例として掲示板などの投稿中に含まれるscriptタグがそのまま動作する場合などを考える。
その掲示板上では攻撃者が投稿したコードが持続的に動作しているので、攻撃者は標的がそのページにアクセスするのをじっと待てばいいだけとなり、反射型XSSに比して攻撃のハードルがぐっと下がることになる。
ただしこれは"標的"がそのページに頻繁に、あるいはしばしばアクセスすることが前提となり、標的がそのページに普段アクセスしない場合などは反射型XSSと同様に何らかの手段を用いて標的がそのページにアクセスするよう誘導する必要がある。

DOM Based XSS

反射型・持続型XSSがサーバサイドコードのバグに起因するのに対し、DOM Based XSSはクライアントサイドスクリプトのバグに起因するXSS
例えばJavaScript中に以下のような処理がある場合は、DOM Based XSSが可能であるといえる。(ただしここまで典型的なものはまず存在しないと思う)

document.write(location.hash.substr(1));

上記処理が「http://localhost/xss.sample.html」上で実行されるとき、「http://localhost/xss.sample.html#<img src=x onerror=alert('XSS')>」といったURLにアクセスすることで、xss.sample.html上で外部から指定された任意のコードが実行されることになる。

DOM Based XSSは他にも様々なバリエーションが存在し得るが、ここでは省略。


XSSでできること

ここまで紹介してきたサンプルでは、Webページ上でダイアログボックスを表示するだけで、実害があることを示せていない。
実際にXSSでできるのは、JavaScript(あるいはVBScriptなど)でできる全てのことと言い換えて差し支えない(と思う)。
例えば以下のような例がある。

  • セッションIDの窃取、およびそれを用いたセッションハイジャック
  • フォームへの入力内容の窃取(ユーザの住所などが含まれるかもしれません)
  • ユーザを外部の悪質なページにリダイレクトさせる
  • あるWebページを全く別物のWebページに見せる
  • 標的のユーザに特定の操作をさせる(物品の購入とか)
  • あるユーザにしか見えていない情報を窃取する

逆説的に、JavaScriptでできないことはXSSでもできない。
いずれにせよ、XSSというのは、あるWebページ上で、本来そのページに存在しないJavaScriptコードを実行させる攻撃手法。


根本的対策

XSS対策として「メタキャラクタをエスケープする」という文言がよく用いられるが、この表現は非常に厄介で、"メタキャラクタ"と"エスケープ"という用語がそれぞれ曖昧なまま用いられることが非常に多い。
例えば、先のサンプルにおいては、ユーザ入力中に出現するHTMLにおけるメタキャラクタ「"'<>&」の5つをそれぞれ文字実体参照・数値文字参照に置き換えることでXSSを防ぐことができる。
しかしながら、例えば以下のようなページを想定すると、HTMLにおけるメタキャラクタを文字実体参照・数値文字参照に置き換えるというのがどんなときにも当てはまる対策ではないことがわかる。(以下の例では「javascript:alert('XSS')」などを入力した場合に任意のコードが実行できる) 特定のコンテキストにおいては「"'<>&」を使わずとも任意のJavaScriptコードは実行し得るからだ。

<?php
  function h($str) {
    # htmlspecialchars関数でHTMLにおけるメタキャラクタを実体参照・数値文字参照に変換できる
    return htmlspecialchars($str, ENT_QUOTES, "UTF-8");
  }
  
  header("Content-Type: text/html; charset=UTF-8");
  $input = filter_input(INPUT_GET, "q");
?>
<!DOCTYPE html>

<html>
  <head>
    <title>XSSサンプル</title>
  </head>
  
  <body>
    <form>
      <input type="text" name="q" value="<?= h($input) ?>">
      <input type="submit" value="search">
    </form>
<?php
  if($input):
?>
    <a href="<?= h($input) ?>"><?= h($input) ?></a>
<?php
  endif;
?>
  </body>
</html>

それを踏まえた根本的対策として…って書こうと思ったけど長くなっちゃうのでこれ読んで!
安全なウェブサイトの作り方(24ページ)

簡単に言うと、他の安全な文字/文字列に置き換えなければならない文字/文字列や、取り除かなければならない文字/文字列がケースバイケースで異なるため、一概に"こうすれば安全"という対策がない。
強いて言えば「メタキャラクタをエスケープする」なのだが、それでは説明になっていないのであまり意味がない。
また、Webアプリケーションの機能要件との噛み合いもある。一部のHTMLタグがユーザ入力として許可されるようなアプリケーションであればXSSへの対策も異なってくる。
基本的なアプローチとしては、HTML中の出力は全てHTMLエスケープし、それ以外のコンテキストでの出力は行わない、ということに尽きる。加えて先の例のようにURLの出力を行う場合はhttpスキーム、httpsスキームのみ許可するといった個別の条件に合わせた追加の対策が必要になる。


影響緩和策

根本的な対策を間違いなく実施することが大事だが、対策漏れがあったときの影響緩和策として、すぐ思いつくのはこの辺り。
他にもあるかも。

  • Cookieのhttponly属性
  • XSS Filter/XSS Auditor
  • CSP(Content Security Policy)

Cookieのhttponly属性

XSSのデモや解説などでもっともよく見られるのが、セッションIDを窃取し、盗み出したセッションIDを用いてセッションハイジャックをするというもの。
Cookieに設定されたPHPSESSIDなどが窃取の対称となるが、Cookieにhttponly属性を付与することでJavaScriptからそのCookieの値にアクセスすることができなくなる。
これによってXSSによるCookieの窃取を防ぐことができる。

XSS Filter/XSS Auditor

ブラウザによってはXSSを検知し、防止する機能が備わっている。
IEXSS Filter、ChromeSafariXSS Auditorがそれにあたる。
それらの機能は基本的にデフォルトで有効化されているが、X-XSS-Protectionヘッダで制御することができる。
特に問題がなければ3つ目のブロックモード指定が無難。

// XSS防止機能を無効化
X-XSS-Protection: 0

// XSS防止機能を有効化
X-XSS-Protection: 1

// XSS防止機能をブロックモードで有効化
X-XSS-Protection: 1; mode=block

これらXSS防止機能は、基本的にリクエスト中に出現するXSSの攻撃コードらしい文字列がエスケープされずにページ中に出力された場合にのみ動作するため、持続型XSSやDOM Based XSSに対しては効果がないことに留意する必要がある。

CSP(Content Security Policy)

多くのモダンブラウザではCSPを用いてXSSの影響を緩和することができる。
CSP (Content Security Policy) - Security | MDN


参考

安全なウェブサイトの作り方:IPA 独立行政法人 情報処理推進機構
体系的に学ぶ 安全なWebアプリケーションの作り方
CSP (Content Security Policy) - Security | MDN