Slide 1

Slide 1 text

ηΩϡϦςΟ IBUFOBJOUFSO !

Slide 2

Slide 2 text

͜ͷߨٛʹ͍ͭͯ • 話すこと • Webアプリケーション開発におけるセキュリティ • アプリケーションエンジニア視点から • ⽬標 • セキュリティを気にできるようになる • 「この仕様や実装⼤丈夫か?」と疑問を持てるようになる IBUFOBJOUFSO !

Slide 3

Slide 3 text

໨࣍ • 何故セキュリティが必要か • 脆弱性に繋がる実装ミスと様々な攻撃⼿法 • 脆弱性を作らないためのセキュアコーディング • 被害に遭うことに備えたインシデントレスポンス IBUFOBJOUFSO !

Slide 4

Slide 4 text

ԿނηΩϡϦςΟ͕ඞཁ͔ IBUFOBJOUFSO !

Slide 5

Slide 5 text

ϢʔβʔͱαʔϏε(ձࣾ)ΛकΔ 例えばサービスの情報が漏えいすると... • ユーザーへの不利益 • 個⼈情報やカード情報の不正利⽤ • プライバシーの侵害 • サービス / 会社への不利益 • 経済的な損失 • 信⽤の損失 不利益を⽣まないためにセキュリティが必要 IBUFOBJOUFSO !

Slide 6

Slide 6 text

੬ऑੑ = ѱ༻Ͱ͖Δόά • 脆弱性 • 他のユーザーの情報が⾒れる • なりすましが出来る • 脆弱性を作らないため、ありがちなバグや悪⽤⽅法(攻撃⼿法) を学ぶ必要がある IBUFOBJOUFSO !

Slide 7

Slide 7 text

஫ҙʂʂʂ • これから紹介する内容を悪⽤したり、実際のサービスで試さな い • 試したくなったら「やられアプリ」でやりましょう • https://owasp.org/www-project-juice-shop/ • https://github.com/ockeghem/badtodo IBUFOBJOUFSO !

Slide 8

Slide 8 text

໨࣍ • 何故セキュリティが必要か • 脆弱性に繋がる実装不備と様々な攻撃⼿法 • 脆弱性を作らないためのセキュアコーディング • 被害に遭うことに備えたインシデントレスポンス IBUFOBJOUFSO !

Slide 9

Slide 9 text

੬ऑੑʹܨ͕Δ࣮૷ෆඋ • 機能実装の例を⾒ながら、やりがちな不備を紹介 • 実装例はGoやNode.js⾵だが、特定の⾔語に依存しない内容 IBUFOBJOUFSO !

Slide 10

Slide 10 text

ྫ:ϒϩάͷԼॻ͖هࣄҰཡΛฦ͢API app.get('/users/:userId/drafts', (req, res) !" { const userId = req.params.userId; !# ύϥϝʔλͷϢʔβʔIDΛऔಘ const drafts = await findDraftsByUserId(userId); !# ϢʔβʔIDͷԼॻ͖هࣄΛऔಘ res.json(drafts); }); • 下書き記事⼀覧を返すAPIの処理 • 下書き記事は、書いたユーザー以外は⾒れない仕様 IBUFOBJOUFSO !"

Slide 11

Slide 11 text

Ϣʔβʔͷೝূෆඋͷ੬ऑੑ app.get('/users/:userId/drafts', (req, res) !" { const userId = req.params.userId; !# ύϥϝʔλͷϢʔβʔIDΛऔಘ const drafts = await findDraftsByUserId(userId); !# ϢʔβʔIDͷԼॻ͖هࣄΛऔಘ res.json(drafts); }); • リクエストがuserIdの下書きを⾒れるかのチェックしていない • userId を知っていれば誰の下書き記事でも取得可能 IBUFOBJOUFSO !!

Slide 12

Slide 12 text

Ϣʔβʔͷೝূෆඋͷ੬ऑੑ (ରࡦ) app.get('/users/:userId/drafts', (req, res) !" { const loggedInUser = !!#; !$ ϩάΠϯϢʔβʔΛऔಘ !$ ϩάΠϯࡁ & userId ͕Ұக͠ͳ͚Ε͹Τϥʔ if (!loggedInUser !% loggedInUser.id !!& req.params.userId) { return res.status(403).send({ error: 'Forbidden' }); } const drafts = db.findDraftsByUserId(req.params.userId); !!# }); • ユーザー認証やパラメータの検証を⾏う IBUFOBJOUFSO !"

Slide 13

Slide 13 text

Ϣʔβʔͷೝূෆඋͷ੬ऑੑ (ରࡦ) app.get('/users/drafts', (req, res) !" { const loggedInUser = !!#; if (!loggedInUser) res.status(403).send({ error: 'Forbidden' }); const drafts = db.findDraftsByUserId(loggedInUser.id); !!# }); • ログインユーザーの記事を返す形にAPIの仕様を変更する⼿もある IBUFOBJOUFSO !"

Slide 14

Slide 14 text

ྫ:༗ྉهࣄͷൢചػೳ • 有料記事を作成できる機能 • 実装にはStripeなどの決済代⾏を利⽤する想定 IBUFOBJOUFSO !"

Slide 15

Slide 15 text

ܾࡁγʔέϯεͷΠϝʔδ IBUFOBJOUFSO !"

Slide 16

Slide 16 text

ܾࡁγʔέϯεͷΠϝʔδ IBUFOBJOUFSO !"

Slide 17

Slide 17 text

ྫ:༗ྉهࣄͷൢചػೳ !" Ϣʔβʔ͔ΒૹΒΕͨτʔΫϯ͕༗ޮ͔໰͍߹Θͤ const paymentResult = await paymentGateway.verify(paymentToken); !" ܾࡁ੒ޭͨ͠ͷͰهࣄͷݖརΛߪೖऀʹ෇༩ if (paymentResult.success) { await db.grantAccessToUser(purchasedUser, articleId); res.status(200).json({ msg: 'Success!' }); } • ユーザーから送られてきたトークンを決済代⾏サービスに問い合せて検証を⾏う • 検証に成功 = 決済完了を確認したので、ユーザーが有料記事を読める処理を実施 IBUFOBJOUFSO !"

Slide 18

Slide 18 text

ݕূෆඋͷ੬ऑੑ !" Ϣʔβʔ͔ΒૹΒΕͨτʔΫϯ͕༗ޮ͔໰͍߹Θͤ const paymentResult = await paymentGateway.verify(paymentToken); !" ߪೖ੒ޭ͔͠ݟ͍ͯͳ͍!# if (paymentResult.success) { await db.grantAccessToUser(purchasedUser, articleId); res.status(200).json({ msg: 'Success!' }); } • 決済の存在と成功しかチェックせず、この記事に対する決済かを確認していない • 別の決済(過去の異なる⾦額の決済等)に差し替えられている可能性がある IBUFOBJOUFSO !"

Slide 19

Slide 19 text

ݕূෆඋͷ੬ऑੑ (ରࡦ) !" ܾࡁͷଘࡏͱ੒ޭʹՃ͑ͯɺֹ͕ۚਖ਼͍͔͠νΣοΫ if (paymentResult.success !# paymentResult.amount !!$ correctPrice) { await db.grantAccessToUser(req.session.user.id, articleId); !" Success !!% } • 決済成功だけでなく、例えば⾦額もチェックする IBUFOBJOUFSO !"

Slide 20

Slide 20 text

ྫ:Ϣʔβʔ৘ใऔಘAPI !" id, name, email, passwordHash, isAdmin, createdAt ΛؚΜͩΦϒδΣΫτ͕ฦΔ const user = db.findUserById(req.params.id); res.json(user); • ユーザー情報をJSONで返すエンドポイント /users/:id • DBから取得した情報をJSON化して返す IBUFOBJOUFSO !"

Slide 21

Slide 21 text

ػඍ৘ใͷ࿙͍͑ !" id, name, email, passwordHash, isAdmin, createdAt ΛؚΜͩΦϒδΣΫτ͕ฦΔ const user = db.findUserById(req.params.id); res.json(user); • 秘匿するべき情報 (passwordHash, isAdmin) まで返している IBUFOBJOUFSO !"

Slide 22

Slide 22 text

ػඍ৘ใͷ࿙͍͑ (ରࡦ) const user = db.findUserById(req.params.id); const userDto = { id: user.id, name: user.name }; res.json(userDto); • DataTransferObjectなどを作成し必要な情報のみ返す IBUFOBJOUFSO !!

Slide 23

Slide 23 text

࣮૷ෆඋʹؔ͢Δ੬ऑੑ·ͱΊ • リクエスト認証不備‧値の検証不備‧機微なデータの露出 • これらはOWASP Top DEに出てくる脆弱性 • ⾼度な攻撃はいくつもあるが、素朴な実装不備が原因なことも 多い IBUFOBJOUFSO !"

Slide 24

Slide 24 text

༷ʑͳ߈ܸख๏ • SQLインジェクション • リダイレクト • CSRF • XSS • Clickjacking • SSRF • LLM IBUFOBJOUFSO !"

Slide 25

Slide 25 text

SQLΠϯδΣΫγϣϯ IBUFOBJOUFSO !"

Slide 26

Slide 26 text

SQLΠϯδΣΫγϣϯ • DBを不正に操作されてしまう脆弱性/攻撃⼿法 • SQLのパラメータ部分に以下のようなクエリを⼊れて操作 • or 1 = 1 で全てのデータを返す • '; DROP TABLE entry でテーブルを消す IBUFOBJOUFSO !"

Slide 27

Slide 27 text

SQLΠϯδΣΫγϣϯ SELECT * FROM entry WHERE id = :id; に対して !" :id ʹ 1 or 1 = 1ΛೖΕΔͱશͯͷϨίʔυΛฦ͢ SELECT * FROM entry WHERE id = 1 or 1 = 1; !" :id ʹ 1; DROP TABLE entry;ΛೖΕΔͱςʔϒϧ͕ফ͑Δ SELECT * FROM entry WHERE id = 1; DROP TABLE entry; IBUFOBJOUFSO !"

Slide 28

Slide 28 text

WebΞϓϦέʔγϣϯͰͷ SQLΠϯδΣΫγϣϯ !" desc / asc ΛϑϩϯτΤϯυͰࢦఆ order !# r.URL.Query().Get("order") stmt !# fmt.Sprintf("SELECT * FROM entry ORDER BY created_at %s", order) rows, err !# db.Query(stmt) • クエリパラメータの値からソート順を決定する実装 IBUFOBJOUFSO !"

Slide 29

Slide 29 text

WebΞϓϦέʔγϣϯͰͷ SQLΠϯδΣΫγϣϯ !" desc / asc ΛϑϩϯτΤϯυͰࢦఆ order !# r.URL.Query().Get("order") stmt !# fmt.Sprintf("SELECT * FROM entry ORDER BY created_at %s", order) rows, err !# db.Query(stmt) • order に desc; DELETE FROM !!" を⼊⼒されてしまう • ⼊⼒値をそのままSQL⽂の構築に利⽤しているのでSQLi発⽣ IBUFOBJOUFSO !"

Slide 30

Slide 30 text

SQLΠϯδΣΫγϣϯ (ରࡦ) • プリペアドステートメントを使う • db.Query("SELECT * FROM entry WHERE id = ?", order) • ? の部分に⼊る値がエスケープされるので、意図しないSQLが実⾏され ない • 極⼒⾃⾝でSQL⽂を組み⽴てない (⽂字列結合を使わない) • 組み⽴てる場合は⾃前でのエスケープを⾏い、信頼できる値だけにする • ユーザーからの⼊⼒値をそのままSQLに⼊れない IBUFOBJOUFSO !"

Slide 31

Slide 31 text

SQLΠϯδΣΫγϣϯ (GORMͷྫ) userInput !" "jinzhu;drop table users;" !# safe, will be escaped db.Where("name = ?", userInput).First(&user) !# SQL injection db.Where(fmt.Sprintf("name = %v", userInput)).First(&user) • ORM を使っていても発⽣し得る • セキュリティ | GORM IBUFOBJOUFSO !"

Slide 32

Slide 32 text

ϦμΠϨΫτ IBUFOBJOUFSO !"

Slide 33

Slide 33 text

ϦμΠϨΫτ !" ?redirect_to=/entry/:id ͳͲ͕ೖΔ const redirectTo = req.query.redirect_to !# '/' if (authenticateUser(username, password)) { res.redirect(redirectTo); !" ϩάΠϯ੒ޭޙʹϦμΠϨΫτ͞ΕΔ } • ログイン後に元いたページに戻れるようにする仕様 • クエリパラメータに元いたページを記録し、ログイン成功後そこにリダイレクトする • /entry/:id → /login?redirect_to=/entry/:id IBUFOBJOUFSO !!

Slide 34

Slide 34 text

ΦʔϓϯϦμΠϨτ੬ऑੑ !" ?redirect_to=https:!"evil.example const redirectTo = req.query.redirect_to !# '/' if (authenticateUser(username, password)) { res.redirect(redirectTo); } • redirect_to に任意のURLを指定できる • 外部サイトにリダイレクトされたり、Location ヘッダと通じたXSSに繋がる IBUFOBJOUFSO !"

Slide 35

Slide 35 text

ΦʔϓϯϦμΠϨΫτͷԿ͕໰୊͔ • ⾃ドメインから悪意のあるサイトに遷移してしまうので、ユー ザーは危険に気づけない • https:!"my-site.example?redirect_to=https:!" evil.example なので、ドメインだけみたら問題ない • フィッシングサイトやスパムに使われる可能性がある • SEO的な懸念もある IBUFOBJOUFSO !"

Slide 36

Slide 36 text

ΦʔϓϯϦμΠϨΫτ (ରࡦ) • リダイレクト先の検証を⾏う • ⾃ドメイン以外の場合はリダイレクトしない • 任意ページのリダイレクトが必要ならクッションページを挟む • ユーザーにリダイレクトしてよいかの確認を求める IBUFOBJOUFSO !"

Slide 37

Slide 37 text

CSRF (Cross-site request forgery) IBUFOBJOUFSO !"

Slide 38

Slide 38 text

ྫ:form ཁૉ Λ࢖ͬͨهࣄ౤ߘ app.post("/entry/post", (req, res) !" { !# ηογϣϯ cookie ͔ΒϢʔβʔΛೝূ !# ͦͷϢʔβʔͷهࣄΛ࡞੒ }); IBUFOBJOUFSO !"

Slide 39

Slide 39 text

ྫ:form ཁૉ Λ࢖ͬͨهࣄ౤ߘ • form はどのURLに向けてもリクエストを送信できる • これを攻撃者のWebサイトにこれを設置し、ユーザーに送信さ せることでスパム投稿が可能だった IBUFOBJOUFSO !"

Slide 40

Slide 40 text

CSRF (Cross-site request forgery) • ユーザーの意図に反してリクエストを送信し、Webアプリケー ションの機能を実⾏させる攻撃 • 事例 • ⼤量の「はまちちゃん」を⽣み出したCSRFの脆弱性とは? - ITmedia エンタープライズ IBUFOBJOUFSO !"

Slide 41

Slide 41 text

CSRF τʔΫϯΛຒΊࠐΜͩରࡦ !"form> !" τʔΫϯͷ஋͕Ұக͠ͳ͚Ε͹Τϥʔ if (req.body.csrf !!# csrfToken) res.status(403).send({ error: 'Forbidden' }); • 推測できないトークンをformに埋め込み、サーバー側でそのト ークンの検証に成功したときのみ処理を実⾏する • 攻撃者はトークンを推測できないため、CSRF攻撃を防げる IBUFOBJOUFSO !"

Slide 42

Slide 42 text

CSRF τʔΫϯΛຒΊࠐΜͩରࡦ • 主要なWebフレームワークにはトークンを埋込機能がある • Securing Rails Applications — Ruby on Rails Guides • Next.js ではCSRFトークンの機能は無い • How to Think About Security in Next.js | Next.js • この理由を理解するため、オリジンによるブラウザのリソース 保護の仕組みについて話します IBUFOBJOUFSO !"

Slide 43

Slide 43 text

ΦϦδϯ (Origin) • URLのスキーム‧ホスト‧ポート番号によって定義される • スキーム‧ホスト‧ポート番号が⼀致すれば same-origin • どれか1つでも異なれば cross origin IBUFOBJOUFSO !"

Slide 44

Slide 44 text

Same-Origin Policy / Cross-Origin Resource Sharing • Same-Origin Policy (SOP) • 他のオリジンにあるリソースへのアクセスを制限するブラウザの仕組み • https:!"my-site.exampleで読み込まれたJSはhttps:!"other-site.exampleのリソースを参照 できない • Cross-Origin Resource Sharing (CORS) • 異なるオリジンのリソースへのアクセスを許可する仕組み • Access-Control-Allow-Originヘッダをサーバーが指定し、リクエストできるオリジンを指定する • これによりhttps:!"my-site.exampleからhttps:!"other-site.exampleのリソースにアクセス 可能 • ただし、単純リクエストの場合はCORSの仕組みは動かない IBUFOBJOUFSO !!

Slide 45

Slide 45 text

୯७ϦΫΤετ • 以下の条件のリクエスト • GET / HEAD / POST のいずれか • Accept / Accept-Language / Content-Language のヘッダーのいずれか • application/x-www-form-urlencoded / multipart/form-data / text/ plain のContent-Type ヘッダーのいずれか • によって送られるリクエストは単純リクエストなので、CORS関 係なく異なるオリジンに送信できる IBUFOBJOUFSO !"

Slide 46

Slide 46 text

Ұ୴ΦϦδϯͱCSRF·ͱΊ • Originに基づくリソース保護の仕組みによって、サーバーは⾃ 分達の意図していないブラウザのリクエストを防げる • ⼀⽅はこの仕組みが動かないので、別なチェックが必要 IBUFOBJOUFSO !"

Slide 47

Slide 47 text

αΠτ (Site) • URL のスキーム‧eTLD+0(eTLDとその直前にあるドメイン部分)の組み合せ • eTLD = Public Suffix List で定義される • hatenablog.com, github.io など • a.hatenablog.com と b.hatenablog.com は同⼀site IBUFOBJOUFSO !"

Slide 48

Slide 48 text

Cookie ͷ SameSite ଐੑ • Cookieを送信する動作を制御する仕組み • Strict: 同⼀siteで送信される • Lax: GETの場合は異なるsiteでも送信される • None: 制限が無い • Chrome/Safari/EdgeはSameSiteがデフォルトでLax IBUFOBJOUFSO !"

Slide 49

Slide 49 text

SameSite ͱ CSRF • CSRF対策としてある程度有効 • 異なるsiteではCookieが送信されない • https:!"evil.example から https:!"my-site.example へのリクエスト時に セッションCookieが送信されないので、攻撃不成⽴ • ただし、同⼀サイト内の攻撃は有効なので完全ではない • blog.example が eTLD の場合 • https:!"my-site.blog.exampleで作成されたセッションCookieは、https:!" evil.blog.example から送信出来る • 同⼀サイト内の攻撃は成⽴するので、サーバー側で送信元Originのチェックが合わせて必要 IBUFOBJOUFSO !"

Slide 50

Slide 50 text

ݱ୅ͷCSRFରࡦ·ͱΊ • Originに基づくリソース保護/SiteによるCookieの送信制限の仕組みがブラウザに存在す る • かといってサーバーサイドで何もしなくてよいわけではない • 送信元Originチェック / SameSite属性の明記 • Fetch Metadata という仕組みもあるので、合せて確認 • 参考 • 令和時代の API 実装のベースプラクティスと CSRF 対策 | blog.jxck.io • Fetch Metadata でウェブ攻撃からリソースを保護| web.dev IBUFOBJOUFSO !"

Slide 51

Slide 51 text

iframe IBUFOBJOUFSO !"

Slide 52

Slide 52 text

iframe • 他のHTMLを埋め込む仕組み • YouTubeの埋め込みなど !#iframe> IBUFOBJOUFSO !"

Slide 53

Slide 53 text

ΫϦοΫδϟοΩϯά • 攻撃者のサイトが iframe で他所のサイトを重ねて表⽰ • クリックさせたい要素に重ねてボタンを配置し、クリックを誘 う IBUFOBJOUFSO !"

Slide 54

Slide 54 text

ΫϦοΫδϟοΩϯά IBUFOBJOUFSO !"

Slide 55

Slide 55 text

iframeͳͲͷຒΊࠐΈΛ੍ݶ͢ΔϔομΛ෇͚ͯରࡦ • Content Security Policy の frame-ancestors • none や 埋め込み許可リストを設定可能 • X-Frame-Options より柔軟に埋め込み制限をできる • X-Frame-Options • DENY / SAMEORIGIN / ALLOW-FROM origin のみ IBUFOBJOUFSO !!

Slide 56

Slide 56 text

XSS IBUFOBJOUFSO !"

Slide 57

Slide 57 text

ྫ:ΫΤϦύϥϝʔλͷ஋Λදࣔ const query = req.query.q !" ''; const html = `

'${query}' ͷݕࡧ݁Ռ!#h1>`; res.send(html); IBUFOBJOUFSO !"

Slide 58

Slide 58 text

ΫΤϦύϥϝʔλͷ஋Λදࣔ const query = req.query.q !" ''; const html = `

'${query}' ͷݕࡧ݁Ռ!#h1>`; res.send(html); • クエリパラメータに alert('XSS')!"script> などを⼊れ ることでXSS発動 • https:!#my-site.example/search? q=<script>alert('XSS')!"script> • エスケープやサニタイズを⾏う IBUFOBJOUFSO !"

Slide 61

Slide 61 text

ΤεέʔϓͱαχλΠζ • エスケープ • HTMLを安全に表⽰するためのエンコードする • < → <, > → > • サニタイズ • HTMLを表⽰してもXSSが発⽕しないようにする • DOMPurify を使う IBUFOBJOUFSO !"

Slide 62

Slide 62 text

SSRF (Server-Side Request Forgery) IBUFOBJOUFSO !"

Slide 63

Slide 63 text

ೖྗͨ͠URLΛऔಘ͠AIʹཁ໿ͤ͞ΔΞϓϦέʔγϣϯ resp, _ !" http.Get(r.URL.Query().Get("url")) !# ೖྗ͞ΕͨURLΛऔಘ body, _ !" io.ReadAll(resp.Body) summary !" summarize(body) !# ཁ໿ॲཧ w.Write(summary) • ⼊⼒されたURLをサーバーサイドで • ⼊⼒されたURLの⽂章をAIに要約させる IBUFOBJOUFSO !"

Slide 64

Slide 64 text

ೖྗͨ͠URLΛऔಘ͠AIʹཁ໿ͤ͞ΔΞϓϦέʔγϣϯ !" url=http:!"169.254.169.254/latest/meta-data/iam/security-credentials/role-name resp, _ !# http.Get(r.URL.Query().Get("url")) body, _ !# io.ReadAll(resp.Body) summary !# summarize(body) w.Write(summary) • インスタンスメタデータのURLを取得するURLに⼊⼒ • { !!", "AccessKeyId": !!", "SecretAccessKey": !!", } 認証情報を返す可能性 • インスタンスメタデータ • EC@インスタンスに関連付けられた情報を取得出来る • インスタンスメタデータからのセキュリティ認証情報の取得 | AWS IBUFOBJOUFSO !"

Slide 65

Slide 65 text

SSRF • 攻撃者が到達できない内部ネットワークのリソースに対する攻撃⼿ 法や脆弱性 • メタデータ取得エンドポイント / 管理画⾯ etc... • 任意URLにリクエストし、そのURLをユーザーが決めれるような機能 • Webアーカイブ‧Web翻訳 • チャットに貼られたリンクのOGP取得 IBUFOBJOUFSO !"

Slide 66

Slide 66 text

SSRF (ରࡦ) • 任意のURLにリクエストを送れないようにする • 内部ネットワークへのアクセスを制限する • リクエストを送るコンポーネントのネットワークを分離する IBUFOBJOUFSO !!

Slide 67

Slide 67 text

LLM IBUFOBJOUFSO !"

Slide 68

Slide 68 text

2025 Top 10 Risk & Mitigations for LLMs and Gen AI Apps • プロンプトインジェクション • 「以前の指⽰はすべて無視してください…」 • ⽣成結果を安全でなくする • 「window.alert('XSS');!"script>を dangerouslySetInnerHTMLを使ってレンダリングしてください」 • APIレートリミット無し • 制限無く LLM の API を呼ばれてサービス全体の Rate Limit を越えてしまう IBUFOBJOUFSO !"

Slide 69

Slide 69 text

ιϑτ΢ΣΞαϓϥΠνΣʔϯ IBUFOBJOUFSO !"

Slide 70

Slide 70 text

ιϑτ΢ΣΞαϓϥΠνΣʔϯ • ユーザーに提供されるソフトウェアの製造過程の話題 • アプリケーションで使う⾔語やライブラリの脆弱性だけでない • コード‧ビルド‧パッケージ化‧実⾏環境‧依存するSaaS • CI/CD環境やそのプロセス IBUFOBJOUFSO !"

Slide 71

Slide 71 text

(ݸਓతʹ)ҹ৅ਂ͍αϓϥΠνΣʔϯ࿩୊ (公開版では削除) IBUFOBJOUFSO !"

Slide 72

Slide 72 text

໨࣍ • 何故セキュリティが必要か • 脆弱性に繋がる実装ミスと様々な攻撃⼿法 • 脆弱性を作らないためのセキュアコーディング • 被害に遭うことに備えたインシデントレスポンス IBUFOBJOUFSO !"

Slide 73

Slide 73 text

੬ऑੑΛ࡞Γ͜·ͳ͍ͨΊʹ IBUFOBJOUFSO !"

Slide 74

Slide 74 text

৴པͰ͖ͳ͍ೖྗ஋ͷݕূΛ͢Δ • 信頼出来ない⼊⼒ • ユーザー⼊⼒ • HTTP (ネットワーク越し) でやってくるもの全て • curl でリクエストを送ったことを思い出そう IBUFOBJOUFSO !"

Slide 75

Slide 75 text

৴པͰ͖ͳ͍ೖྗ஋ͷݕূΛ͢Δ • 信頼できる/できないの区別をつける • 事前に定義された値 • 検証済の値 • APIのスキーマで守る • ⼊⼒値のデータ型のバリデーション • あくまで型だけであることに注意 • バックエンドで検証する • フロントエンドのみのバリデーションは攻撃者に対しては意味がない IBUFOBJOUFSO !"

Slide 76

Slide 76 text

ग़ྗͷՃ޻ɾແ֐ԽΛ͢Δ • XSSで出てきたエスケープとサニタイズ • 渡すべきでない値と判定できたらエラーにするなども IBUFOBJOUFSO !"

Slide 77

Slide 77 text

ϑΣʔϧηʔϑɾσϑΥϧτෆڐՄ • フェールセーフ • 所謂「安全側に倒す」 • エラーが⽣じた場合は処理を継続させず⽌めてしまう • デフォルト不許可 • 基本は不許可を返す実装とし、認証や権限等のチェックに通 った場合許可を返す IBUFOBJOUFSO !!

Slide 78

Slide 78 text

ଟ૚๷ޚ • 防御策を1つではなく、何層にも作る • 1箇所⽳があっても他でカバーできる • 被害範囲を最⼩限にできる IBUFOBJOUFSO !"

Slide 79

Slide 79 text

ςετΛॻ͘ • 実装不備を検知するためにテストを書く • 例: 権限チェックのため他⼈のIDを渡した場合エラーになる かどうか • 将来の変更で不備に気づけるように IBUFOBJOUFSO !"

Slide 80

Slide 80 text

CIͰकΔ IBUFOBJOUFSO !"

Slide 81

Slide 81 text

CIͰकΔ • Linter ツールの導⼊ • gosec / govuluncheck / ESLint • シークレットやコードのスキャン • https://docs.github.com/ja/code-security/secret-scanning/ introduction/about-secret-scanning • https://docs.github.com/ja/code-security/code-scanning/ introduction-to-code-scanning/about-code-scanning IBUFOBJOUFSO !"

Slide 82

Slide 82 text

੬ऑੑΛ࡞Γ͜·ͳ͍ͨΊʹ • 様々なガイドラインがあるので改めて読もう • IPA 安全なウェブサイトの作り⽅ • IPA セキュア・プログラミング講座 IBUFOBJOUFSO !"

Slide 83

Slide 83 text

໨࣍ • 何故セキュリティが必要か • 脆弱性に繋がる実装ミスと様々な攻撃⼿法 • 脆弱性を作らないためのセキュアコーディング • 被害に遭うことに備えたインシデントレスポンス IBUFOBJOUFSO !"

Slide 84

Slide 84 text

ΠϯγσϯτϨεϙϯε IBUFOBJOUFSO !"

Slide 85

Slide 85 text

׬ᘳͳରࡦ͸೉͍͠ • 今⽇話したのはほんの⼀部 • 対策していても被害に遭うときは遭う • インシデントに対応する能⼒も⼤事 IBUFOBJOUFSO !"

Slide 86

Slide 86 text

ΠϯγσϯτϨεϙϯε • インシデントの発⾒ • 初動対応 • 調査と復旧 IBUFOBJOUFSO !"

Slide 87

Slide 87 text

Πϯγσϯτͷൃݟ 発⽣する被害を把握する • ユーザーや組織が受ける不利益は何か • アカウント乗っ取り / 不正利⽤ / 情報漏えい / etc... • 影響範囲 • ユーザー全員なのか、⼀部期間なのか • 現在進⾏系で発⽣しているか IBUFOBJOUFSO !"

Slide 88

Slide 88 text

Πϯγσϯτͷൃݟ ⾃分が脆弱性を⾒つけたら • まず報告‧相談 • 「問題があるかわからない」でも相談する • ⼤丈夫だったら「よかったね」で済む話 IBUFOBJOUFSO !!

Slide 89

Slide 89 text

ॳಈରԠ • まずはこれ以上の被害拡⼤を⾷い⽌める • サービスを⽌める‧問題のある機能を停⽌する • 直すのはその後でよい • サービスが使えないことよりも、ユーザーの情報が漏えいする ⽅がユーザーの不利益になる IBUFOBJOUFSO !"

Slide 90

Slide 90 text

ௐࠪͱ෮چ • 被害拡⼤を防いだら調査と復旧対応をする • 調査: 被害の影響範囲‧原因 • 復旧: サービス再開できる • 「復旧」の定義は事象や組織によって変わる • 脆弱性を修正できれば完了か、他に侵害を受けてないことが確認できて から完了か • 外部のセキュリティ機関のチェックを受けて復旧とする場合も IBUFOBJOUFSO !"

Slide 91

Slide 91 text

͸ͯͳͰ͸ (公開版では削除) IBUFOBJOUFSO !"

Slide 92

Slide 92 text

͓ΘΓ • 何故セキュリティが必要か • 脆弱性に繋がる実装ミスと様々な攻撃⼿法 • 脆弱性を作らないためのセキュアコーディング • 被害に遭うことに備えたインシデントレスポンス IBUFOBJOUFSO !"

Slide 93

Slide 93 text

ࢀߟจݙɾҾ༻ やられアプリ • https://owasp.org/www-project-juice-shop/ • https://github.com/ockeghem/badtodo SQLインジェクション • https://gorm.io/ja_JP/docs/security.html • https://www.ipa.go.jp/security/vuln/websecurity/ug=>p?@@@@@A?=eB-att/ @@@@[email protected] IBUFOBJOUFSO !"

Slide 94

Slide 94 text

ࢀߟจݙɾҾ༻ CSRF • https://guides.rubyonrails.org/security.html#csrf-countermeasures • https://nextjs.org/blog/security-nextjs-server-components-actions#csrf • https://www.itmedia.co.jp/enterprise/articles/>?>@/AB/news>>?.html • https://web.dev/articles/same-site-same-origin?hl=ja • https://developer.mozilla.org/en-US/docs/Web/Security/Attacks/CSRF • https://blog.jxck.io/entries/A>A@->@-AN/csrf.html • https://web.dev/articles/fetch-metadata?hl=ja IBUFOBJOUFSO !"

Slide 95

Slide 95 text

ࢀߟจݙɾҾ༻ クリックジャッキング • https://developer.mozilla.org/en-US/docs/Web/Security/Attacks/Clickjacking SSRF • https://blog.tokumaru.org/2345/42/introduction-to-ssrf-server-side-request-forgery.html • https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/instance-metadata-security-credentials.html LLM • https://genai.owasp.org/llm-top-45/ IBUFOBJOUFSO !"

Slide 96

Slide 96 text

ࢀߟจݙɾҾ༻ 脆弱性を作りこまないために • https://www.ipa.go.jp/security/vuln/websecurity/ug89p:;;;;;<:8e=- att/;;;;