Pro Yearly is on sale from $80 to $50! »

現場で使える Django のセキュリティ対策 / Django security measures for business (DjangoCon JP 2019)

現場で使える Django のセキュリティ対策 / Django security measures for business (DjangoCon JP 2019)

○ 発表タイトル

現場で使える Django のセキュリティ対策

○ 発表内容

待望のバージョン2系の LTS がリリースされ、ますます現場で Django が盛り上がることが予想されますが、導入検討の際にネックになるものの一つに「セキュリティ」への懸念があります。

Django にはデフォルトでセキュリティ対策も含まれていますが、そのあたりの理解が中途半端だと、リリースした Webアプリが攻撃者の格好の餌食になってしまいかねません。そうならないためにも、Django のセキュリティ事情については開発前から(もちろん開発中でも)きちんと把握しておきたいところです。

そこでまず、Django におけるセキュリティ対策の基礎について概観します。そして CSRF などの重要な(そして重要な割にあまりよく理解されていない)ものについては、「CSRF(しーさーふ)って何?」というレベルの人にも分かるように基本から解説します。

C3a47a823a1e7adcb5be27cc3df5c482?s=128

akiyoko

May 18, 2019
Tweet

Transcript

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

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

    を使えば セキュリティ対策もまるっと万事解決? 1
  3. ⽬次 1. Webアプリケーションにセキュリティ対策は必要? 2. セキュリティ対策の基準 3. 代表的な脆弱性と Django での対策 4.

    まとめ スライドに掲載した情報やコードを利⽤することで発⽣したトラブルや損失、 損害に対しては⼀切責任を負いません。 2
  4. ⾃⼰紹介 • 名 前 : 横瀬 明仁(akiyoko) • 所 属

    : 株式会社 ワングリット • Twitter : @aki_yok • ブログ : akiyoko blog(http://akiyoko.hatenablog.jp/) • Django歴 : 6年くらい • セキュリティ資格 : IPA「情報セキュリティマネジメント試験」 • 同⼈誌 : 『現場で使える Django の教科書(基礎編)』 『現場で使える Django の教科書(実践編)』 『現場で使える Django REST Framework の教科書』 3
  5. 1. Webアプリケーションにセキュリティ対策は必要? 2. セキュリティ対策の基準 3. 代表的な脆弱性と Django での対策 4. まとめ

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

    (原告もグダグダだったので過失相殺3割) 5 鬼ヤバ
  7. 判例 【判決の注⽬点 ①】 Webアプリケーションの脆弱性対策は当然の責務として必須 【判決の注⽬点 ②】 経産省・IPAの注意喚起がセキュリティ対策の基準として判断された 6

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

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

    8
  10. 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
  11. 「安全なウェブサイトの作り⽅」要約 (1/4) セキュリティ対策の全体像 10 サーバの セキュリティ対策 DNSの セキュリティ対策 ネットワークの セキュリティ対策

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

  13. 「安全なウェブサイトの作り⽅」要約 (3/4) 脆弱性の根本対策 • 「脆弱性」とは、第三者に悪⽤されてしまう「安全上の⽋陥」 • 予測不可能な落とし⽳ではなく、よくあるものについては⼀般常識に • SQLインジェクション対策、XSS対策、CSRF対策、etc ⼆次対策(保険的対策)

    • 根本解決ではないが、攻撃されにくくする、被害を最⼩化するなどの⽬的で • 予算や運⽤要件などに応じて、安全性を強化するための積極施策も • パスワード漏洩対策、監視⽤ログ出⼒、etc 12 今⽇話すのは 主にコレ
  14. 「安全なウェブサイトの作り⽅」要約 (4/4) 13 カテゴリ 脆弱性・攻撃の例 概要 Ⅰ. パスワード系 (1) パスワード不正取得

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

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

    15
  17. Ⅰ. パスワード系の脆弱性とその対策 16 カテゴリ 脆弱性・攻撃の例 Django での対策 Ⅰ. パスワード系 (1)

    パスワード不正取得 ? (2) パスワード漏洩 ?
  18. Ⅰ- (1) パスワード不正取得 17

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

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

  21. Ⅰ- (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 ཁ ௥ Ճ ର Ԡ
  22. Ⅰ- (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⽂字以上であること ③ よくあるパスワードのリストと⼀致していないか ④ 数値のみで構成されていないか を検証してくれる ① ② ③ ④
  23. Ⅰ- (1) パスワード不正取得 22 Django パスワード不正取得対策 ཁ ௥ Ճ ର

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

  25. Ⅰ- (2) パスワード漏洩 【どんな脆弱性?】 • データベースに(平⽂あるいは容易に復号可能な形式で)保存されたパス ワードが漏洩した場合に、悪意ある攻撃者に不正アクセスされる • 他の Webアプリでも同じパスワードを使い回している場合、リスト攻撃に

    よって被害が拡⼤することも admin / pass12345 user01 / pass12345 user02 / passw0rd ・・ 24
  26. Ⅰ- (2) パスワード漏洩 【⼀般的な対策】 • パスワードは平⽂ではなく、ハッシュ値に変換してデータベースに保存する • その際、同じパスワードが同じハッシュ値にならないように、ソルト(ラン ダムな⽂字列)を連結してからハッシュ変換する •

    さらに、容易に復号できないようにストレッチング(ハッシュ変換の繰り返 し)をおこなう 25 ฏจμϝʂ θολΠʂ
  27. Ⅰ- (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
  28. Ⅰ- (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
  29. Ⅰ- (2) パスワード漏洩 28 Django パスワード漏洩対策

  30. Ⅱ. 認証・認可系の脆弱性とその対策 29 カテゴリ 脆弱性・攻撃の例 Django での対策 Ⅱ. 認証・認可系 (3)

    セッション管理の不備 ? (4) アクセス制御の不備 ?
  31. Ⅱ- (3) セッション管理の不備 30

  32. Ⅱ- (3) セッション管理の不備 【どんな脆弱性?】 • ログイン⽅式に Cookie 認証(セッション認証)を利⽤していて且つ次のよ うな場合は、盗⽤・なりすまし(セッション・ハイジャック)の危険がある •

    推測可能なセッションID • URL 埋め込みのセッションID • ログイン前後で同じセッションIDを利⽤(セッションID 固定化攻撃) • HTTPS/HTTP 間で同じセッションID を共有 31
  33. Ⅱ- (3) セッション管理の不備 【⼀般的な対策】 • セッションID を推測可能なものにしない • セッションID を

    URL に埋め込まない • ログイン成功時に新たなセッションを開始する • HTTPS/HTTP で別のセッションID を使う(Cookie に Secure属性を付与) 32
  34. Ⅱ- (3) セッション管理の不備 【Django での対策】 • Django のセッション管理は Cookie ベース。URL

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

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

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

  38. Ⅱ- (4) アクセス制御の不備 【Django での対策】 • ログイン後は、django.contrib.auth.middleware.AuthenticationMiddleware が全てのリクエストの前処理で、セッションID とログインユーザーを紐付け てくれる(ログインユーザー権限の付与)

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

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

    Ԡ
  41. Ⅲ. インジェクション攻撃系の脆弱性 とその対策 40 カテゴリ 脆弱性・攻撃の例 Django での対策 Ⅲ. インジェクション

    攻撃系 (5) SQLインジェクション ? (6) HTTPヘッダ・インジェクション ? (7) メールヘッダ・インジェクション ? OSコマンド・インジェクション ✕ 該当箇所が無いか探す
  42. Ⅲ- (5) SQLインジェクション 41

  43. Ⅲ- (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
  44. Ⅲ- (5) SQLインジェクション 【⼀般的な対策】 • SQL⽂を組み⽴てる際、意図しない⽂に改変されないようにする • たとえば、 • プレースホルダに値をバインドする⽅式を利⽤する

    • Prepared Statement(プリペアドステートメント)を利⽤する 43
  45. Ⅲ- (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 ཁ ஫ ҙ
  46. Ⅲ- (5) SQLインジェクション 45 Django SQLインジェクション対策 ཁ ஫ ҙ

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

  48. Ⅲ- (6) HTTPヘッダ・インジェクション 【どんな脆弱性?】 • HTTPヘッダにおいて改⾏や空⾏に意味があることが悪⽤される • 外部からのパラメータを元に HTTPレスポンスヘッダを⽣成するプログラム では、ヘッダが任意に改変される危険性がある

    • レスポンスを分割して任意のレスポンスボディをリバースプロキシ等に キャッシュさせる攻撃は「キャッシュ汚染」と呼ばれる 罠サイト Location: example.com Location: evil.xyz 47 HTTPリクエスト HTTPレスポンス https://evil.xyz/
  49. Ⅲ- (6) HTTPヘッダ・インジェクション 【⼀般的な対策】 • ⾃前で HTTPヘッダを出⼒せず、HTTPヘッダ出⼒⽤の APIを使う • 改⾏コードを適切に処理する

    48
  50. Ⅲ- (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 ཁ ஫ ҙ
  51. Ⅲ- (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
  52. Ⅲ- (6) HTTPヘッダ・インジェクション 51 Django HTTPヘッダ・インジェクション対策 ཁ ஫ ҙ

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

  54. Ⅲ- (7) メールヘッダ・インジェクション 【どんな脆弱性?】 • 送信メールのヘッダを改変され、迷惑メール送信などに悪⽤される 【⼀般的な対策】 • ⾃前でメールヘッダを出⼒せず、ヘッダ出⼒⽤のAPIを使う 【Django

    での対策】 • django.core.mail.send_mail() や django.core.mail.message.EmailMultiAlternativesなどのメール送信⽤APIを 利⽤することで、意図しないヘッダの改変は防御可能 53
  55. Ⅲ- (7) メールヘッダ・インジェクション 54 Django メールヘッダ・インジェクション対策

  56. Ⅳ. クロスサイト(罠サイト)系 の脆弱性とその対策 55 カテゴリ 脆弱性・攻撃の例 Django での対策 Ⅳ. クロスサイト

    (罠サイト)系 (8) XSS ? (9) CSRF ? (10) クリックジャッキング ?
  57. Ⅳ- (8) XSS 56

  58. Ⅳ- (8) XSS 【どんな脆弱性?】 • XSS(クロスサイト・スクリプティング)とは、画⾯への出⼒処理にスクリ プトを埋め込める脆弱性がある場合、利⽤者のブラウザ上で不正なスクリプ トが実⾏される危険性がある • Cookie

    に保存されたセッションIDを抜き取られる可能性もあり、⼤変危険 スクリプト 実⾏! 罠サイト 57 HTTPリクエスト https://evil.xyz/ HTTPリクエスト <script>func()</script>
  59. Ⅳ- (8) XSS 【⼀般的な対策】 • 意図しない HTML や JavaScript が注⼊・実⾏されないように、画⾯に出⼒

    する項⽬は特定⽂字のエスケープ(無害化)処理を施す • 万が⼀ XSS の被害にあっても、Cookie に保存されている重要情報が JavaScript によって抜き出されないように、レスポンスの Set-Cookie ヘッ ダに HttpOnly 属性を付与する 58
  60. Ⅳ- (8) XSS 【Django での対策】 • Django Template Language(Django 標準のテンプレート構⽂)を利⽤して

    いる場合は、{{ 〜 }} を使って変数を表⽰する際に危険とみなされる特定⽂ 字を⾃動的にエスケープしてくれる • ただし、万能ではない https://docs.djangoproject.com/ja/2.2/topics/security/#cross-site- scripting-xss-protection 59 <style class={{ var }}>...</style> class1 onmouseover=javascript:func() ཁ ஫ ҙ
  61. Ⅳ- (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 ཁ ஫ ҙ ཁ ௥ Ճ ର Ԡ
  62. Ⅳ- (8) XSS 61 Django XSS 対策 ཁ ௥ Ճ

    ର Ԡ ཁ ஫ ҙ
  63. Ⅳ- (9) CSRF 62

  64. 63 Ⅳ- (9) CSRF ハイ出ました! CSRF ヨチヨチ歩きの頃、こんな画⾯に悩まされたことはありませんでしたか?? POSTリクエストで 謎の 403エラーが。

    ビューまで届かん。。 よく分からんけど <form> に {% csrf_token %} 入れたら直った!ワーイ
  65. Ⅳ- (9) CSRF 【どんな脆弱性?】 • CSRF(クロスサイト・リクエスト・フォージェリ)とは、「(Webブラウ ザに保存されている Cookie などの値が⾃動的にリクエストヘッダにセット されて送信されるという性質を攻撃者が利⽤して)副作⽤を伴う重要なリク

    エストを利⽤者の意図に反して強要する」攻撃を指す • Cookie 認証を利⽤している場合、Cookie に保存されているセッションID が Webブラウザによって勝⼿に送信されてしまうことが悪⽤される • 読み⽅は「しーさーふ」とも 64 CSRF 攻撃の仕組みを図解
  66. Ⅳ- (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 とは
  67. Ⅳ- (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 とは
  68. Ⅳ- (9) CSRF 【⼀般的な対策】 • POST などの副作⽤のあるリクエストをおこなうフォームが正規のサイトに よって⽣成されたものかどうかを検証する • たとえば、乱数値を

    Cookie とリクエストパラメータの両⽅に持たせ、両者 が⼀致していれば正規のリクエストとみなす(「トークン埋め込み」⽅式) • Ajax でも CSRF 対策は必要 67
  69. Ⅳ- (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 ཁ ஫ ҙ
  70. Ⅳ- (9) CSRF Django サイト CsrfViewMiddleware リクエスト⾏ メッセージヘッダ メッセージボディ GET

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

    POST /accounts/login/ Cookie: csrftoken=111111 username=admin&password=pass &csrfmiddlewaretoken=xxxxxx ステータス⾏ メッセージヘッダ メッセージボディ 302 OK Set-Cookie: csrftoken=222222 <body>...</body> リクエスト⾏ メッセージヘッダ メッセージボディ 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 対策 レスポンス
  72. Ⅳ- (9) CSRF 71 Django CSRF 対策 ཁ ஫ ҙ

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

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

    ? 購 ⼊ 罠サイト https://evil.xyz/ 73
  75. Ⅳ- (10) クリックジャッキング 【⼀般的な対策】 • frame および iframe での参照を制限する「X-Frame-Options」ヘッダをレ スポンスに付与

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

  77. 代表的な脆弱性とその対策まとめ カテゴリ 脆弱性・攻撃の例 Django での対策 Ⅰ. パスワード系 (1) パスワード不正取得 ◦

    (2) パスワード漏洩 ◦ Ⅱ. 認証・認可系 (3) セッション管理の不備 ◦ (4) アクセス制御の不備 ◦ Ⅲ. インジェクション 攻撃系 (4) SQLインジェクション ◦ (5) HTTPヘッダ・インジェクション ◦ (6) メールヘッダ・インジェクション ◦ OSコマンド・インジェクション ✕ 該当箇所が無いか探す Ⅳ. クロスサイト (罠サイト)系 (8) XSS ◦ (9) CSRF ◦ (10) クリックジャッキング ◦ Ⅴ. その他 ディレクトリ・トラバーサル ✕ 該当箇所が無いか探す バッファオーバーフロー ✕ 該当箇所が無いか探す ཁ ௥ Ճ ର Ԡ ཁ ஫ ҙ ཁ ஫ ҙ ཁ ஫ ҙ ཁ ௥ Ճ ର Ԡ 76 ཁ ௥ Ճ ର Ԡ ཁ ௥ Ճ ର Ԡ ཁ ஫ ҙ
  78. ポイント ③ ③ フルスタック(全部⼊り)の Django を使えば セキュリティ対策もまるっと万事解決? ⇒ほぼ解決。ただし、例外や追加対応が必要なものも 77

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

    78
  80. まとめ • 経産省・IPA が注意喚起した Webアプリケーションの脆弱性対策は必須 • IPA の「安全なウェブサイトの作り⽅」は最低限必ず網羅 • 補助教材として「徳丸本」を活⽤

    • Django 公式ドキュメント「Django におけるセキュリティ」も必読 https://docs.djangoproject.com/ja/2.2/topics/security/ • 脆弱性診断や WAF、各種ツールの利⽤も検討 • 正しく Django を使えば、主な脆弱性は⾃動的に対策してくれるので便利 • 安⼼して現場で Django を使っていきましょう✌ 79
  81. 今回 話したこと ① Webアプリケーションのセキュリティ対策って そもそも必要なの? ⇒絶対必要(判例もある) ② 「これだけは絶対やっとけ」的な基準はある? ⇒IPA「安全なウェブサイトの作り⽅」 ③

    フルスタック(全部⼊り)の Django を使えば セキュリティ対策もまるっと万事解決? ⇒ほぼ解決。ただし、例外や追加対応が必要なものも 80
  82. 宣伝 (電⼦版・紙の本) 『現場で使えるDjango の教科書 《基礎編》』 『現場で使えるDjango の教科書 《実践編》』 (電⼦版) (紙の本)

    『現場で使える Django REST Framework の教科書』 (紙の本) (紙の本) ★ セキュリティの章あり ★ セキュリティの章あり 81 【 Amazon 】 【 BOOTH 】 (電⼦版)
  83. 参考資料 (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
  84. 参考資料 (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