過去に、OWASP ZAP使って、Django製の Mezzanine で構築されたブログに対して、脆弱性を検証してみる | Monotalk
脆弱性を検証、対策を実施しました。

セキュリティ系のその他のツールを探してたのですが、Observatory by Mozilla
コマンドラインツールmozilla/http-observatory-cli: The command line tool for the HTTP Observatory見つけたので、
こちらをインストールして、脆弱性を検証、対策をしてみた結果を記載します。


前提

以下の環境で実行しています。

  • OS
    CentOS release 6.9 (Final)

  • Python Version
    Python 2.7.8

  • Package (必要そうなものだけ抜粋)
    Django (1.10.6)
    Mezzanine (4.2.3)

また、Django製の Mezzanine で構築されたブログに対して、脆弱性を検証してみる | Monotalk設定は引き継いでいますので、この記事で対策したものは、
警告出力は行われないと思います。

検証の内容

  • http-observatory-cli は オプションなどはなく、デフォルトで検証を実行

  • Mezzanine は、公開画面 ドメイン指定での検証と、 管理ログイン画面の検証 を行う


http-observatory-cli のインストールと検証の実行

  • インストール
    pipインストールできます。

    pip install httpobs-cli
    

  • 検証の実行 コマンドを叩いて検証を実行します。

    httpobs -v -z -x www.monotalk.xyz
    
    ---------------------------------------------------
    Score: 30 [D]
    Modifiers:
        [   0] All cookies use the Secure flag and all session cookies use the HttpOnly flag
        [   0] Content is not visible via cross-origin resource sharing (CORS) files or headers
        [   0] Contribute.json isn't required on websites that don't belong to Mozilla
        [   0] HTTP Public Key Pinning (HPKP) header not implemented
        [   0] Referrer-Policy header not implemented
        [   0] X-Content-Type-Options header set to "nosniff"
        [   0] X-Frame-Options (XFO) header set to SAMEORIGIN or DENY
        [   0] X-XSS-Protection header set to "1; mode=block"
        [  -5] Subresource Integrity (SRI) not implemented, but all external scripts are loaded over https
        [ -20] Does not redirect to an https site
        [ -20] HTTP Strict Transport Security (HSTS) header not implemented
        [ -25] Content Security Policy (CSP) header not implemented
    
    ---------------------------------------------------
    
    オプション-v -z -x意味は以下の通りです。

    • -z
      問題のないチェック項目も出力

    • -v
      インジケーターの出力

    • -x
      最近のスキャン結果に、スキャン結果を表示しない


警告の内容と、対処方法

Score は 30 [D] 評価でした。
マイナス評価が出た項目に対して、対処していきます。

Subresource Integrity (SRI) not implemented, but all external scripts are loaded over https

CDN 経由で参照しているサブリソース、script、link タグに、integrity 属性を付与していないという警告です。
以下が、参考になりました。

google analyticsタグなどには、付与できそうにない。
付与できるものもあるし、付与できないものもあるため、
対処しませんでした。。(対処できず。。)

Does not redirect to an https site

HTTP から、HTTPS へのリダイレクトが行われていないために、警告が出力されていました。

こちらは、settings.py に以下追加することで、 HTTP から HTTPSへリダイレクトされるようになります。

SECURE_SSL_REDIRECT = True

もちろんHTTPサーバー側でも設定はできます。
以下が、参考になりました。

自分のサイトでは、VirtualHost設定していたので、以下の通り、80番ポートでアクセスされた場合、
httpsリダイレクトするように設定しました。1

<VirtualHost *:80>
    ServerName www.monotalk.xyz
    ServerAlias monotalk.xyz *.monotalk.xyz
    Redirect / https://www.monotalk.xyz/
</VirtualHost>
[1] が、Django で設定できることを知ったので、そちらで設定を行うようにしました。

HTTP Strict Transport Security (HSTS) header not implemented

HSTSヘッダが付与されていないために警告が出力されているようでした。
こちらも、django の SecurityMiddleware設定で付与できます。
以下をsettings.py追加しました。

# 180日を設定
SECURE_HSTS_SECONDS = 15552000                                                                                                                         
# includeSubDomains を付与する
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
# preload を付与する (django 1.11から追加)
SECURE_HSTS_PRELOAD = True

以下、参考になりました。

Content Security Policy (CSP) header not implemented

CSP ヘッダが付与されていないため、出力される警告です。
以下が参考になりました。

正直、いきなり適用するのは難しいそうだったので、
Report 機能のみ使用して、 Reportを記録 して、少しずつ修正していく方法をとります。
Django だと、CSP ヘッダを出力する mozilla/django-csp: Content Security Policy for Django.いう、Middlewareと、
Report を記録するadamalton/django-csp-reports: Django app for handling browser reports from Content Security Policy violations
いうplugin がありましたので、それらをインストールして設定してみます。

django-csp のインストール

  • pip install

    pip install django-csp
    ------------------------------------
    Successfully installed django-csp-3.3
    ------------------------------------
    

  • settings.py に application を追加

    INSTALLED_APPS = (
        "csp", 
        ...
        )
    

  • MIDDLEWARE_CLASSES に csp.middleware.CSPMiddleware追加

    MIDDLEWARE_CLASSES = (
        # ...
        'csp.middleware.CSPMiddleware',
        # ...
    )
    

  • django-csp の設定を追加 CSP_REPORT_URI に django-csp-report のURLを、
    CSP_REPORT_ONLY に True を設定します。

    #############################
    # Django-CSP Settings
    #############################
    CSP_DEFAULT_SRC = ("'self'")
    CSP_REPORT_URI = '/report/'
    CSP_REPORT_ONLY = True
    

django-csp-reports のインストール

  • pip install

    pip install django-csp-reports
    -----------------------------------
    Successfully installed django-csp-reports-1.1
    -----------------------------------
    

  • settings.py に application を追加

    INSTALLED_APPS = (
        "cspreports", 
        ...
        )
    

  • django-csp-reports の設定を追加
    EMAIL で通知する機能をOFF、
    DBに書き込む機能をOFFに設定し、
    LOGにのみ出力するようにします。

    CSP_REPORTS_EMAIL_ADMINS = False
    CSP_REPORTS_SAVE = False
    

  • Loggerの設定
    handler に csp_report_file を、
    logger に CSP Reports を追加します。
    CSP Reports は、django-csp-reports のデフォルトのロガー名です。

##########################
# LOGGING SETTINGS
##########################
# settings.py
LOGGING = {
    'version': 1,
    'formatters': {
        'verbose': {
            'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s'
        },
        'simple': {
            'format': '%(levelname)s %(message)s'
        },
    },
    'handlers': {
        'file': {
            'class': 'logging.handlers.RotatingFileHandler',
            'filename': '/var/log/your_app.log',
            'maxBytes': 1024 * 1024 * 10,
            'backupCount': 10, 
            'formatter': 'verbose',
        },
        'csp_report_file': {
            'class': 'logging.handlers.RotatingFileHandler',
            'filename': '/var/log/your_csp_report.log',
            'maxBytes': 1024 * 1024 * 10,
            'backupCount': 10, 
            'formatter': 'verbose',
        },
    },
    'loggers': {
        'django.request': {
            'handlers': ['file'],
            'level': 'INFO',
            'propagate': False,
            },
        'django_crontab': {
            'handlers': ['file'],
            'level': 'INFO',
            'propagate': False,
            },
        'CSP Reports': {
            'handlers': ['csp_report_file'],
            'level': 'INFO',
            'propagate': False,
        }
    },
}

  • urls.py に django-csp-reports のurl を追加
    urlpatterns += [
        url("^", include("cspreports.urls")),
    ]
    

これで、ログには以下の形式で、reportが出力されるようになります。
しばらくこれで、様子を見守ろうかと思います。2

WARNING 2017-04-17 02:40:06,206 utils 17040 140383643092736 Content Security Policy violation: {
    "csp-report": {
        "blocked-uri": "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js",
        "disposition": "report",
        "document-uri": "https://www.monotalk.xyz/",
        "effective-directive": "script-src",
        "original-policy": "default-src 'self'; report-uri /report/",
        "referrer": "",
        "status-code": 0,
        "violated-directive": "script-src"
    }
}

[2] 後日、log を MongoDB に Export しましたが、加工が若干面倒くさいです。
Looger 設定のFormat を記載している simple にするか、'%(message)s' だけログファイルに出力するほうが、
RDBなりに登録して、集計するならしやすいと思います。


http-observatory-cli で再度、検証の実行

再度検証するには、-r オプションを付けて、
コマンドを実行します。
付けないと、前回の検証結果が出力されて、アレってなるので、注意です。

httpobs  -r -v -z -x www.monotalk.xyz
-------------------------------------------------------------
Score: 70 [B]
Modifiers:
    [   0] All cookies use the Secure flag and all session cookies use the HttpOnly flag
    [   0] Content is not visible via cross-origin resource sharing (CORS) files or headers
    [   0] Contribute.json isn't required on websites that don't belong to Mozilla
    [   0] HTTP Public Key Pinning (HPKP) header not implemented
    [   0] HTTP Strict Transport Security (HSTS) header set to a minimum of six months (15768000)
    [   0] Initial redirection is to https on same host, final destination is https
    [   0] Referrer-Policy header not implemented
    [   0] X-Content-Type-Options header set to "nosniff"
    [   0] X-Frame-Options (XFO) header set to SAMEORIGIN or DENY
    [   0] X-XSS-Protection header set to "1; mode=block"
    [  -5] Subresource Integrity (SRI) not implemented, but all external scripts are loaded over https
    [ -25] Content Security Policy (CSP) header not implemented
-------------------------------------------------------------

Content Security Policy (CSP) header not implementedままですが、
Score は 70 [B] となりました。
後日、レポート集計して CSP 設定して、もう少し点数は挙げたいかなと思います。3
以上です。

[3] そもそもの話なのですが、点数が低いからといって、実害の及ぶセキュリティホールがあるサイトかと言うとNOで、
点数が高いからといって、実害の及ぶセキュリティホールがないサイトかと言うとNOな、指標を出すツールかと思います。
ただ、これで点数が低いと、実害の及ぶ可能性は、点数が高いサイトよりも高いというアレかと。
開発者とか企業としては、内部で検証は、実施するだけは実施するけど、対応施作をやる、やらないは、実害のあるなしとか、
対応工数とか、実施することで、営業的に良しとか、その他の考慮事項はありそうな気がします。
OWAZAP の検証結果も検証まではやるとして、対応の実施についてはサイトによるのだと思います。

コメント