Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Next.js App Router セキュリティ
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
zaru
November 05, 2024
20
8.3k
Next.js App Router セキュリティ
zaru
November 05, 2024
Tweet
Share
More Decks by zaru
See All by zaru
Hotwire を 本番環境で使ってみた感想
zaru_sakuraba
7
6.7k
失敗から学ぶ個人開発
zaru_sakuraba
18
5.5k
伝わらない Issue の書き方
zaru_sakuraba
1
870
とあるプロジェクトでコードを書き始めた僕がつまづいた石たち
zaru_sakuraba
0
190
Ruby との対話 : pry を使い pry をデバッグし pry のバグを直す話
zaru_sakuraba
4
590
もう「クレデンシャルください」なんて言わせない
zaru_sakuraba
5
1.6k
個人プロジェクト現状報告会
zaru_sakuraba
0
140
僕と契約して、メソッドになってよ!
zaru_sakuraba
0
190
Featured
See All Featured
ラッコキーワード サービス紹介資料
rakko
1
2.3M
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
31
3.1k
HDC tutorial
michielstock
1
390
Reality Check: Gamification 10 Years Later
codingconduct
0
2k
SEOcharity - Dark patterns in SEO and UX: How to avoid them and build a more ethical web
sarafernandez
0
120
Collaborative Software Design: How to facilitate domain modelling decisions
baasie
0
140
Heart Work Chapter 1 - Part 1
lfama
PRO
5
35k
The Curse of the Amulet
leimatthew05
1
8.7k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
234
17k
Noah Learner - AI + Me: how we built a GSC Bulk Export data pipeline
techseoconnect
PRO
0
110
Large-scale JavaScript Application Architecture
addyosmani
515
110k
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.6k
Transcript
Next.js セキュリティ #Offers_DeepDive 2024.11.06 @zaru / nanabit
自己紹介 @zaru ムーザルちゃんねるから来ました nanabit という会社で開発支援してます
今日は Next.js App Router の セキュリティで気をつけたい話をします
Next.js App Router の簡単な紹介
Server Component Streaming with Suspense Server Actions 主に React19 の新機能を先取りして提供
Server Component Streaming with Suspense Server Actions 今日は主にこの 2 つに関連する話
Server (Component|Actions) is 何? フロントエンドとバックエンドの境界線をなくす コンポーネントから直接 SQL 実行できる フロントの状態を極力持たずに書ける バックエンドの処理を関数で呼び出せる
None
じゃあ、 雰囲気でなんとなーく理解したところで、 本題に入りましょう。 今日はちょっとしたゲームを Next.js で作ってきたので、 それで遊びます。 このゲームには脆弱性がいくつかあります。 簡単なので調査してみてね。 (*)
DoS とかしちゃだめだよ。 そういうのじゃないよ。
Next Clicker 今すぐアクセスして脆弱性を見つけよう
https://nextclicker.nanabit.dev/ 今日の解説に使う題材です
見つかりましたか? では答えです
無防備な Server Actions
Ⓝ をクリックすると、 通信が発生している
Request Header で Next-Action を送信してる curl で再現するとこんな感じの POST 通信 curl
'https://nextclicker.nanabit.dev/' \ -H 'Content-Type: text/plain;charset=UTF-8' \ -H 'Cookie: ...' \ -H 'Next-Action: 6eb8416051487420c0347306825a392adf55f29e' \ --data-raw '[1]' 手動でリクエストを試してみる
--data-raw '[9999]' の数値をいじると、 1 クリックで上がる 数値を変更可能なことが分かった curl 'https://nextclicker.nanabit.dev/' \ -H
'Content-Type: text/plain;charset=UTF-8' \ -H 'Cookie: ...' \ -H 'Next-Action: 6eb8416051487420c0347306825a392adf55f29e' \ --data-raw '[9999]' # 1 クリックで9999 上がる 任意の数値でスコアを挙げられることを発見
"use server"; export async function incrementalScore(power: number) { const user
= await currentUser(); if (!user) return; await prisma.user.update({ where: { id: user.id }, data: { score: { increment: power } }, }); revalidatePath("/"); } Bad: 引数で上げる数値を受け取り信頼してしまっている Server Component 関数の実装
Server Actions = HTTP エンドポイント 見た目は関数を呼び出しているが HTTP エンドポイント 自動でエンドポイントをたて、 内部で
fetch している つまり外部に公開されているので引数は信頼できない 引数は必ずパースし、 必要なら認証もする 外部公開 API と捉えて設計と実装をすること こう考える
露出してる Server Actions
DevTools の Search で [0-9a-z]{40} で検索する Request Header で Next-Action
で使う ID が見つかる Server Actions の探し方
curl 'https://nextclicker.nanabit.dev/' \ -H 'Content-Type: text/plain;charset=UTF-8' \ -H 'Next-Action: 8d2238ce9fde355707d6a4b613a12f5d5360427c'
\ --data-raw '[1]' 0:["$@1",["EBYDKshKtbxTnpEuKdpC4",null]] 1:{"id":1,"name":"zaru","password":"$$2b$10$k6BnP5...","score":280,"level":0} ハッシュ化されたパスワードが返ってきた・ ・ ・! 適当にリクエストしてみる
"use server"; は Server Actions にするディレクティブ 名前から 「サーバ処理をする時に付けるもの」 と勘違い 盲目的に、
DB を叩く関数すべてにつけてしまった・ ・ ・ "use server"; # 内部でしか使ってないのに、 意図せず外部公開されてしまった関数 export async function fetchRankers() { return prisma.user.findMany({ orderBy: { score: "desc" }, take: 10, }); } 意図せず Server Actions になってしまった例
"use server"; != サーバ処理 上記を理解していても 1 ファイルに複数の関数を export して いると、
気が付かずに ServerActions になってしまうものが出 てくる可能性 v15 ではID が露出しないように改善された Knip というツールで未 export 関数の検出可能 こう考える
Client Component に漏れる
DevTool を使ってユーザ名を検索・ ・ ・ めっちゃパスワードがブラウザ側に露出している 情報漏洩してないか検索
Server Component で取得したユーザ情報をそのまま Client Component に渡している // Ranking はServer Component
export async function Ranking() { const users = await fetchRankers(); return ( {users.map((user) => ( // RankingItem はClientComponent <RankingItem key={user.id} user={user} /> ))} ); } Server と Client の境界線
コンポーネント内部で使っているかどうかは関係ない Server Component は JSX に使っているものだけ露出する 面倒くさがってオブジェクト全部渡しちゃったり・ ・ ・ 構造的片付けで意図しないプロパティが含まれてしまうケ
ースも ClientComponent の props は全て露出
必要な情報だけ props に渡す コンポーネントが Server か Client かで考えると境界線意識 がつらい どんなコンポーネントでも必要な情報だけ扱うようにする
TaintAPI や Pick 型/Zod パースなどを使う それぞれ効能が少し異なるのでシーンによって使い分ける こう考える
SQL なら原則 SELECT 句は指定した方が良い export async function fetchRankers() { return
prisma.user.findMany({ // Prisma の例 select: { id: true, name: true, score: true, level: true }, }); } SELECT 句を明示的にする
React の提供する Taint API を使うと使用禁止をマークできる サーバ側でしか使わないようなオブジェクトに対して利用可能 ただし、 実行時エラーなのでエディタ上では分からない export async
function fetchRankers() { const users = await prisma.user.findMany(); for (const user of users) { // user オブジェクトをClient Component に渡すとエラーになる taintObjectReference("Client Component では使えません", user); } return users; } Taint API を使う
ライブラリでパースし、 必要ないプロパティを落とす const schema = z.object({ id: z.number(), name: z.string(),
}); // パースすると、 id / name 以外のプロパティは消える const parsed = schema.safeParse(user); Zod でパースする
認証してるのに見える
None
条件分岐で弾かれているのにコードに含まれちゃってる またも DevTool で検索する
None
Layout で認証しない v15 では Layout からレンダリングされるので回避は可能 ただし順序に依存すると Next.js の変更で露出するかも 隠したい情報を表示するコンポーネント自体で判定させる
将来的には Request Interceptors で共通処理できるかも https://github.com/vercel/next.js/pull/70961 こう考える
仕組みを理解して使うことが大事 フロントとバックの境界線を意識する この先、 境界線をまたぐ書き方は増えていく気がする 自分の領域を決めすぎず広く対応していきたい
import 'server-only'; で Client Component に含ませない next-safe-action という Server Actions
を少し安全にする https://next-safe-action.dev/ 似たようなライブラリは他にもいくつかある おまけ
おしまい もし Web アプリの開発・技術顧問、 エンジニア組織・文化の相談あれば、 @zaru までお問い合わせください