Slide 1

Slide 1 text

現場で使える Django のセキュリティ対策 2019.5.18 DjangoCongress JP 横瀬 明仁(akiyoko)

Slide 2

Slide 2 text

今回 話すこと ① Webアプリケーションのセキュリティ対策って そもそも必要なの? ② 「これだけは絶対やっとけ」的な基準はある? ③ フルスタック(全部⼊り)の Django を使えば セキュリティ対策もまるっと万事解決? 1

Slide 3

Slide 3 text

⽬次 1. Webアプリケーションにセキュリティ対策は必要? 2. セキュリティ対策の基準 3. 代表的な脆弱性と Django での対策 4. まとめ スライドに掲載した情報やコードを利⽤することで発⽣したトラブルや損失、 損害に対しては⼀切責任を負いません。 2

Slide 4

Slide 4 text

⾃⼰紹介 • 名 前 : 横瀬 明仁(akiyoko) • 所 属 : 株式会社 ワングリット • Twitter : @aki_yok • ブログ : akiyoko blog(http://akiyoko.hatenablog.jp/) • Django歴 : 6年くらい • セキュリティ資格 : IPA「情報セキュリティマネジメント試験」 • 同⼈誌 : 『現場で使える Django の教科書(基礎編)』 『現場で使える Django の教科書(実践編)』 『現場で使える Django REST Framework の教科書』 3

Slide 5

Slide 5 text

1. Webアプリケーションにセキュリティ対策は必要? 2. セキュリティ対策の基準 3. 代表的な脆弱性と Django での対策 4. まとめ 4

Slide 6

Slide 6 text

判例 「ECサイト不正アクセス損害賠償事件訴訟」(平23(ワ) 32060号) 契約書やRFPに明記されていなくても、経産省・IPAが注意喚起したセキュリ ティ措置を施さなかったのは、ベンダ企業が「専⾨家として当然果たすべき注 意義務」を怠った重過失 ⇒ 発注費 920万円に対し、損害賠償 2,262万円の⽀払いが確定 (原告もグダグダだったので過失相殺3割) 5 鬼ヤバ

Slide 7

Slide 7 text

判例 【判決の注⽬点 ①】 Webアプリケーションの脆弱性対策は当然の責務として必須 【判決の注⽬点 ②】 経産省・IPAの注意喚起がセキュリティ対策の基準として判断された 6

Slide 8

Slide 8 text

ポイント ① ① Webアプリケーションのセキュリティ対策って そもそも必要なの? ⇒絶対必要(判例もある) 7

Slide 9

Slide 9 text

1. Webアプリケーションにセキュリティ対策は必要? 2. セキュリティ対策の基準 3. 代表的な脆弱性と Django での対策 4. まとめ 8

Slide 10

Slide 10 text

IPAによる脆弱性対策の指針 • IPA(情報処理推進機構)の公表資料 「安全なウェブサイトの作り⽅」(PDF・115ページ) 「セキュリティ実装 チェックリスト」(Excel) https://www.ipa.go.jp/security/vuln/websecurity.html 実際の届け出を元に脆弱性対策・安全性向上施策・失敗例について解説 • 補助教材として 『体系的に学ぶ 安全なWebアプリケーションの作り⽅ 第2版』 (著:徳丸 浩)← IPA ⾮常勤研究員 https://www.amazon.co.jp/dp/4797393165 9

Slide 11

Slide 11 text

「安全なウェブサイトの作り⽅」要約 (1/4) セキュリティ対策の全体像 10 サーバの セキュリティ対策 DNSの セキュリティ対策 ネットワークの セキュリティ対策 Webアプリケーションの セキュリティ対策

Slide 12

Slide 12 text

「安全なウェブサイトの作り⽅」要約 (2/4) 11 Webアプリケーションの セキュリティ対策 ⼆次対策(保険的対策) 脆弱性の根本対策

Slide 13

Slide 13 text

「安全なウェブサイトの作り⽅」要約 (3/4) 脆弱性の根本対策 • 「脆弱性」とは、第三者に悪⽤されてしまう「安全上の⽋陥」 • 予測不可能な落とし⽳ではなく、よくあるものについては⼀般常識に • SQLインジェクション対策、XSS対策、CSRF対策、etc ⼆次対策(保険的対策) • 根本解決ではないが、攻撃されにくくする、被害を最⼩化するなどの⽬的で • 予算や運⽤要件などに応じて、安全性を強化するための積極施策も • パスワード漏洩対策、監視⽤ログ出⼒、etc 12 今⽇話すのは 主にコレ

Slide 14

Slide 14 text

「安全なウェブサイトの作り⽅」要約 (4/4) 13 カテゴリ 脆弱性・攻撃の例 概要 Ⅰ. パスワード系 (1) パスワード不正取得 (2) パスワード漏洩 悪意ある攻撃からパスワードを保護。 万が⼀流出した場合の対策も必要 Ⅱ. 認証・認可系 (3) セッション管理の不備 (4) アクセス制御の不備 セッションIDを不正取得されないように 対策。アクセス制御で秘密情報を保護 Ⅲ. インジェク ション攻撃系 (5) SQLインジェクション (6) HTTPヘッダ・インジェクション (7) メールヘッダ・インジェクション OSコマンド・インジェクション 意図しないスクリプトが実⾏されないよ うに制御。本来実⾏するスクリプト⽂の 区切り⽂字や制御⽂字が悪⽤される Ⅳ. クロスサイト (罠サイト)系 (8) XSS (9) CSRF (10) クリックジャッキング 罠サイトからの攻撃を考慮 Ⅴ. その他 ディレクトリ・トラバーサル バッファオーバーフロー バッファオーバーフローは主に C や C++ が対象 ͜Ε͚ͩ͸ઈରରࡦ͠ͳ͖Όଛ֐ഛঈϞϯͷܹϠό੬ऑੑ

Slide 15

Slide 15 text

ポイント ② ② 「これだけは絶対やっとけ」的な基準はある? ⇒IPA「安全なウェブサイトの作り⽅」 14

Slide 16

Slide 16 text

1. Webアプリケーションにセキュリティ対策は必要? 2. セキュリティ対策の基準 3. 代表的な脆弱性と Django での対策 4. まとめ 15

Slide 17

Slide 17 text

Ⅰ. パスワード系の脆弱性とその対策 16 カテゴリ 脆弱性・攻撃の例 Django での対策 Ⅰ. パスワード系 (1) パスワード不正取得 ? (2) パスワード漏洩 ?

Slide 18

Slide 18 text

Ⅰ- (1) パスワード不正取得 17

Slide 19

Slide 19 text

Ⅰ- (1) パスワード不正取得 【どんな脆弱性?】 • ブルートフォース(総当たり)攻撃や辞書攻撃により、ログインパスワード が奪取される admin / password admin / password0 admin / password1 ・・ 18

Slide 20

Slide 20 text

Ⅰ- (1) パスワード不正取得 【⼀般的な対策】 • ユーザ登録やパスワード変更の際に設定するパスワードの強度を上げる • アカウントロック(⼀定時間内に規定回数を超えてログインに失敗するとロ グインできなくする仕組み)を導⼊する 19

Slide 21

Slide 21 text

Ⅰ- (1) パスワード不正取得 【Django での対策】 • startprojectコマンドで⾃動作成される設定ファイル(settings.py)の 「AUTH_PASSWORD_VALIDATORS」にセットされたバリデーションが、 パスワード設定時に実⾏される(Django 1.9 以降) • createsuperuserコマンドや UserCreationForm、SetPasswordForm で django.contrib.auth.password_validation.validate_password() を介して実⾏される • アカウントロックはデフォルトで⽤意されていないため、⾃前で導⼊する • django-axes を利⽤すれば簡単に導⼊可能 https://django-axes.readthedocs.io/ 20 ཁ ௥ Ճ ର Ԡ

Slide 22

Slide 22 text

Ⅰ- (1) パスワード不正取得 【該当コード】 AUTH_PASSWORD_VALIDATORS = [ { 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', }, { 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', }, { 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', }, { 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', }, ] <設定ディレクトリ>/settings.py 21 デフォルトでは ①「username」「first_name」「last_name」 「email」と類似していないか ② 8⽂字以上であること ③ よくあるパスワードのリストと⼀致していないか ④ 数値のみで構成されていないか を検証してくれる ① ② ③ ④

Slide 23

Slide 23 text

Ⅰ- (1) パスワード不正取得 22 Django パスワード不正取得対策 ཁ ௥ Ճ ର Ԡ

Slide 24

Slide 24 text

Ⅰ- (2) パスワード漏洩 23

Slide 25

Slide 25 text

Ⅰ- (2) パスワード漏洩 【どんな脆弱性?】 • データベースに(平⽂あるいは容易に復号可能な形式で)保存されたパス ワードが漏洩した場合に、悪意ある攻撃者に不正アクセスされる • 他の Webアプリでも同じパスワードを使い回している場合、リスト攻撃に よって被害が拡⼤することも admin / pass12345 user01 / pass12345 user02 / passw0rd ・・ 24

Slide 26

Slide 26 text

Ⅰ- (2) パスワード漏洩 【⼀般的な対策】 • パスワードは平⽂ではなく、ハッシュ値に変換してデータベースに保存する • その際、同じパスワードが同じハッシュ値にならないように、ソルト(ラン ダムな⽂字列)を連結してからハッシュ変換する • さらに、容易に復号できないようにストレッチング(ハッシュ変換の繰り返 し)をおこなう 25 ฏจμϝʂ θολΠʂ

Slide 27

Slide 27 text

Ⅰ- (2) パスワード漏洩 【Django での対策】 • ⽣パスワードとソルトと連結したものを規定回数(Django 2.2 では 15,000 回)ストレッチングしたハッシュ値が保存される • django.contrib.auth.base_user.AbstractBaseUser#set_password() を 使うと、内部で django.contrib.auth.hashers.make_password() が呼ばれる pass12345 pbkdf2_sha256$150000$VU5rxZy7LYHK$ zWzEkGbxey/1A5nAW7/6yn9wxfCyv+DeGmOOoN+wq6s= <アルゴリズム>$<ストレッチ回数>$<ソルト>$<ハッシュ値> 【⽣パスワード】 【変換されたハッシュ値】 26

Slide 28

Slide 28 text

Ⅰ- (2) パスワード漏洩 【該当コード】 def make_password(password, salt=None, hasher='default'): """ Turn a plain-text password into a hash for database storage Same as encode() but generate a new random salt. If password is None then return a concatenation of UNUSABLE_PASSWORD_PREFIX and a random string, which disallows logins. Additional random string reduces chances of gaining access to staff or superuser accounts. See ticket #20079 for more info. """ if password is None: return UNUSABLE_PASSWORD_PREFIX + ¥ get_random_string(UNUSABLE_PASSWORD_SUFFIX_LENGTH) hasher = get_hasher(hasher) salt = salt or hasher.salt() return hasher.encode(password, salt) django.contrib.auth.hashers.make_password ハッシャーは設定ファイルの「PASSWORD_HASHERS」 にセットされたもの(Django 2.2 のデフォルトは django.contrib.auth.hashers.PBKDF2PasswordHasher) が使われる 27

Slide 29

Slide 29 text

Ⅰ- (2) パスワード漏洩 28 Django パスワード漏洩対策

Slide 30

Slide 30 text

Ⅱ. 認証・認可系の脆弱性とその対策 29 カテゴリ 脆弱性・攻撃の例 Django での対策 Ⅱ. 認証・認可系 (3) セッション管理の不備 ? (4) アクセス制御の不備 ?

Slide 31

Slide 31 text

Ⅱ- (3) セッション管理の不備 30

Slide 32

Slide 32 text

Ⅱ- (3) セッション管理の不備 【どんな脆弱性?】 • ログイン⽅式に Cookie 認証(セッション認証)を利⽤していて且つ次のよ うな場合は、盗⽤・なりすまし(セッション・ハイジャック)の危険がある • 推測可能なセッションID • URL 埋め込みのセッションID • ログイン前後で同じセッションIDを利⽤(セッションID 固定化攻撃) • HTTPS/HTTP 間で同じセッションID を共有 31

Slide 33

Slide 33 text

Ⅱ- (3) セッション管理の不備 【⼀般的な対策】 • セッションID を推測可能なものにしない • セッションID を URL に埋め込まない • ログイン成功時に新たなセッションを開始する • HTTPS/HTTP で別のセッションID を使う(Cookie に Secure属性を付与) 32

Slide 34

Slide 34 text

Ⅱ- (3) セッション管理の不備 【Django での対策】 • Django のセッション管理は Cookie ベース。URL 埋め込みはしていない • セッションID は推測困難なランダム⽂字列として発⾏される • ログインのビューに django.contrib.auth.views.LoginView を使った場合、 ログイン成功時に古いセッションを破棄してからセッション再開してくれる • HTTPS 環境では「SESSION_COOKIE_SECURE」 (デフォルトは False) を True に設定して、Cookie に Secure 属性を付与する(ただし、本番環境 を常時SSL にすればほぼ問題なし) 33 ཁ ௥ Ճ ର Ԡ

Slide 35

Slide 35 text

Ⅱ- (3) セッション管理の不備 34 Django セッション管理 ཁ ௥ Ճ ର Ԡ

Slide 36

Slide 36 text

Ⅱ- (4) アクセス制御の不備 35

Slide 37

Slide 37 text

Ⅱ- (4) アクセス制御の不備 【どんな脆弱性?】 • アクセス制御が⽋落していると、本⼈しか⾒れないはずの秘密情報や⾮公開 情報が第三者に閲覧されてしまう 36

Slide 38

Slide 38 text

Ⅱ- (4) アクセス制御の不備 【Django での対策】 • ログイン後は、django.contrib.auth.middleware.AuthenticationMiddleware が全てのリクエストの前処理で、セッションID とログインユーザーを紐付け てくれる(ログインユーザー権限の付与) • django.contrib.auth.mixins.LoginRequiredMixin を利⽤して、ログイン後のユーザーの みがアクセスできる権限をビュー単位に付与できる • パーミッション(Permission)とグループ(Group)を使ってモデルベース の権限を付与できる認可機能もデフォルトで提供されている 37 見たことあるはず ཁ ௥ Ճ ର Ԡ ཁ ௥ Ճ ର Ԡ

Slide 39

Slide 39 text

Ⅱ- (4) アクセス制御の不備 【Django での対策】 パーミッションとグループによる権限付与 38 管理サイト

Slide 40

Slide 40 text

Ⅱ- (4) アクセス制御の不備 39 Django アクセス制御 ཁ ௥ Ճ ର Ԡ

Slide 41

Slide 41 text

Ⅲ. インジェクション攻撃系の脆弱性 とその対策 40 カテゴリ 脆弱性・攻撃の例 Django での対策 Ⅲ. インジェクション 攻撃系 (5) SQLインジェクション ? (6) HTTPヘッダ・インジェクション ? (7) メールヘッダ・インジェクション ? OSコマンド・インジェクション ✕ 該当箇所が無いか探す

Slide 42

Slide 42 text

Ⅲ- (5) SQLインジェクション 41

Slide 43

Slide 43 text

Ⅲ- (5) SQLインジェクション 【どんな脆弱性?】 • インジェクション攻撃は、実⾏⽂に悪意あるスクリプトを注⼊(インジェク ト)することで開発者が意図しない形に改変するもの • SQL 呼び出しの不備を突いて、任意の SQL が実⾏される "SELECT * FROM auth_user WHERE username = '%s'" % username SELECT * FROM auth_user WHERE username = 'hoge' OR 'a' = 'a' username = "hoge' OR 'a' = 'a" 42

Slide 44

Slide 44 text

Ⅲ- (5) SQLインジェクション 【⼀般的な対策】 • SQL⽂を組み⽴てる際、意図しない⽂に改変されないようにする • たとえば、 • プレースホルダに値をバインドする⽅式を利⽤する • Prepared Statement(プリペアドステートメント)を利⽤する 43

Slide 45

Slide 45 text

Ⅲ- (5) SQLインジェクション 【Django での対策】 • Django のモデルやクエリセットAPI を利⽤してクエリを発⾏することで、 Django ORM が内部でセキュアな SQL を組み⽴ててくれる https://docs.djangoproject.com/ja/2.2/topics/security/#sql-injection- protection • 最後の⼿段としてモデルマネージャの raw() や django.db.connection.cursor オブジェクトの execute() を使えば ⽣の SQL を実⾏することもできるが、 書き⽅によっては SQLインジェクションのリスクがあるので注意 https://docs.djangoproject.com/ja/2.2/topics/db/sql/#passing- parameters-into-raw 44 ཁ ஫ ҙ

Slide 46

Slide 46 text

Ⅲ- (5) SQLインジェクション 45 Django SQLインジェクション対策 ཁ ஫ ҙ

Slide 47

Slide 47 text

Ⅲ- (6) HTTPヘッダ・インジェクション 46

Slide 48

Slide 48 text

Ⅲ- (6) HTTPヘッダ・インジェクション 【どんな脆弱性?】 • HTTPヘッダにおいて改⾏や空⾏に意味があることが悪⽤される • 外部からのパラメータを元に HTTPレスポンスヘッダを⽣成するプログラム では、ヘッダが任意に改変される危険性がある • レスポンスを分割して任意のレスポンスボディをリバースプロキシ等に キャッシュさせる攻撃は「キャッシュ汚染」と呼ばれる 罠サイト Location: example.com Location: evil.xyz 47 HTTPリクエスト HTTPレスポンス https://evil.xyz/

Slide 49

Slide 49 text

Ⅲ- (6) HTTPヘッダ・インジェクション 【⼀般的な対策】 • ⾃前で HTTPヘッダを出⼒せず、HTTPヘッダ出⼒⽤の APIを使う • 改⾏コードを適切に処理する 48

Slide 50

Slide 50 text

Ⅲ- (6) HTTPヘッダ・インジェクション 【Django での対策】 • Django が適切にレスポンスヘッダを組み⽴てるので、ユーザーのリクエス トを元にしたレスポンスヘッダは追加されない。 django.http.response.HttpResponse を使う場合、ヘッダに改⾏が含められ ていると例外発⽣ • 「Host」ヘッダに攻撃⽤の⽂字列が注⼊されるのを防ぐために、 「ALLOWED_HOSTS」に定義したホワイトリストでホスト名を検証 https://docs.djangoproject.com/ja/2.2/topics/security/#host-header- validation • 本番⽤の設定ファイルの「ALLOWED_HOSTS」は適切に設定(” * " にしない!) 49 ཁ ஫ ҙ

Slide 51

Slide 51 text

Ⅲ- (6) HTTPヘッダ・インジェクション 【該当コード】 def _convert_to_charset(self, value, charset, mime_encode=False): ... if ((isinstance(value, bytes) and (b‘¥n’ in value or b‘¥r’ in value)) or isinstance(value, str) and (‘¥n’ in value or ‘¥r’ in value)): raise BadHeaderError(“Header values can‘t contain newlines (got %r)” % value) django.http.response.HttpResponseBase#_convert_to_charset >>> from django.http.response import HttpResponse >>> res = HttpResponse() >>> res['Location¥nLocation: evil.net'] = 'example.com’ django.http.response.BadHeaderError: Header values can't contain newlines (got 'Location¥nLocation: evil.net') 実⾏結果 50

Slide 52

Slide 52 text

Ⅲ- (6) HTTPヘッダ・インジェクション 51 Django HTTPヘッダ・インジェクション対策 ཁ ஫ ҙ

Slide 53

Slide 53 text

Ⅲ- (7) メールヘッダ・インジェクション 52

Slide 54

Slide 54 text

Ⅲ- (7) メールヘッダ・インジェクション 【どんな脆弱性?】 • 送信メールのヘッダを改変され、迷惑メール送信などに悪⽤される 【⼀般的な対策】 • ⾃前でメールヘッダを出⼒せず、ヘッダ出⼒⽤のAPIを使う 【Django での対策】 • django.core.mail.send_mail() や django.core.mail.message.EmailMultiAlternativesなどのメール送信⽤APIを 利⽤することで、意図しないヘッダの改変は防御可能 53

Slide 55

Slide 55 text

Ⅲ- (7) メールヘッダ・インジェクション 54 Django メールヘッダ・インジェクション対策

Slide 56

Slide 56 text

Ⅳ. クロスサイト(罠サイト)系 の脆弱性とその対策 55 カテゴリ 脆弱性・攻撃の例 Django での対策 Ⅳ. クロスサイト (罠サイト)系 (8) XSS ? (9) CSRF ? (10) クリックジャッキング ?

Slide 57

Slide 57 text

Ⅳ- (8) XSS 56

Slide 58

Slide 58 text

Ⅳ- (8) XSS 【どんな脆弱性?】 • XSS(クロスサイト・スクリプティング)とは、画⾯への出⼒処理にスクリ プトを埋め込める脆弱性がある場合、利⽤者のブラウザ上で不正なスクリプ トが実⾏される危険性がある • Cookie に保存されたセッションIDを抜き取られる可能性もあり、⼤変危険 スクリプト 実⾏! 罠サイト 57 HTTPリクエスト https://evil.xyz/ HTTPリクエスト func()

Slide 59

Slide 59 text

Ⅳ- (8) XSS 【⼀般的な対策】 • 意図しない HTML や JavaScript が注⼊・実⾏されないように、画⾯に出⼒ する項⽬は特定⽂字のエスケープ(無害化)処理を施す • 万が⼀ XSS の被害にあっても、Cookie に保存されている重要情報が JavaScript によって抜き出されないように、レスポンスの Set-Cookie ヘッ ダに HttpOnly 属性を付与する 58

Slide 60

Slide 60 text

Ⅳ- (8) XSS 【Django での対策】 • Django Template Language(Django 標準のテンプレート構⽂)を利⽤して いる場合は、{{ 〜 }} を使って変数を表⽰する際に危険とみなされる特定⽂ 字を⾃動的にエスケープしてくれる • ただし、万能ではない https://docs.djangoproject.com/ja/2.2/topics/security/#cross-site- scripting-xss-protection 59 ... class1 onmouseover=javascript:func() ཁ ஫ ҙ

Slide 61

Slide 61 text

Ⅳ- (8) XSS 【Django での対策(続き)】 • ⾃動エスケープを無効にするための「safeフィルタ」や「autoescapeタグ」 は、第三者が登録・更新する可能性がある項⽬では利⽤しないように注意 https://docs.djangoproject.com/ja/2.2/topics/security/#cross-site- scripting-xss-protection • XSS の被害にあった場合に Cookie に保存されている重要情報が JavaScript によって抜き出されないように、「CSRF_COOKIE_HTTPONLY」(デフォ ルトは False)および「SESSION_COOKIE_HTTPONLY」 (デフォルトは True)を True に設定して、HttpOnly 属性を付与 60 ཁ ஫ ҙ ཁ ௥ Ճ ର Ԡ

Slide 62

Slide 62 text

Ⅳ- (8) XSS 61 Django XSS 対策 ཁ ௥ Ճ ର Ԡ ཁ ஫ ҙ

Slide 63

Slide 63 text

Ⅳ- (9) CSRF 62

Slide 64

Slide 64 text

63 Ⅳ- (9) CSRF ハイ出ました! CSRF ヨチヨチ歩きの頃、こんな画⾯に悩まされたことはありませんでしたか?? POSTリクエストで 謎の 403エラーが。 ビューまで届かん。。 よく分からんけど に {% csrf_token %} 入れたら直った!ワーイ

Slide 65

Slide 65 text

Ⅳ- (9) CSRF 【どんな脆弱性?】 • CSRF(クロスサイト・リクエスト・フォージェリ)とは、「(Webブラウ ザに保存されている Cookie などの値が⾃動的にリクエストヘッダにセット されて送信されるという性質を攻撃者が利⽤して)副作⽤を伴う重要なリク エストを利⽤者の意図に反して強要する」攻撃を指す • Cookie 認証を利⽤している場合、Cookie に保存されているセッションID が Webブラウザによって勝⼿に送信されてしまうことが悪⽤される • 読み⽅は「しーさーふ」とも 64 CSRF 攻撃の仕組みを図解

Slide 66

Slide 66 text

Ⅳ- (9) CSRF 正規のサイト https://example.com/ セッション ② ログアウトするまで (または⼀定時間が経過す るまで) セッションデータ がサーバ側で保存される ① 正規のサイトにログイン ③ Webブラウザの Cookie に セッションIDが保存される https://example.com/ ④ 正規のリクエスト リクエスト⾏ メッセージヘッダ POST /shop/buy/ Host: example.com Cookie: sessionid=xxxxxxx メッセージボディ item_no=123 購 ⼊ Cookie sessionid=xxxxxx (Domain=example.com) 65 図解:CSRF とは

Slide 67

Slide 67 text

Ⅳ- (9) CSRF ⑤ ログインセッションが 残った状態で、 悪意のある罠サイトに アクセスしてしまい・・ https://evil.xyz/ とにかく クリックしてね ⑥ 罠によって、正規のサイトに 不正なリクエストを送信して しまう https://example.com/ 購 ⼊ Cookie sessionid=xxxxxx (Domain=example.com) 正規のサイト https://example.com/ セッション 不正なリクエスト リクエスト⾏ メッセージヘッダ POST /shop/buy/ Host: example.com Cookie: sessionid=xxxxxxx メッセージボディ tem_no=123 ⑦ ログインユーザーの 正規のリクエストと区別 できないので、そのまま 処理してしまうことも クリック 罠サイト 66 図解:CSRF とは

Slide 68

Slide 68 text

Ⅳ- (9) CSRF 【⼀般的な対策】 • POST などの副作⽤のあるリクエストをおこなうフォームが正規のサイトに よって⽣成されたものかどうかを検証する • たとえば、乱数値を Cookie とリクエストパラメータの両⽅に持たせ、両者 が⼀致していれば正規のリクエストとみなす(「トークン埋め込み」⽅式) • Ajax でも CSRF 対策は必要 67

Slide 69

Slide 69 text

Ⅳ- (9) CSRF 【Django での対策】 • CsrfViewMiddleware を有効にして(デフォルトで有効)、テンプレートの POST⽤の form 要素に {% csrf_token %} を含めておくだけで、あとは⾃動 で CSRF検証をおこなってくれる • CsrfViewMiddleware によって「CSRFトークン」(Cookie に保存される「csrftoken」 と hidden項⽬として利⽤される「csrfmiddlewaretoken」の2種類の乱数値)の⽣成お よび検証がおこなわれる • テンプレートレンダリング時に、テンプレートに {% csrf_token %} が含まれていれば CSRFトークンを⽣成する • CsrfViewMiddleware の前処理時に、POST リクエストの場合のみ CSRF検証をおこな い、検証NG の場合は 403エラーを返す • csrf_exemptデコレータで CSRF検証を回避できるが、理由なく使⽤しない 68 ཁ ஫ ҙ

Slide 70

Slide 70 text

Ⅳ- (9) CSRF Django サイト CsrfViewMiddleware リクエスト⾏ メッセージヘッダ メッセージボディ GET /accounts/login/ ステータス⾏ メッセージヘッダ メッセージボディ 200 OK Set-Cookie: csrftoken=111111 ... ① GET リクエスト ユーザー名 パスワード ログイン ビュー ログイン画⾯ レスポンス ② POST リクエスト(次ページへ) ( csrftoken = 111111) ①ʼʼ csrfmiddlewaretoken ⽣成 ①ʼ csrftoken ⽣成 ( csrfmiddlewaretoken = xxxxxx) Cookie csrftoken=111111 (Domain=example.com) 69 Djangoでの CSRF 対策

Slide 71

Slide 71 text

Django サイト CsrfViewMiddleware ビュー Ⅳ- (9) CSRF リクエスト⾏ メッセージヘッダ メッセージボディ POST /accounts/login/ Cookie: csrftoken=111111 username=admin&password=pass &csrfmiddlewaretoken=xxxxxx ステータス⾏ メッセージヘッダ メッセージボディ 302 OK Set-Cookie: csrftoken=222222 ... リクエスト⾏ メッセージヘッダ メッセージボディ GET /dashboard/ Cookie: csrftoken=222222 ・・・ ログイン後の画⾯ ②ʼ CSRF 検証 ( csrftoken = 222222) ②ʼʼ csrftoken 更新 ログイン画⾯ ユーザー名 パスワード ログイン Cookie csrftoken=111111 (Domain=example.com) Cookie csrftoken=222222 (Domain=example.com) ② POST リクエスト ③ GET リクエスト 70 Djangoでの CSRF 対策 レスポンス

Slide 72

Slide 72 text

Ⅳ- (9) CSRF 71 Django CSRF 対策 ཁ ஫ ҙ

Slide 73

Slide 73 text

Ⅳ- (10) クリックジャッキング 72

Slide 74

Slide 74 text

Ⅳ- (10) クリックジャッキング 【どんな脆弱性?】 • iframe を使って攻撃対象サイトの上に罠サイトを巧妙に重ね合わせ、攻撃対 象サイトを透明にしておくことで、利⽤者の気づかないうちにクリックを誘 導する いいね! ? 購 ⼊ 罠サイト https://evil.xyz/ 73

Slide 75

Slide 75 text

Ⅳ- (10) クリックジャッキング 【⼀般的な対策】 • frame および iframe での参照を制限する「X-Frame-Options」ヘッダをレ スポンスに付与 【Django での対策】 • 「XFrameOptionsMiddleware」を有効にして(デフォルトで有効)、 「X-Frame-Options」ヘッダを全てのレスポンスに設定することで iframe 内のページの埋め込みを制御 • デフォルト値は「SAMEORIGIN」(同⼀オリジンのみ許可) • ちなみに、Django 3.0 以降はデフォルト値が「DENY」(すべて拒否)に変更 74

Slide 76

Slide 76 text

Ⅳ- (10) クリックジャッキング 75 Django クリックジャッキング対策

Slide 77

Slide 77 text

代表的な脆弱性とその対策まとめ カテゴリ 脆弱性・攻撃の例 Django での対策 Ⅰ. パスワード系 (1) パスワード不正取得 ○ (2) パスワード漏洩 ○ Ⅱ. 認証・認可系 (3) セッション管理の不備 ○ (4) アクセス制御の不備 ○ Ⅲ. インジェクション 攻撃系 (4) SQLインジェクション ○ (5) HTTPヘッダ・インジェクション ○ (6) メールヘッダ・インジェクション ○ OSコマンド・インジェクション ✕ 該当箇所が無いか探す Ⅳ. クロスサイト (罠サイト)系 (8) XSS ○ (9) CSRF ○ (10) クリックジャッキング ○ Ⅴ. その他 ディレクトリ・トラバーサル ✕ 該当箇所が無いか探す バッファオーバーフロー ✕ 該当箇所が無いか探す ཁ ௥ Ճ ର Ԡ ཁ ஫ ҙ ཁ ஫ ҙ ཁ ஫ ҙ ཁ ௥ Ճ ର Ԡ 76 ཁ ௥ Ճ ର Ԡ ཁ ௥ Ճ ର Ԡ ཁ ஫ ҙ

Slide 78

Slide 78 text

ポイント ③ ③ フルスタック(全部⼊り)の Django を使えば セキュリティ対策もまるっと万事解決? ⇒ほぼ解決。ただし、例外や追加対応が必要なものも 77

Slide 79

Slide 79 text

1. Webアプリケーションにセキュリティ対策は必要? 2. セキュリティ対策の基準 3. 代表的な脆弱性と Django での対策 4. まとめ 78

Slide 80

Slide 80 text

まとめ • 経産省・IPA が注意喚起した Webアプリケーションの脆弱性対策は必須 • IPA の「安全なウェブサイトの作り⽅」は最低限必ず網羅 • 補助教材として「徳丸本」を活⽤ • Django 公式ドキュメント「Django におけるセキュリティ」も必読 https://docs.djangoproject.com/ja/2.2/topics/security/ • 脆弱性診断や WAF、各種ツールの利⽤も検討 • 正しく Django を使えば、主な脆弱性は⾃動的に対策してくれるので便利 • 安⼼して現場で Django を使っていきましょう✌ 79

Slide 81

Slide 81 text

今回 話したこと ① Webアプリケーションのセキュリティ対策って そもそも必要なの? ⇒絶対必要(判例もある) ② 「これだけは絶対やっとけ」的な基準はある? ⇒IPA「安全なウェブサイトの作り⽅」 ③ フルスタック(全部⼊り)の Django を使えば セキュリティ対策もまるっと万事解決? ⇒ほぼ解決。ただし、例外や追加対応が必要なものも 80

Slide 82

Slide 82 text

宣伝 (電⼦版・紙の本) 『現場で使えるDjango の教科書 《基礎編》』 『現場で使えるDjango の教科書 《実践編》』 (電⼦版) (紙の本) 『現場で使える Django REST Framework の教科書』 (紙の本) (紙の本) ★ セキュリティの章あり ★ セキュリティの章あり 81 【 Amazon 】 【 BOOTH 】 (電⼦版)

Slide 83

Slide 83 text

参考資料 (1) • ECサイト不正アクセス損害賠償事件訴訟(平23(ワ) 32060号) • SQLインジェクション対策もれの責任を開発会社に問う判決 | 徳丸浩の⽇記 https://blog.tokumaru.org/2015/01/sql.html • システムベンダのセキュリティ対策義務 | 弁護⼠ 武⽥勝弘 https://www.softic.or.jp/semi/2014/5_141113/rep2.pdf • Django 公式ドキュメント • Django におけるセキュリティ https://docs.djangoproject.com/ja/2.2/topics/security/ • django-announce メーリングリスト 新バージョンのリリース情報やセキュリティアップデート速報など https://docs.djangoproject.com/en/2.2/internals/mailing-lists/#django- announce 82

Slide 84

Slide 84 text

参考資料 (2) • IPA 情報セキュリティ • 「安全なウェブサイトの作り⽅」「セキュリティ実装 チェックリスト」 https://www.ipa.go.jp/security/vuln/websecurity.html • 各ツールの紹介 https://www.ipa.go.jp/security/tools/index.html • その他 • Djangoのセキュリティとその実装 https://www.slideshare.net/aki33524/django-58472909 • Djangoはパスワードをどうやって保存しているのか | CreditEngine Tech https://medium.com/creditengine-tech/64a4b38904ff • アカウントロック機能を追加するライブラリdjango-axesの紹介 | CreditEngine Tech https://medium.com/creditengine-tech/e5414cc674e0 83