본문 바로가기
One-day 취약점 분석

[CVE-2024-6028] One-day 취약점 분석

by jh117jh 2024. 12. 16.
728x90

1. CVE-2024-6028이란?

CVE ID: CVE-2024-6028

 CVSS 심각도 점수: 9.8

 영향을 받는 버전: ≤ 6.5.8.3

 

WordPress용 Quiz Maker 플러그인은 사용자가 제공한 매개변수에서 이스케이프가 충분하지 않고 기존 SQL 쿼리에 대한 준비가 충분하지 않아 6.5.8.3 이전 모든 버전에서 ‘ays_questions’ 매개변수를 통한 시간 기반 SQL 주입에 취약하다. 이를 통해 인증되지 않은 공격자가 기존 쿼리에 추가 SQL 쿼리를 추가하여 데이터베이스에서 민감한 정보를 추출할 수 있다.

 

https://www.wordfence.com/threat-intel/vulnerabilities/wordpress-plugins/quiz-maker/quiz-maker-6583-unauthenticated-sql-injection-via-ays-questions-parameter

 

Quiz Maker <= 6.5.8.3 - Unauthenticated SQL Injection via 'ays_questions' Parameter

Did you know Wordfence Intelligence provides free personal and commercial API access to our comprehensive WordPress vulnerability database, along with a free webhook integration to stay on top of the latest vulnerabilities added and updated in the database

www.wordfence.com

 

2. 환경구축

XAMPP 3.3.0, Wordpress 6.6.2, Quiz Maker for Wordpress 6.5.8.3

Quiz Maker 플러그인을 활성화 후, 간단한 수학 퀴즈를 작성한다.

 

 

작성된 퀴즈의 Shortcode를 이용해 글을 배포해 준다.

 

3. 분석

우선 ‘ays_questions’ 매개변수를 통해 sql 인젝션이 가능하므로 해당 부분을 찾아보면

class-quiz-maker-public.php에서 찾을 수 있다.

‘ays_questions’ 매개변수에 관련된 sql문과 취약한 부분을 찾아보면

 

//4982라인
$questions_answers = (isset($_REQUEST["ays_questions"])) ? Quiz_Maker_Admin::recursive_sanitize_text_field( $_REQUEST['ays_questions'] ) : array();

//5130~5141라인
if (is_array($questions_answers)) {
                $quests = array();
                $questions_cats = array();
                $quiz_questions_ids = array();
                $question_bank_by_categories1 = array();

                foreach($questions_answers as $key => $val){
                    $question_id = explode('-', $key)[2];
                    $quiz_questions_ids[] = strval($question_id);
                }

                $questions_categories = $this->get_questions_categories( implode( ',', $quiz_questions_ids ) );
                // ......
                
                
//6902~6923라인
public static function get_questions_categories($q_ids){
        global $wpdb;

        if($q_ids == ''){
            return array();
        }
        $sql = "SELECT DISTINCT c.id, c.title
                FROM {$wpdb->prefix}aysquiz_categories c
                JOIN {$wpdb->prefix}aysquiz_questions q
                ON c.id = q.category_id
                WHERE q.id IN ({$q_ids})";

        $result = $wpdb->get_results($sql, 'ARRAY_A');
        error_log($sql);
        $cats = array();

        foreach($result as $res){
            $cats[$res['id']] = $res['title'];
        }

        return $cats;
}

 

$questions_answers 초기화 부분을 보면 Quiz_Maker_Admin::recursive_sanitize_text_field로 필터링되어 있다.

recursive_sanitize_text_field함수는 아래와 같이 정의되어 있다.

 

public static function recursive_sanitize_text_field($array) {
        foreach ( $array as $key => &$value ) {
            if ( is_array( $value ) ) {
                $value = self::recursive_sanitize_text_field($value);
            } else {
                $value = sanitize_text_field( $value );
            }
        }

        return $array;
    }

 

하지만 태그(<,>)나 인코딩 문자 개행 및 탭문자를 필터링할 뿐 다른 특수 문자를 필터링하지 않으므로 sql에 취약하다.

 

 

위 사진은 문제를 다 풀고 finish 버튼을 누른 패킷을 잡아 파라미터들을 확인해 본 것이다.

파라미터 중 취약점이 있는 ays_questions파라미터를 확인할 수 있으며

5136번 라인의 $question_id 초기화 부분은 ays_questions파라미터 형식을 보면 이해할 수 있다.

ays_questions파라미터는 ays_questions[ays-question-1]=3 값으로 전달되고 배열 형식으로 작성된다.

$question_id는 $questions_answers 즉, ays_questions의 키 값을 -를 기준으로 추출한 3번째 요소로 초기화된다.

현재 사진에서는 ays-question-1 → 1이 된다.

 

4. POC

이제 sql 문의 형식을 log를 이용해 살펴보면 $q_ids 즉, $question_id가 IN 연산자 뒤에 들어가는 걸 확인할 수 있다.

 

 

그러면 $question_id를 이용해 sql 뒤에 악성 쿼리를 삽입이 가능하다.

$question_id값에 1)+or+sleep(5 을 넣어보면

 

 

 

sleep함수가 정상적으로 들어가는 걸 확인할 수 있다.

 

5. 패치

$sql = $wpdb->prepare(
	            "SELECT DISTINCT c.id, c.title
	             FROM {$wpdb->prefix}aysquiz_categories c
	             JOIN {$wpdb->prefix}aysquiz_questions q
	             ON c.id = q.category_id
	             WHERE q.id IN ( $in_pholders )",
 		           array( ...$in_values )
 		        );

 

6.5.8.4 버전 이후부터는 sql문이 prepare 함수로 sql 인젝션을 방지하게 패치되었다.

728x90