PatreonWordPressプラグインで見つかった脆弱性
公開: 2021-03-26WordPress用のPatreonプラグインの内部監査中に、Jetpack Scanチームは、誰かがWebサイトを乗っ取ることができるいくつかの弱点を発見しました。
これらの脆弱性はプラグインの作成者に開示され、プラグインの作成者はこれらの問題をすべて修正するバージョン1.7.2を即座にリリースしました。 古いバージョンのプラグインを実行している場合は、今すぐ更新してください。
技術的な詳細については、以下をお読みください。 これが頭に浮かんだとしても、心配しないでください。 Jetpack Scanを提供して、マルウェアのスキャンと自動アップグレードまたは削除を処理します。
私たちのチームは、ローカルファイル開示、クロスサイトリクエストフォージェリ(CSRF)、リフレクトクロスサイトスクリプティング(XSS)の脆弱性など、さまざまな攻撃ベクトルを特定しました。
ローカルファイル開示の脆弱性は、悪意のある攻撃者がWebサイトの秘密鍵やデータベースの資格情報などの重要な情報にアクセスするために使用できるバグです。 反映されたクロスサイトスクリプティングおよびクロスサイトリクエストフォージェリの脆弱性は、攻撃者が慎重に作成された悪意のあるリンクをクリックするようにだまして、疑いを持たないユーザーに代わって特定のアクションを実行できるようにする問題です。
これらの一部が悪用された場合、悪意のある個人が脆弱なWebサイトを乗っ取る可能性があります。
ローカルファイル開示の脆弱性
影響を受けるバージョン: <1.7.0
CVE ID: CVE-2021-24227
CVSSv3: 7.5
CWSS: 83.6
public static function servePatronOnlyImage( $image=false ) {
if ( ( !isset( $image ) OR !$image ) AND isset( $_REQUEST['patron_only_image'] ) ) {
$image = $_REQUEST['patron_only_image'];
}
if ( !$image OR $image == '') {
// This is not a rewritten image request. Exit.
return;
}
if ( !( isset( $_REQUEST['patreon_action'] ) AND $_REQUEST['patreon_action'] == 'serve_patron_only_image' ) ) {
return;
}
$upload_locations = wp_upload_dir();
// We want the base upload location so we can account for any changes to date based subfolders in case there are
$upload_dir = substr( wp_make_link_relative( $upload_locations['baseurl'] ) , 1 );
$image = get_site_url() . '/' . $upload_dir . '/' . $image;
if ( current_user_can( 'manage_options' ) ) {
Patreon_Protect::readAndServeImage( $image );
}
// Below define can be defined in any plugin to bypass core locking function and use a custom one from plugin
// It is independent of the plugin load order since it checks if it is defined.
// It can be defined by any plugin until right before the_content filter is run.
if ( apply_filters( 'ptrn/bypass_image_filtering', defined( 'PATREON_BYPASS_IMAGE_FILTERING' ) ) ) {
Patreon_Protect::readAndServeImage( $image );
}
// Check if the image is protected:
$attachment_id = attachment_url_to_postid( $image );
// attachment_url_to_postid returns 0 if it cant find the attachment post id
if ( $attachment_id == 0 ) {
// Couldnt determine attachment post id. Try to get id from thumbnail
$attachment_id = Patreon_Protect::getAttachmentIDfromThumbnailURL( $image );
//No go. Have to get out and serve the image normally
if ( $attachment_id == 0 OR !$attachment_id ) {
Patreon_Protect::readAndServeImage( $image );
Patreon-Connectには、サイトにアクセスするすべての人に悪用される可能性のあるローカルファイル開示の脆弱性が含まれていました。 この攻撃ベクトルを使用すると、攻撃者はwp-config.phpなどの重要な内部ファイルを漏洩する可能性があります。このファイルには、ナンスとCookieの生成に使用されるデータベースの資格情報と暗号化キーが含まれています。
悪用に成功した場合、このセキュリティ上の欠陥は、悪意のある人物による完全なサイト乗っ取りにつながる可能性があります。
ログインフォームに反映されたXSS
影響を受けるバージョン: <1.7.2
CVE ID: CVE-2021-24228
CVSSv3: 8.8
CWSS: 80.6
public static function processPatreonMessages() {
$patreon_error = '';
if ( isset( $_REQUEST['patreon_error'] ) ) {
// If any specific error message is sent from Patreon, prepare it
$patreon_error = ' - Patreon returned: ' . $_REQUEST['patreon_error'];
}
if ( isset( $_REQUEST['patreon_message'] ) ) {
return '<p class="patreon_message">' . apply_filters( 'ptrn/error_message', self::$messages_map[ $_REQUEST['patreon_message'] ] . $patreon_error ) . '</p>';
Patreon-ConnectはWordPressログインフォーム(wp-login.php)にフックし、ユーザーがPatreonアカウントを使用してサイトで認証できるようにします。 残念ながら、舞台裏のエラーロギングロジックの中には、ユーザーが制御する入力をサニタイズせずにログインページに反映させるものがありました。
この脆弱性を悪用するには、攻撃者は被害者をだまして、悪意のあるJavascriptコードを含むブービートラップされたリンクにアクセスさせる必要があります。 Javascriptは被害者のブラウザコンテキストで実行されるため、攻撃者はそのリンクに隠されたコードを調整して、このユーザーの権限で許可されていることを実行できます。
この攻撃が管理者に対して成功した場合、スクリプトはサイトを完全に乗っ取ることができます。
AJAXアクションに反映されたXSS'patreon_save_attachment_patreon_level'
影響を受けるバージョン: <1.7.2
CVE ID: CVE-2021-24229
CVSSv3: 8.8
CWSS: 80.6
$args = array (
'attachment_id' => $attachment_id,
'patreon_level' => $_REQUEST['patreon_attachment_patreon_level'],
'message' => $message,
);
echo self::make_image_lock_interface( $args );
public function make_image_lock_interface( $args = array() ) {
$interface = '';
$interface .= '<div class="patreon_image_lock_modal_content">';
$interface .= '<span class="patreon_image_lock_modal_close">×</span>';
$interface .= ' <form id="patreon_attachment_patreon_level_form" action="/wp-admin/admin-ajax.php" method="post">';
$interface .= '<h1 class="patreon_image_locking_interface_heading">Lock Image</h1>';
$interface .= '<div class="patreon_image_locking_interface_level">';
$interface .= '<span class="patreon_image_locking_interface_input_prefix">$<input id="patreon_attachment_patreon_level" type="text" name="patreon_attachment_patreon_level" value="' . $args['patreon_level'] . '" / ></span>';
プラグインはまた、AJAXフックを使用して、Patreonサブスクライバーが特定の添付ファイルにアクセスするために必要な誓約レベルを更新します。 このアクションには、「manage_options」権限を持つユーザーアカウント(つまり、管理者のみ)がアクセスできます。
残念ながら、このAJAXエンドポイントで使用されるパラメーターの1つは、ユーザーに出力される前にサニタイズされないため、それが表すリスクは、前述のXSSの脆弱性と同じです。
攻撃者がユーザーメタを上書き/作成できるようにするCSRF
影響を受けるバージョン: <1.7.0
CVE ID: CVE-2021-24230
CVSSv3: 6.5
CWSS: 42
public function toggle_option() {
if( !( is_admin() && current_user_can( 'manage_options' ) ) ) {
return;
}
$current_user = wp_get_current_user();
$option_to_toggle = $_REQUEST['toggle_id'];
$current_value = get_user_meta( $current_user->ID, $option_to_toggle, true );
$new_value = 'off';
if( !$current_value OR $current_value == 'off' ) {
$new_value = 'on';
}
update_user_meta( $current_user->ID, $option_to_toggle, $new_value );
}
一部のエンドポイントは、受信したリクエストがユーザーからの正当なアクションの後に送信されたことを検証しませんでした。これは、ナンスを使用して実行できます。 これらの保護されていないエンドポイントの1つにより、悪意のある個人は、一度アクセスすると被害者のアカウントに任意のユーザーメタデータを上書きまたは作成する、ブービートラップされたリンクを作成できました。
悪用された場合、このバグを使用して、影響を受けるユーザーアカウントの役割と特権を含む「wp_capabilities」メタを上書きできます。 これを行うと、基本的にサイトからロックアウトされ、有料コンテンツへのアクセスがブロックされます。
攻撃者がサイトをPatreonから切断できるようにするCSRF
影響を受けるバージョン: <1.7.0
CVE ID :CVE-2021-24231
CVSSv3: 6.5
CWSS: 26.1
if ( isset( $_REQUEST['patreon_wordpress_action'] ) AND $_REQUEST['patreon_wordpress_action'] == 'disconnect_site_from_patreon' AND is_admin() AND current_user_can( 'manage_options' ) ) {
// Admin side, user is admin level. Perform action:
// To disconnect the site from a particular creator account, we will delete all options related to creator account, but we will leave other plugin settings and post gating values untouched
$options_to_delete = array(
'patreon-custom-page-name',
'patreon-fetch-creator-id',
'patreon-creator-tiers',
'patreon-creator-last-name',
'patreon-creator-first-name',
'patreon-creator-full-name',
'patreon-creator-url',
'patreon-campaign-id',
'patreon-creators-refresh-token-expiration',
'patreon-creator-id',
'patreon-setup-wizard-last-call-result',
'patreon-creators-refresh-token',
'patreon-creators-access-token',
'patreon-client-secret',
'patreon-client-id',
'patreon-setup_is_being_done',
'patreon-setup-done',
'patreon-currency-sign',
);
// Ask the API to delete this client:
$creator_access_token = get_option( 'patreon-creators-access-token', false );
$client_id = get_option( 'patreon-client-id', false );
// Exceptions until v1 v2 transition is complete
$api_version = get_option( 'patreon-installation-api-version' );
if ( $api_version == '1' ) {
// Delete override - proceed with deleting local options
foreach ( $options_to_delete as $key => $value ) {
delete_option( $options_to_delete[$key] );
}
update_option( 'patreon-installation-api-version', '2' );
update_option( 'patreon-can-use-api-v2', true );
wp_redirect( admin_url( 'admin.php?page=patreon_wordpress_setup_wizard&setup_stage=reconnect_0') );
exit;
}
これは、同じ種類の攻撃(CSRF)であるという点で最後の脆弱性に似ていますが、管理者を対象としています。 この特定の攻撃ベクトルは、前のように機能します。 攻撃者は、特別に細工されたリンクにアクセスするために、ログインした管理者を取得する必要があります。
この特定のエンドポイントはサイトをPatreonから切断する可能性があるため、この攻撃ベクトルを標的とする攻撃者もそれを実行できます。これにより、新しいコンテンツがサイトに同期されなくなります。
タイムライン
- 最初の連絡の試み(失敗)–12月4日
- 2回目の連絡の試み–12月11日
- 著者は報告を認めます–12月15日
- バージョン1.7.0がリリースされました–1月5日
- 2つの追加のXSS問題を報告します–3月9日
- 著者は2番目のレポートを認めます–3月9日
- バージョン1.7.2がリリースされました–3月11日
結論
サイトで使用しているPatreon-Connectプラグインの現在のバージョンを確認し、1.7.2でない場合は、できるだけ早く更新することをお勧めします。
Jetpackでは、お客様のWebサイトがこれらのタイプの脆弱性から保護されるように努めています。 新しい脅威の一歩先を行くには、セキュリティスキャンと自動マルウェア除去を含むJetpackScanをチェックしてください。
クレジット
このセキュリティ開示は、George Stephanis、Fioravante Souza、Miguel Neto、Benedict Singer、MarcMontpasのおかげで可能になりました。