Next.jsで作ったポートフォリオをNiktoでスキャンしてResponse Header周りの設定を見直す
3行で
- EC2インスタンス上にの簡単なポートフォリオをデプロイしたので、Niktoを使ってスキャンしてみた。
- 諸々の脆弱性が検出された。今回はHTTP Response Header関連を復習する。
- X-XSS-Protection等のSecurity Headers周りについて既に知っとるわされている方は、ブラウザバック推奨です!
前置き
10月末に今の会社を退職&転職活動開始予定でありブログ形式の簡単なポートフォリオサイトを作成中です。
ポートフォリオを何で今更作るのか
- セキュリティの勉強中であり、VM以外で自由に攻撃できるHostが欲しい(これが一番大きい)
- ないよりはあったほうが良い。履歴書をアップロードして置いたり、今まで取り組んできた開発の内容を簡単にしたためておくことで先方に自分のイメージが伝わりやすく、また定形的な質問などに余計な時間をおかけする可能性を減らせる
- 自分の考えたくだらないこと (Slackの自分用メッセージにためておくくらいの、zennの記事にするまでもないが覚えてはおきたいこと)を蓄積できる場所が欲しかった
先日、ある程度形になったのでAWS EC2上に実際にデプロイしました。
今回は当該ポートフォリオサイト:54.199.245.89
に対して、実際にNiktoを用いてスキャンしてみたいと思います。
Nikto
(Nikto is an Open Source (GPL) web server scanner which performs comprehensive tests against web servers for multiple items, including over 6700 potentially dangerous files/programs, checks for outdated versions of over 1250 servers, and version specific problems on over 270 servers. It also checks for server configuration items such as the presence of multiple index files, HTTP server options, and will attempt to identify installed web servers and software. Scan items and plugins are frequently updated and can be automatically updated.)
(Google翻訳)
Nikto は、6700 を超える潜在的に危険なファイル/プログラム、1250 を超えるサーバーの古いバージョンのチェック、および 270 を超えるサーバーのバージョン固有の問題を含む複数の項目について、Web サーバーに対して包括的なテストを実行するオープン ソース (GPL) の Web サーバー スキャナーです。 また、複数のインデックス ファイルの存在、HTTP サーバー オプションなどのサーバー構成項目をチェックし、インストールされている Web サーバーとソフトウェアの識別を試みます。 スキャン項目とプラグインは頻繁に更新され、自動的に更新されます。
インストール
Kali Linuxの場合Niktoはプリインストールされているようですが、私の環境だと2.1.6と結構古いバージョンでした。
また、GithubのWikiにもKaliに同梱されているものは想定とは違ったロケーションにinstallされているため、gitから直接cloneすることを推奨している記載があります。
なので今回はgithubから直接リポジトリをcloneします。
git clone https://github.com/sullo/nikto
cd nikto/program
実行してみる
./nikto.pl -Help
今回はスキャンしたアウトプットをhtml形式にしてじっくり眺めてみたいと思います
./nikto.pl -h 54.199.245.89 -F html -o output.html
実行中
実行結果の一部
個別のCVEについてみていくとちょっと大変 & 実は記事を書く前にあらかじめ全てのCVEについて見ており、metasploitで使えそうなものをモジュールを探してみましたが見つからず(力不足...つ、強くなりたい...)突破できそうにないので、今回はログ冒頭に出てきた以下のモノを見てみたいと思います。
+ /: Retrieved x-powered-by header: Next.js.
+ /: The anti-clickjacking X-Frame-Options header is not present. See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
+ /: Uncommon header 'x-nextjs-cache' found, with contents: HIT.
+ /: The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type. See: https://www.netsparker.com/web-vulnerability-scanner/vulnerabilities/missing-content-type-header/
検知された脆弱性
1. X-Powered-By
Response Header
May be set by hosting environments or other frameworks and contains information about them while not providing any usefulness to the application or its visitors. Unset this header to avoid exposing potential vulnerabilities.
(Google翻訳)
ホスティング環境または他のフレームワークによって設定される可能性があり、それらに関する情報を含みますが、アプリケーションまたはその訪問者には何の有用性も提供しません。このヘッダーの設定を解除して、潜在的な脆弱性を公開しないようにします。
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers
Next.jsだとデフォルトでOnになっているHeaderですね。
そういえばOFFにしてなかった...
Next.jsはバージョンについての情報は何も含まれていませんが、PHPだとバージョン情報までしっかりこのヘッダーに記載されるようです。
もしバージョンが割れてしまい、更にそのバージョンに脆弱性が含まれていた場合セキュリティホールになる可能性があります。
利用しているフレームワークや、言語等について積極的に明かす理由はないのでOFFにします。
next.config.jsonに1行足せば出力無しにできます。
module.exports = {
...
poweredByHeader: false,
}
余談: これをOFFにする意味がNext.jsであるのかどうか
実はNext.jsはこのX-Powered-By以外にもう一つ「x-nextjs-cache」(vercel環境だとx-vercel-cacghe)という特殊なHeaderを返却しており、このヘッダによってcacheを管理しています。
このヘッダを確認すれば、少なくとも「Next.jsを使っている」というX-Powered-Byと同じ情報が得られるので、X-Powered-Byをオフにする効能は実は結構薄かったりするのかなと個人的には思っています。
ただX-Powered-Byヘッダを機械的に探している攻撃者もいるかと思いますので、とりあえず今回はOFFにしておきます。
さらに余談: Next.jsのバージョンによる脆弱性(CVE Details)
結構話がそれますが、X-Powered-Byでフレームワークやバージョンが露呈するのってそんなに危険かな....?と思ったりしませんか。(めちゃ恥ずかしながら私はしてました....)
CVE Detailsを見るに、2020年、Next.jsはv9.3.2以前
のバージョンにてdirectory traversal vulnerability
が確認されているようです。
dynamic routingでurlからpages配下の色々なファイルへアクセスできるNext.jsですが、
urlに../../../
等といった文字列をURLエンコードして渡すと、上の階層が
覗ける脆弱性がかつて存在していたようです。(ただし露見する範囲は.nextフォルダの中だけに留まる。)
.nextフォルダの中(build assets等しか通常含まれない)の閲覧だけなのがまだ救いですが、
こんな感じでX-Powered-Byは攻撃の足掛かりになりそうです。
やはり不必要な情報はできるだけ渡さない方がよいですね..
2. Server
また、Response Headerをよく見るとServer: Apache/2.4.54 ()
というヘッダーが...
後でnginxに挿げ替える予定ですが、httpd.confをいじれば諸々簡単にOFFにできるので
OFFにしておきます。
...
ServerTokens Prod
ServerSignature Off
3. X-Frame-Options, X-Content-Type-Options
X-Frame-Options は HTTP のレスポンスヘッダーで、ブラウザーがページを <frame>、<iframe>、<embed>、<object> の中に表示することを許可するかどうかを示すために使用します。サイトはコンテンツが他のサイトに埋め込まれないよう保証することで、クリックジャッキング攻撃を防ぐために使用することができます。
https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/X-Frame-Options
X-Frame-Optionsは、ウェブアプリケーションをクリックジャッキング攻撃から防御するためのヘッダです。HTTPのレスポンスヘッダに「X-Frame-Options: DENY」のように出力することで、X-Frame-Optionsに対応したブラウザにおいて、frame要素やiframe要素によるページ読み込みの制限ができます。なお、Internet Explorer 7は、X-Frame-Options ヘッダに対応していないため、本対策を実施したとしても、当該ブラウザにおいてはクリックジャッキング攻撃を防げません。
https://www.ipa.go.jp/security/vuln/websecurity-HTML-1_9.html
X-Content-Type-Options は HTTP のレスポンスヘッダーで、 Content-Type ヘッダーで示された MIME タイプを変更せずに従うべきであることを示すために、サーバーによって使用されるマーカーです。これにより、MIME タイプのスニッフィングを抑止することができます。言い替えれば、 MIME タイプを意図的に設定することができます。
ここらへんはよく話題にあがるやつですね。。。先人の方々がとても分かりやすくまとめてくださっており、私が書く駄文よりずっと洗練された記事がすでに多数存在しているのでURLを貼ってお茶を濁させてください。
...
Header always append X-Frame-Options SAMEORIGIN
Header always set X-Content-Type-Options nosniff
気になった点
-
X-XSS-Protectionについても設定しておらずデフォルトの1のままでしたが、特に脆弱性として検知されませんでした。構成として完全なSSGを採用しており、ブラウザからデータベースへの書き込みは一切発生しない作りにしているから検知されなかったのか、それとも単にスキャンしていないのかはわからず....
-
CORSについても開発中なのもありとりあえず全Originを許容していますが、それについても特に何も言われませんでした。
まとめ
今回Niktoでスキャンをしてみて、Headerの設定忘れに気づくことができました。
他の脆弱性についても良く読み込み、どういう攻撃の足掛かりになるのかをまとめてまた発信しようと思います。
また機会があれば今度はNessus等も触ってみたいと思います。
一点注意ですが、
By default, Nikto scans are very “noisy,” but this behavior can be modified to perform stealthier scans.
と言われているように、デフォルトの状態でスキャンをするとログが結構大量に溢れます
Apache access-log(全部Nikto) 実際にはこれの数倍のログが出ている
もし実際にスキャンを試してみる際は、共同のサーバ等でしたら十分に周囲の同意を得てから実施するのをお勧めします。
Discussion