
CVE-2021-43408에 대한 기술 분석 및 개념 증명 익스플로잇으로, WordPress Duplicate Post 플러그인 버전 1.1.9의 SQL 인젝션 취약점에 대한 단계별 공격 가이드와 수정 조언을 포함합니다.
WordPress는 오픈소스 CMS(Content Management System) 소프트웨어로, 콘텐츠 관리 시스템입니다. HTML 코딩 언어를 사용하는 대신 WP는 PHP 프로그래밍 언어로 작성되었으며 MySQL 데이터 플랫폼을 사용합니다. WordPress는 프로그래머 Matt Mullenweg와 Mike Little이 창립했습니다. 현재 WordPress는 미국 캘리포니아주 샌프란시스코에 본사를 둔 Automattic 회사가 소유하고 있습니다.
WordPress의 Duplicate Post 플러그인은 1.1.9 이하 버전에서 SQL 인젝션 취약점이 발생합니다. 이 유형의 공격을 통해 공격자는 SQL 쿼리를 주입할 수 있으며, 데이터베이스의 리소스를 읽거나 수정, 심지어 삭제할 수 있습니다.
이 취약점은 Duplicate Post 플러그인의 기능을 사용할 권한이 있는 모든 인증된 사용자가 악용할 수 있습니다. 기본적으로 Admin만 이 권한을 가지지만, 권한이 수정될 경우 Editor, Author, Contributor, 심지어 Subscriber도 이 플러그인을 사용할 수 있습니다.
CVE-2021-43408은 "11/19/2021"에 발견되었으며 CVSS 점수 기준으로 HIGH 심각도로 평가되었습니다.

이 취약점의 핵심 원인은 사용자 요청으로부터 전송된 데이터가 SQL 실행에 사용되기 전에 sanitize되지 않기 때문입니다.
더 구체적으로는 post/handler.php 파일의 cdn_insert_post() 함수입니다.
function cdp_insert_post($id, $data, $times, $areWePro, $isChild = false, $p_ids = null, $site) {
// Get Wordpress database
global $wpdb;
// Create empty array for new id(s) and error(s)
$results = array('ids' => array(), 'error' => 0, 'counter' => 0);
// Get Counter value
$prefix = (($site != -1) ? $wpdb->get_blog_prefix($site) : $wpdb->get_blog_prefix());
$newestId = $wpdb->get_results("SELECT post_id FROM {$prefix}postmeta WHERE meta_key = '_cdp_origin' AND meta_value = {$id} ORDER BY post_id DESC LIMIT 1", ARRAY_A);
$id는 공격자가 통제할 수 있습니다.
$id 변수는 어떠한 sanitize 과정도 거치지 않은 채 SQL 쿼리를 포함한 함수로 전달됩니다. 이 함수는 WordPress Ajax wp_ajax_cdp_action_handling을 통해 호출됩니다.
param id는 cdn_sanitize_array 함수를 통해 전달되는 것을 볼 수 있습니다. 여기서 post의 데이터 필드는 sanitize_text_field 함수를 거치며, 데이터 문자열에서 모든 따옴표 '를 이스케이프합니다.

데이터 필드는
sanitize_text_field로 처리됩니다.
하지만 이 코드에는 Integer 필드(id 필드)의 데이터를 SQL 실행문에 전달할 때 취약점이 있습니다. 공격자는 이를 악용하여 이 필드의 값에 추가 SQL 문을 삽입할 수 있습니다. 따라서 SQL 쿼리를 제어하기 위해 공격자는 ' 문자만 피하면 됩니다.
1단계: Admin 사용자로 로그인한 후 Duplicate Post 플러그인 1.1.9 버전을 설치합니다. 이 플러그인은 사용자가 기존 게시물을 복제할 수 있도록 지원합니다.

2단계: Post 메뉴로 이동하여 게시물 하나를 선택하고 Copy 작업을 선택한 다음 Apply를 클릭합니다.

3단계: Setting: Default를 선택하고 Copy를 클릭합니다.

4단계: HTTP 요청을 인터셉트합니다. 여기서 주목해야 할 데이터 필드는 id이며, 이 필드의 데이터가 정수(Integer) 형식임을 확인할 수 있습니다.

5단계: SQL 인젝션 페이로드를 삽입하고 요청을 전송한 후 9초 후에 서버가 응답을 반환하는 것을 확인할 수 있습니다 -> SQL 인젝션 성공.
Payload: 1 and (select*from(select(sleep(9)))a)--

