まったり技術ブログ

主にWebエンジニア向けのセキュリティ情報

【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日 新規作成

PHP-FPM RCE(CVE-2019-11043)の攻撃をAWS WAFでブロック

  • はじめに
  • AWS WAFの設定
    • 文字列マッチの条件を作成
    • ルールを作成
    • ACLにルールを追加
  • 攻撃がブロックされることを確認
  • 参考
  • 更新履歴

はじめに

 先日、PHP-FPMにRCEの脆弱性(CVE-2019-11043)があることが公表されました。

 脆弱性の詳細について本記事で説明しません。脆弱性を含んでいるバーションや攻撃が可能となる条件等は下のリンクの記事を参照して下さい。

 本記事では、この脆弱性に対しての攻撃をブロックするAWS WAFのルールの作成方法を紹介します。
「PHPのアップデート」や「Nginxの設定変更」で対応できますが、それが行えない環境下での対応手段の1つだと思っています。
ブロックルールは単純なので、AWS WAF以外の製品にも適用できるとも考えています。

jp.tenable.com

続きを読む

Laravelで学ぶ「安全でないデシリアライゼーション」

f:id:motikan2010:20191105225943p:plain

  • はじめに
  • 環境
  • 事前知識
    • 1つのPHPファイルでやってみる
    • なぜOSコマンドが実行されたのか
    • なにが問題なのか
  • Laravel でやってみる
    • 修正内容
    • 脆弱性の確認
    • OSコマンド呼び出し部分の確認
      • Illuminate/Broadcasting/PendingBroadcast クラス
      • Faker/Generator クラス
  • PHPGGC(PHP Generic Gadget Chains)
    • PoCを出力する
  • 対策
    • unserialize関数に渡す値はバリデーションを行う
    • allowed_classesオプションの付与(※非推奨な対策)
  • まとめ
  • 更新履歴

はじめに

 OWASP Top 10 - 2017に「A8:安全でないデシリアライゼーション」がありますが、この脆弱性が顕在化 することは少なく、あまり身近ではないかなと感じています。ということで今回は本脆弱性がどういったものなのかを簡単に手元で試すことができるLaravelを用いて説明します。
 PHPオブジェクトインジェクションを試すことになります。

続きを読む

【セキュリティ】motikan2010作サイト『オープンハニーポット』とは

f:id:motikan2010:20191010000552p:plain:w400
  • はじめに
  • どのようなサイト?
  • 各画面の説明
    • トップ
    • リクエスト一覧
    • リクエスト詳細
    • 時間別アクセス数
    • 日別アクセス数
    • ログイン画面
  • 今後
  • 参考
  • 更新履歴

はじめに

 前回のブログ更新から1ヶ月以上経ち、たまには更新をしないといけないと思ったので最近私が作成したサイトを簡単に紹介することにします。
 その名は『オープンハニーポット』!!
 まだ β版 ということで挙動がおかしい部分がありますが、興味のある方は是非さわってみてください。

honypot.motikan2010.com

どのようなサイト?

ハニーポットという名が入っていることからもわかる通り、ハニーポットに関係しているサイトです。
 このサイトには私が運用している複数のハニーポットのアクセスログが保存されており、誰でもそのログを閲覧することができます。ちなみに今は4台のハニーポットからログを収集しています。

 その4台上で動作しているハニーポットは全て同じですが、動作させているクラウドサービスがそれぞれ異なっており、「AWS」「GCP」「Azure」「Alibaba Cloud」を利用しています。
 その意図としては、クラウドサービスごとに攻撃の種類が異なるのかを観測したかったというのがあります。(実際は軽く確認した感じ、差異はありませんでした・・・)

 「オープンハニーポット」では、それらのハニーポットで収集されたアクセスログの詳細や時間別のアクセス数などを確認することができます。

続きを読む

OWASP Security Shepherdで入門するWebセキュリティ

f:id:motikan2010:20190824233013p:plain

  • はじめに
    • 公式サイト
  • DVWA(Damn Vulnerable Web Application)との違い
  • 環境構築
  • 試しに解いてみる
    • 問題 1 - 入力フォームが無い状態でのリクエスト改変
    • 問題 2 - JavaScript側のバリデーションの回避
  • AWS EC2で動作させる方法
  • まとめ

はじめに

 「OWASP Security Shepherd」はWebセキュリティを学ぶことができるアプリケーションです。
Webフレームワークを用いた場合にでも発生する可能性が高い脆弱性(リクエストパラメータの改ざん等)が取り上げられており、そのような脆弱性に対して実際に攻撃する経験をすることができます。
 Webフレームワークを用いての開発が主流となっている昨今でも非常に有意義な学習用ツールだと思っています。普段開発で用いらないローカルプロキシを使い始めるきっかけにもよいかと。

 使い方の流れとしては「ログイン → 問題を解く → スコアに反映」といった感じです。
構築も簡単であり、競技形式で学習ができるのが素晴らしい点だと思っています。
f:id:motikan2010:20190825000646p:plain

公式サイト

www.owasp.org

続きを読む