Upgrade to Pro — share decks privately, control downloads, hide ads and more …

現場で使える 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(しーさーふ)って何?」というレベルの人にも分かるように基本から解説します。

akiyoko

May 18, 2019
Tweet

More Decks by akiyoko

Other Decks in Programming

Transcript

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  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
    ཁ ௥ Ճ ର Ԡ

    View Slide

  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⽂字以上であること
    ③ よくあるパスワードのリストと⼀致していないか
    ④ 数値のみで構成されていないか
    を検証してくれる




    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  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

    View Slide

  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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  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

    View Slide

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

    View Slide

  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
    ཁ ஫ ҙ

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  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
    ཁ ஫ ҙ

    View Slide

  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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  57. Ⅳ- (8) XSS
    56

    View Slide

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

    View Slide

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

    View Slide

  60. Ⅳ- (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()
    ཁ ஫ ҙ

    View Slide

  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
    ཁ ஫ ҙ
    ཁ ௥ Ճ ର Ԡ

    View Slide

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

    View Slide

  63. Ⅳ- (9) CSRF
    62

    View Slide

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

    View Slide

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

    View Slide

  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 とは

    View Slide

  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 とは

    View Slide

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

    View Slide

  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
    ཁ ஫ ҙ

    View Slide

  70. Ⅳ- (9) CSRF
    Django サイト
    CsrfViewMiddleware
    リクエスト⾏
    メッセージヘッダ
    メッセージボディ
    GET /accounts/login/
    ステータス⾏
    メッセージヘッダ
    メッセージボディ
    200 OK
    Set-Cookie: csrftoken=111111

    ...
    name="csrfmiddlewaretoken"
    value="xxxxxx">

    ① GET リクエスト
    ユーザー名
    パスワード
    ログイン
    ビュー
    ログイン画⾯
    レスポンス
    ② POST リクエスト(次ページへ)
    ( csrftoken = 111111)
    ①ʼʼ csrfmiddlewaretoken
    ⽣成
    ①ʼ csrftoken ⽣成
    ( csrfmiddlewaretoken = xxxxxx)
    Cookie
    csrftoken=111111
    (Domain=example.com)
    69
    Djangoでの CSRF 対策

    View Slide

  71. 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 対策
    レスポンス

    View Slide

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

    View Slide

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

    View Slide

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

    購 ⼊
    罠サイト
    https://evil.xyz/
    73

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  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

    View Slide

  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

    View Slide