ช่องโหว่ที่พบในปลั๊กอิน Patreon WordPress
เผยแพร่แล้ว: 2021-03-26ในระหว่างการตรวจสอบภายในของปลั๊กอิน Patreon สำหรับ WordPress ทีม Jetpack Scan พบจุดอ่อนหลายประการที่จะยอมให้ผู้อื่นเข้ายึดเว็บไซต์
ช่องโหว่เหล่านี้ถูกเปิดเผยต่อผู้สร้างปลั๊กอิน ซึ่งเปิดตัวเวอร์ชัน 1.7.2 ทันที ซึ่งแก้ไขปัญหาเหล่านี้ทั้งหมด หากคุณใช้ปลั๊กอินเวอร์ชันเก่า โปรดอัปเดตวันนี้!
อ่านรายละเอียดทางเทคนิคทั้งหมดต่อไป หากสิ่งนี้เกินหัวคุณอย่ากังวล เราขอเสนอ Jetpack Scan เพื่อจัดการกับการสแกนมัลแวร์และการอัปเกรดหรือการลบอัตโนมัติสำหรับคุณ
ทีมของเราระบุเวกเตอร์การโจมตีต่างๆ รวมถึงช่องโหว่ Local File Disclosure, Cross-Site Request Forgery (CSRF) และช่องโหว่ Reflected Cross-Site Scripting (XSS)
ช่องโหว่ Local File Disclosure เป็นข้อบกพร่องที่ผู้ไม่หวังดีสามารถใช้เพื่อเข้าถึงข้อมูลที่สำคัญได้ เช่น คีย์ลับของเว็บไซต์และข้อมูลประจำตัวของฐานข้อมูล ช่องโหว่ของ Cross-Site Scripting และ Cross-Site Request Forgery ที่สะท้อนให้เห็นเป็นปัญหาที่ทำให้ผู้โจมตีสามารถดำเนินการเฉพาะในนามของผู้ใช้ที่ไม่สงสัยโดยหลอกล่อให้คลิกลิงก์ที่เป็นอันตรายซึ่งสร้างขึ้นอย่างระมัดระวัง
หากถูกเอารัดเอาเปรียบ สิ่งเหล่านี้บางส่วนอาจทำให้บุคคลที่เป็นอันตรายเข้ายึดเว็บไซต์ที่มีช่องโหว่ได้
ช่องโหว่การเปิดเผยไฟล์ในเครื่อง
เวอร์ชันที่ได้รับผลกระทบ: < 1.7.0
รหัส CVE: 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 ซึ่งมีข้อมูลประจำตัวของฐานข้อมูลและคีย์การเข้ารหัสที่ใช้ในการสร้าง nonce และคุกกี้
หากใช้ประโยชน์ได้สำเร็จ ข้อบกพร่องด้านความปลอดภัยนี้อาจนำไปสู่การเข้ายึดเว็บไซต์โดยสมบูรณ์โดยผู้ไม่หวังดี
XSS สะท้อนบนแบบฟอร์มการเข้าสู่ระบบ
เวอร์ชันที่ได้รับผลกระทบ: < 1.7.2
รหัส CVE: 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 ที่เป็นอันตราย เนื่องจากจาวาสคริปต์ทำงานในบริบทของเบราว์เซอร์ของเหยื่อ ผู้โจมตีสามารถปรับโค้ดที่ซ่อนอยู่ในลิงก์นั้นเพื่อดำเนินการตามที่ผู้ใช้อนุญาต
หากการโจมตีนี้ประสบความสำเร็จกับผู้ดูแลระบบ สคริปต์สามารถเข้าควบคุมไซต์ได้อย่างสมบูรณ์
สะท้อน XSS ในการกระทำ AJAX 'patreon_save_attachment_patreon_level'
เวอร์ชันที่ได้รับผลกระทบ: < 1.7.2
รหัส CVE: 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 hook เพื่ออัปเดตระดับการจำนำที่สมาชิก Patreon ต้องการเพื่อเข้าถึงไฟล์แนบที่กำหนด การดำเนินการนี้สามารถเข้าถึงได้สำหรับบัญชีผู้ใช้ที่มีสิทธิ์ "manage_options" (เช่น เฉพาะผู้ดูแลระบบ)
ขออภัย พารามิเตอร์ตัวใดตัวหนึ่งที่ใช้ในจุดปลาย AJAX นี้ไม่ได้รับการฆ่าเชื้อก่อนที่จะพิมพ์กลับไปยังผู้ใช้ ดังนั้นความเสี่ยงที่แสดงจึงเหมือนกับช่องโหว่ XSS ก่อนหน้าที่เราอธิบายไว้
CSRF อนุญาตให้ผู้โจมตีเขียนทับ/สร้าง Meta . ของผู้ใช้
เวอร์ชันที่ได้รับผลกระทบ: < 1.7.0
รหัส CVE: 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 );
}
ปลายทางบางจุดไม่ได้ตรวจสอบคำขอที่ได้รับซึ่งส่งไปหลังจากการดำเนินการที่ถูกต้องจากผู้ใช้ ซึ่งคุณสามารถทำได้โดยใช้ nonce หนึ่งในอุปกรณ์ปลายทางที่ไม่มีการป้องกันเหล่านี้อนุญาตให้บุคคลที่มุ่งร้ายสร้างลิงก์ที่ติดกับดักซึ่งจะเขียนทับหรือสร้างข้อมูลเมตาของผู้ใช้ตามอำเภอใจในบัญชีของเหยื่อเมื่อเข้าชม
หากถูกโจมตี จุดบกพร่องนี้สามารถใช้เพื่อเขียนทับเมตา "wp_capabilities" ซึ่งมีบทบาทและสิทธิ์ของบัญชีผู้ใช้ที่ได้รับผลกระทบ การทำเช่นนี้จะเป็นการล็อกพวกเขาออกจากไซต์ ปิดกั้นไม่ให้เข้าถึงเนื้อหาที่ต้องชำระเงิน
CSRF อนุญาตให้ผู้โจมตีตัดการเชื่อมต่อไซต์จาก Patreon
เวอร์ชันที่ได้รับผลกระทบ: < 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 ผู้โจมตีที่กำหนดเป้าหมายเวกเตอร์การโจมตีนี้ก็สามารถทำเช่นนั้นได้ ซึ่งจะป้องกันไม่ให้เนื้อหาใหม่ถูกซิงโครไนซ์กับไซต์
เส้นเวลา
- ความพยายามในการติดต่อครั้งแรก (ไม่สำเร็จ) – ธ.ค. 4th
- ความพยายามในการติดต่อครั้งที่สอง – วันที่ 11 ธันวาคม
- ผู้เขียนรับทราบรายงาน – ธันวาคม 15th
- เวอร์ชัน 1.7.0 เปิดตัว – 5 มกราคม
- เรารายงานปัญหา XSS เพิ่มเติมสองฉบับ – 9 มีนาคม
- ผู้เขียนรับทราบรายงานที่สอง – 9 มีนาคม
- เวอร์ชั่น 1.7.2 เปิดตัว – 11 มีนาคม
บทสรุป
เราขอแนะนำให้คุณตรวจสอบเวอร์ชันปัจจุบันของปลั๊กอิน Patreon-Connect ที่คุณใช้ในเว็บไซต์ของคุณ และหากไม่ใช่ 1.7.2 ให้อัปเดตโดยเร็วที่สุด!
ที่ Jetpack เราทำงานอย่างหนักเพื่อให้แน่ใจว่าเว็บไซต์ของคุณได้รับการปกป้องจากช่องโหว่ประเภทนี้ เพื่อนำหน้าภัยคุกคามใหม่ ๆ หนึ่งก้าว ให้ลองดู Jetpack Scan ซึ่งรวมถึงการสแกนความปลอดภัยและการกำจัดมัลแวร์โดยอัตโนมัติ
เครดิต
การเปิดเผยข้อมูลความปลอดภัยนี้เกิดขึ้นได้เนื่องจาก George Stephanis, Fioravante Souza, Miguel Neto, Benedict Singer และ Marc Montpas