まったり技術ブログ

主にWebエンジニア向けのセキュリティブログ。たまに開発も

【Python】Waitress の ReDoS をやってみる(CVE-2020-5236)

f:id:motikan2010:20200205224320p:plain
いらすとや産のPython

  • はじめに
    • Waitress とは
  • 検証
    • 検証バージョン
    • 環境構築
    • ReDoS をしてみる
      • 脆弱なバージョン 1.4.2
      • パッチ適用バージョン 1.4.3
      • 脆弱性が存在しないバージョン 1.4.1
  • 脆弱性を掘り下げる
    • 修正コミット
    • 修正前 と 修正後 の正規表現
      • 簡単に負荷の大きい正規表現を試す
    • 遅い原因を考えてみる
  • 参考
    • 本脆弱性の情報
    • ReDoSの情報
  • 更新履歴

はじめに

 GitHub Advisory Database - CVE-2020-5236緊急度が Critical(最も危険) となっていたので調べてみました。

f:id:motikan2010:20200205214545p:plain:w700
GitHub アドバイザリ - CVE-2020-5236

 影響を受ける Waitress のバージョンは1.4.2のみです。
リリースのタイムラインは以下のようになっています。2020年1月中に導入した人はバージョンを確認してみたほうがよいでしょう。(※本脆弱性以外にも過去のバージョンには他の脆弱性が見つかっているようでした。)

  • 1.4.2 2020年 1月 2日 リリース
  • 1.4.3 2020年 2月 2日 リリース

Waitress — waitress 1.4.3 documentation

Waitress とは

 あまり耳にしないソフトウェアだと思う「Waitress」は何かと言うと、「WSGI サーバ」らしい。

 WSGI サーバとは何ぞやというと、

Web Server Gateway Interface (WSGI; ウィスキー) は、プログラミング言語Pythonにおいて、WebサーバとWebアプリケーション(もしくはWebアプリケーションフレームワーク)を接続するための、標準化されたインタフェース定義である。

by Wikipedia

つまり、
  Django や Bottle といったPython言語のWebアプリケーションフレームを動作させる為のアプリケーションサーバとのこと。
 Ruby界隈で例えると Unicorn に近い役割を持っているWebサーバだと思う。

 WSGI サーバーについてのより詳しい内容は以下の記事が参考になりました。
WSGIアプリケーションとは?WebフレームワークからWSGIサーバーまで - Make組ブログ

 今回脆弱性が発見された「Waitress」はそのようなソフトウェアの1つということです。

 どのくらい普及しているのかというと、GitHub の 約12,800個のリポジトリで利用されていることから、そこそこ普及しているWebサーバだと思います。

f:id:motikan2010:20200205215037p:plain:w700
2020/2/5 現在

 そんな Waitress から ReDoS(Regular expression Denial of Service) の脆弱性が発見されました。
本脆弱性の再現には特別な設定等は必要なく、さらに攻撃方法が容易ということで簡単に再現してしまうことから緊急度が Critical となっていると思います。

github.com

続きを読む

【Webセキュリティ】依存ライブラリのセキュリティチェックツール(SCA)を使ってみる

f:id:motikan2010:20200129012730p:plain
  • はじめに
  • 言語別 ツール一覧
    • PHP
      • sensiolabs / security-checker
        • 使い方
        • 脆弱性データベース
        • Web版
    • Ruby
      • rubysec / bundler-audit
        • 使い方
      • 脆弱性データベース - rubysec / ruby-advisory-db
    • Python
      • pyupio / safety
        • 脆弱性データベース
        • 使い方
        • 詳細情報レポートの取得。 --full-report オプション
    • Java
      • jeremylong / DependencyCheck
      • Gradle用 jeremylong/dependency-check-gradle
    • JavaScript
      • Npm標準ツール - npm-audit
        • 脆弱なパッケージをアップデートする " npm audit fix " コマンド
  • まとめ
  • 更新履歴

はじめに

 まず「依存ライブラリのセキュリティチェックツール」とは?ということですが、このようなツールの呼び方が定まっていないため本記事ではこのような呼び方にしています。
(強いて言えば、Software Composition Analysツールと呼ばれているツール群)

これらのツールの特徴として、動作しているアプリケーションが依存しているライブラリやパッケージに既知の脆弱性が存在していないかをバージョン情報などをもとに検査します。脆弱性があるバージョンのライブラリがあるとアラートを出す挙動をします。

 従来から利用されている Burp Suite や OWASP ZAP などのWebセキュリティ診断ツールは実際にアプリケーションを動作させて、その挙動から脆弱性を検出します。それに対して「依存ライブラリのセキュリティチェックツール」はアプリケーションを動作させずに検査します。ツールの動作が全く異なるので、検査内容も大きく違います。

 どちらかといったらWordPressの検査に利用される WPScan に検査内容は近いです。どちらも利用しているプラグイン(ライブラリ)のバージョン情報で検出するのがメインとなっているからです。
それでも検査を実施できる範囲は異なります。
 WPScan はネット越しに公開されているサイト全てに検査することが可能です。対して「依存ライブラリのセキュリティチェックツール」はアプリケーションが依存しているライブラリが記述されているファイル(Gemfile.lock や composer.lock)が検査対象になりますので、それらのファイルを閲覧できる権限者のみが検査を実施できます。それらのファイルに依存関係はほぼ全て記述されているので、依存関係を全て取得するのが難しいネット越しでの検査に比べてより厳密な検査ができます。

 そして近頃、Webアプリケーションなどのソフトウェアに依存しているライブラリに既知の脆弱性が潜んでいないかを検査するために、セキュリティチェックツールを提供・利用するサービスが増えてきている気がしています。

▼ Snyk もセキュリティチェックツールを開発/提供している企業であり資金調達が上手くいっている模様。 jp.techcrunch.com

 まずは、手軽に導入することができるOSSのセキュリティチェックツールを使用してみて、どのような検査結果を得ることができるのかなどを確認してみます。
ついでに検出された脆弱性の情報はどこから取得しているのかなども確認してきます。

続きを読む

2018年 人気脆弱性 TOP 10 in GitHub

f:id:motikan2010:20200106223239p:plain
  • はじめに
  • TOP 10
    • 10位 541 ポイント 『Intel Core マイクロプロセッサを搭載したシステムにおける情報漏えいに関する脆弱性(CVE-2018-3620 通称「Foreshadow」)』
    • 9位 575 ポイント 『Intel ハードウェアアーキテクチャのデバッグ例外を適切に処理していない問題(CVE-2018-8897)』
    • 8位 582 ポイント 『WinRAR における入力確認に関する脆弱性(CVE-2018-20250)』
    • 7位 592 ポイント 『TBK DVR4104 および DVR4216 デバイスにおける証明書・パスワードの管理に関する脆弱性(CVE-2018-9995)』
    • 6位 605 ポイント 『Microsoft Exchange Server における権限を昇格される脆弱性(CVE-2018-8581)』
    • 5位 627 ポイント『OpenSSH における情報漏えいに関する脆弱性(CVE-2018-15473)』
    • 4位 674 ポイント 『Apache Struts2 における任意のコードが実行可能な脆弱性(CVE-2018-11776、S2-057)』
    • 3位 946 ポイント『複数の Microsoft Windows 製品における権限を昇格される脆弱性(CVE-2018-8120)』
    • 2位 1236 ポイント『Drupal における入力確認に関する脆弱性(CVE-2018-7600 通称「Drupalgeddon2」)』
    • 1位 1242 ポイント『libssh における認証に関する脆弱性(CVE-2018-10933)』
    • TOP 10 一覧
    • おまけ
      • リポジトリ数ランキング
  • 更新履歴

はじめに

 2020年 1発目の投稿となりますが、時代に逆行して2018年に人気だった脆弱性を紹介します。
先日書いた「2019年 人気脆弱性 TOP 10 in GitHub」の2018年版です。

↓ 2019年版 ↓
blog.motikan2010.com

TOP 10

 TOP 10の算出方法としては、「リポジトリの数」と「それらのリポジトリのスターの数」を使用しています。
リポジトリ毎に10ポイント、スター毎に1ポイント 加算される形式で算出しています。
 ※各脆弱性のタイトルはJVNから引用しています。

10位 541 ポイント 『Intel Core マイクロプロセッサを搭載したシステムにおける情報漏えいに関する脆弱性(CVE-2018-3620 通称「Foreshadow」)』

access.redhat.com

人気リポジトリ
GitHub - ionescu007/SpecuCheck: SpecuCheck is a Windows utility for checking the state of the software mitigations and hardware against CVE-2017-5754 (Meltdown), CVE-2017-5715 (Spectre v2), CVE-2018-3260 (Foreshadow), and CVE-2018-3639 (Spectre v4)

続きを読む

2019年 人気脆弱性 TOP 10 in GitHub

f:id:motikan2010:20191231225911p:plain
  • はじめに
  • TOP 10
    • 10位 501 ポイント『Pulse Secure Pulse Connect Secure におけるパーミッションに関する脆弱性(CVE-2019-11510)』
    • 9位 522 ポイント『Canonical snapd における入力確認に関する脆弱性(CVE-2019-7304)』
    • 8位 545 ポイント『Firefox および Thunderbird における入力確認に関する脆弱性(CVE-2019-11708)』
    • 7位 572 ポイント『Android 用 ES File Explorer File Manager アプリケーションにおける入力確認に関する脆弱性(CVE-2019-6447)』
    • 6位 629 ポイント『Espressif ESP-IDF および ESP8266_NONOS_SDK における入力確認に関する脆弱性(CVE-2019-12586)』
    • 5位 704 ポイント『Oracle Fusion Middleware の Oracle WebLogic Server における WLS Core Components に関する脆弱性(CVE-2019-2618)』
    • 4位 785 ポイント『Docker および runc におけるコンテナエラーの脆弱性(CVE-2019-5736)』
    • 3位 935 ポイント『Oracle Fusion Middleware の Oracle WebLogic Server における Web Services に関する脆弱性(CVE-2019-2725)』
    • 2位 1868 ポイント『PHP における境界外書き込みに関する脆弱性(CVE-2019-11043)』
    • 1位 5413 ポイント『複数の Microsoft Windows 製品のリモートデスクトップ サービスにおけるリモートでコードを実行される脆弱性(CVE-2019-0708 通称「BlueKeep」)』
    • TOP 10 一覧
  • おまけ
    • リポジトリ数ランキング
  • 更新履歴

はじめに

 2019年も終わりに近づいているので、2019年に公表されたCVEが採番されている脆弱性の中から人気なものをGitHubから検索しTOP 10を決めていきます。

検索結果のリポジトリについては下記のリポジトリで管理されています。
github.com

TOP 10

 TOP 10の算出方法としては、「リポジトリの数」と「それらのリポジトリのスターの数」を使用しています。
リポジトリ毎に10ポイント、スター毎に1ポイント 加算される形式で算出しています。
 ※各脆弱性のタイトルはJVNから引用しています。

10位 501 ポイント『Pulse Secure Pulse Connect Secure におけるパーミッションに関する脆弱性(CVE-2019-11510)』

jp.tenable.com

攻撃者はユーザー名とプレーンテキストパスワードを取得するためにCVE-2019-11510を使用して脆弱性のあるシステムを探し出しています。

とある通り、任意のファイルが取得できる脆弱性となっています。

Twitter社にも該当する脆弱性があったようですね。 Twitterも影響を受けたSSL VPN製品の脆弱性についてまとめてみた - piyolog

こちらの脆弱性はBlack Hat 2019でも触れられていた脆弱性でした。 https://i.blackhat.com/USA-19/Wednesday/us-19-Tsai-Infiltrating-Corporate-Intranet-Like-NSA.pdf

人気リポジトリ
GitHub - projectzeroindia/CVE-2019-11510: Exploit for Arbitrary File Read on Pulse Secure SSL VPN (CVE-2019-11510)

続きを読む

【Python】Selenium側からネットワーク情報を取得する

f:id:motikan2010:20191120223853p:plain

はじめに

 Selenium側からページが読み込むリソース情報(URL)を取得する方法を紹介します。
言語はPythonを使います。

動作環境

  • Python 3.6.9
  • Selenium 3.141.0
  • Google Chrome 78.0

取得対象

 サンプルページのHTMLは以下のようになっており、このページが開かれたら6つのリクエストが飛ぶはずです。
(JSファイル2つ、画像ファイル1つ、Ajaxのリクエスト2つ、ファビコン1つ)
 それらのリソースのURLをSelenium側(Python側)から取得することが本記事での目的となります。

<html>
<body>
  <img src="https://dummyimage.com/600x400/000/fff.png" />
</body>
<script src="./lib/jquery-3.3.1.min.js"></script>
<script src="./lib/bootstrap.min.js"></script>
<script type="text/javascript">
  $.ajax({type: "GET", url: "ajax-get.php"});
  $.ajax({type: "POST",url: "ajax-post.php", data: "name=taro"});
</script>
</html>

実装

パフォーマンス情報の取得

 リクエストやレスポンス等のネットワーク情報はパフォーマンス情報内に含まれています。
なので、まず初めにパフォーマンス情報を取得してみます。

from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities

url = 'http://127.0.0.1:8080/index.html'
d = DesiredCapabilities.CHROME
d['goog:loggingPrefs'] = { 'performance': 'ALL' }
driver = webdriver.Chrome(desired_capabilities=d)
driver.get(url)

for entry_json in driver.get_log('performance'):
    print(entry_json)

driver.close()
  • パフォーマンス情報の取得結果

 パフォーマンスは以下のように出力されます。
パフォーマンス情報はイベント毎に出力されるようになっており、リクエスト情報以外のイベント情報も出力されるようになっています。
ここではURLを取得したいので、次はリクエスト情報のみ出力するようにフィルタ処理を追加します。

{'level': 'INFO', 'message': '{"message":{"method":"Network.loadingFinished","params":{"encodedDataLength":0,"requestId":"DA7DC2455827A385EFD29AAD84A5FAD4","shouldReportCorbBlocking":false,"timestamp":31590.809391}},"webview":"7C67A40D1B7E099220778917F0FC37BF"}', 'timestamp': 1574243695252}
{'level': 'INFO', 'message': '{"message":{"method":"Page.loadEventFired","params":{"timestamp":31590.84658}},"webview":"7C67A40D1B7E099220778917F0FC37BF"}', 'timestamp': 1574243695252}
{'level': 'INFO', 'message': '{"message":{"method":"Page.frameStoppedLoading","params":{"frameId":"7C67A40D1B7E099220778917F0FC37BF"}},"webview":"7C67A40D1B7E099220778917F0FC37BF"}', 'timestamp': 1574243695253}
{'level': 'INFO', 'message': '{"message":{"method":"Page.domContentEventFired","params":{"timestamp":31590.847009}},"webview":"7C67A40D1B7E099220778917F0FC37BF"}', 'timestamp': 1574243695253}
{'level': 'INFO', 'message': '{"message":{"method":"Page.frameResized","params":{}},"webview":"7C67A40D1B7E099220778917F0FC37BF"}', 'timestamp': 1574243695253}
{'level': 'INFO', 'message': '{"message":{"method":"Network.requestWillBeSent","params":{"documentURL":"http://127.0.0.1:8080/index.html","frameId":"7C67A40D1B7E099220778917F0FC37BF","hasUserGesture":false,"initiator":{"type":"other"},"loaderId":"4BC43963C4D0AA21F19857E6EB4160C8","request":{"headers":{"Sec-Fetch-User":"?1","Upgrade-Insecure-Requests":"1","User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"},"initialPriority":"VeryHigh","method":"GET","mixedContentType":"none","referrerPolicy":"no-referrer-when-downgrade","url":"http://127.0.0.1:8080/index.html"},"requestId":"4BC43963C4D0AA21F19857E6EB4160C8","timestamp":31590.884601,"type":"Document","wallTime":1574243695.273999}},"webview":"7C67A40D1B7E099220778917F0FC37BF"}', 'timestamp': 1574243695274}
以下略...

 フィルタ条件を調べる為にリクエスト情報に着目します。一番下の出力がリクエスト情報です。
その情報を整形したのが下記のものです。
 「method」が「Network.requestWillBeSent」になっているものをフィルタすれば良さそうです。

{
  "message": {
    "method": "Network.requestWillBeSent", ← この値がフィルタに使えそう
    "params": {
      "documentURL": "http://127.0.0.1:8080/index.html",
      "frameId": "7C67A40D1B7E099220778917F0FC37BF",
      "hasUserGesture": false,
      "initiator": {
        "type": "other"
      },
      "loaderId": "4BC43963C4D0AA21F19857E6EB4160C8",
      "request": {
        "headers": {
          "Sec-Fetch-User": "?1",
          "Upgrade-Insecure-Requests": "1",
          "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"
        },
        "initialPriority": "VeryHigh",
        "method": "GET",
        "mixedContentType": "none",
        "referrerPolicy": "no-referrer-when-downgrade",
        "url": "http://127.0.0.1:8080/index.html"
      },
      "requestId": "4BC43963C4D0AA21F19857E6EB4160C8",
      "timestamp": 31590.884601,
      "type": "Document",
      "wallTime": 1574243695.273999
    }
  },
  "webview": "7C67A40D1B7E099220778917F0FC37BF"
}

ブラウザが読み込むリソースのURLを取得

 URLのみを表示するフィルタを追加したコードが下記になります。
for内部を以下のようにすることでリクエストURLを取得することが可能です。

import json

# ...

for entry_json in driver.get_log('performance'):
    entry = entry_json.loads(entry_json['message'])
    if entry['message']['method'] != 'Network.requestWillBeSent' :
        continue;
    print(entry['message']['params']['request']['url'])

 実行結果が以下です。(先頭のページ表示時のURLも表示されていますが、許容できる範囲でしょう)

http://127.0.0.1:8080/index.html
https://dummyimage.com/600x400/000/fff.png
http://127.0.0.1:8080/lib/jquery-3.3.1.min.js
http://127.0.0.1:8080/lib/bootstrap.min.js
http://127.0.0.1:8080/ajax-get.php
http://127.0.0.1:8080/ajax-post.php
http://127.0.0.1:8080/favicon.ico

 リクエスト時のNetwork.requestWillBeSentのようなイベントは他にもあり以下のコードで一覧が記載されています。
取得したい情報に応じてフィルタを掛けることが可能です。
github.com

まとめ

 Seleniumはテストの自動化といった場面で多く活用されていますが、本記事では大量のJavaScriptファイルの通信を解析する場面を想定したSeleniumの使い方でした。
難読化されたJavaScriptの挙動などを軽く確認したい時とかに活用できそうです。
 実際に私も難読化された大量のJavaScriptファイルを動的解析する必要があり、本記事で紹介した方法を試みました。
他にも解析方法があったらSelenium問わずやってみたいです。

更新履歴

  • 2019年 11月 19日 新規作成