1. Fancy Product Designer
- 온라인에서 의류, 머그컵, 휴대폰 케이스 등을 사용자 맞춤형으로 디자인할 수 있게 해주는 Worpress 플러그인 [2]
2. 취약점
2.1 CVE-2024-51818 [3]
- 취약점은 class-wc-dokan.php의 get_products_sql_attrs() 함수에 존재
> 해당 함수는 class-product.php의 get_products()에 의해 호출
> Line13 : $attrs를 매개변수로 fpd_get_products_sql_attrs() 호출
- get_products_sql_attrs()
> Line23 : fpd_filter_users_select 값이 존재하고, -1이 아닌 경우 if문 실행
> Line24 : "user_id=" 문자열 뒤 strip_tags($_POST['fpd_filter_users_select'])를 추가한 결과를 $where 변수에 할당
- strip_tags()는 NULL bytes와 HTML 및 PHP 태그를 제거하는 함수로 SQL 공격을 방지하지 못함 [4]
> Line29~31 : $where 값은 get_products()의 $wpdb->get_results로 쿼리에 실행
inc/api/class-product.php, function get_products()
1 public static function get_products( $attrs = array(), $type = 'catalog' ) {
2
3 global $wpdb;
4
5 $defaults = array(
6 'cols' => '*',
7 'where' => '',
8 'order_by' => '',
9 'limit' => null,
10 'offset' => null
11 );
12
13 $attrs = apply_filters( 'fpd_get_products_sql_attrs', $attrs );
14
15 extract( array_merge( $defaults, $attrs ) );
16
17 $products = array();
18 if( fpd_table_exists(FPD_PRODUCTS_TABLE) ) {
19
20 $where = empty($where) ? $wpdb->prepare( 'WHERE type="%s"', $type) : $wpdb->prepare( 'WHERE type="%s" AND ', $type ) . $where;
21
22 if( !preg_match('/^[a-zA-Z]+\\s(ASC|DESC)$/', $order_by) )
23 $order_by = '';
24 $order_by = empty($order_by) ? '' : 'ORDER BY '. $order_by;
25
26 $limit = empty($limit) ? '' : $wpdb->prepare( 'LIMIT %d', $limit );
27 $offset = empty($offset) ? '' : $wpdb->prepare( 'OFFSET %d', $offset );
28
29 $products = $wpdb->get_results(
30 SELECT $cols FROM .FPD_PRODUCTS_TABLE." $where $order_by $limit $offset"
31 );
32
33 }
34
35 return $products;
36
37 }
woo/class-wc-dokan.php, function get_products_sql_attrs
1 public function get_products_sql_attrs( $attrs ) {
2
3 $where = isset( $attrs['where'] ) ? $attrs['where'] : null;
4
5 if( self::user_is_vendor() ) {
6
7 $user_ids = array(get_current_user_id());
8
9 //add fpd products from user
10 $fpd_products_user_id = fpd_get_option( 'fpd_wc_dokan_user_global_products' );
11
12 //skip if no use is set or on product builder
13 if( $fpd_products_user_id !== 'none' && !(isset( $_GET['page'] ) && $_GET['page'] === 'fpd_product_builder') )
14 array_push( $user_ids, $fpd_products_user_id );
15
16 $user_ids = join( ",", $user_ids );
17
18 $where = empty($where) ? "user_id IN ($user_ids)" : $where." AND user_id IN ($user_ids)";
19
20 }
21
22 //manage products filter
23 if( isset($_POST['fpd_filter_users_select']) && $_POST['fpd_filter_users_select'] != "-1" ) {
24 $where = "user_id=".strip_tags( $_POST['fpd_filter_users_select'] );
25
26
27 $attrs['where'] = $where;
28
29 return $attrs;
30
31 }
2.2 CVE-2024-51919 [5]
- 취약점은 class-pro-export.php의 save_remote_file() 함수와 fpd-admin-functions.php의 fpd_admin_copy_file() 함수에 존재
- save_remote_file()
> Line9 : $remote_file_url을 통해 원격 URL 값을 받아 fpd_admin_copy_file() 호출
- fpd_admin_copy_file()
> Line8 : basename($file_url)의 결과를 $filename에 할당
> Line10 ~ Line22 : 파일을 복사 또는 저장
> 파일에 대한 검사 없이 복사 또는 저장하므로 임의의 파일 업로드가 가능
pro-export/class-pro-export.php, function save_remote_file()
1 public static function save_remote_file( $remote_file_url ) {
2
3 $unique_dir = time().bin2hex(random_bytes(16));
4 $temp_dir = FPD_ORDER_DIR . 'print_ready_files/' . $unique_dir;
5 mkdir($temp_dir);
6
7 $local_file_path = $temp_dir;
8
9 $filename = fpd_admin_copy_file(
10 $remote_file_url,
11 $local_file_path
12 );
13
14 return $filename ? $unique_dir . '/' . $filename : null;
15
16 }
admin/fpd-admin-functions.php, function fpd_admin_copy_file()
1 function fpd_admin_copy_file( $file_url, $destination_dir ) {
2
3 if( empty( $file_url ) ) return false;
4
5 if( !file_exists($destination_dir) )
6 wp_mkdir_p( $destination_dir );
7
8 $filename = basename( $file_url );
9
10 if( function_exists('copy') ) {
11
12 return copy( $file_url, $destination_dir . '/' . $filename ) ? $filename : false;
13
14 }
15 else {
16
17 $content = file_get_contents( $file_url );
18 $fp = fopen( $destination_dir . '/' . $filename, 'w' );
19 $bytes = fwrite( $fp, $content );
20 fclose( $fp );
21
22 return $bytes !== false ? $filename : false;
23
24 }
3. 대응방안
- 취약점이 벤더사에 전달 되었으나, 최근 버전(6.4.3)까지 패치가 이루어지지 않은 상태
> 권고사항
ⓐ임의 파일 업로드 방지 : 안전한 파일 확장자만 허용하는 허용 목록(allowlist) 설정
ⓑ SQL 인젝션 대응 : 데이터베이스 쿼리의 철저한 입력 값 검증 및 적절한 이스케이프 처리
ⓒ 정기적인 보안 점검 : 플러그인 업데이트 상태 주기적 확인 및 새로운 취약점 발생 여부 모니터링
ⓓ 대안 플러그인 고려 : 개발사가 문제를 해결하지 않는 상황에서 보안이 보장된 대안 플러그인을 사용 고려
4. 참고
[1] https://patchstack.com/articles/critical-vulnerabilities-found-in-fancy-product-designer-plugin/
[2] https://fancyproductdesigner.com/
[3] https://patchstack.com/database/wordpress/plugin/fancy-product-designer/vulnerability/wordpress-fancy-product-designer-plugin-6-4-3-unauthenticated-sql-injection-vulnerability
[4] https://www.php.net/manual/en/function.strip-tags.php
[5] https://patchstack.com/database/wordpress/plugin/fancy-product-designer/vulnerability/wordpress-fancy-product-designer-plugin-6-4-3-unauthenticated-arbitrary-file-upload-vulnerability
[6] https://www.dailysecu.com/news/articleView.html?idxno=162891
'취약점 > Injection' 카테고리의 다른 글
Four-Faith 산업용 라우터 OS 명령 주입 취약점 (CVE-2024-12856) (0) | 2025.01.04 |
---|---|
WordPress WPLMS, VibeBP SQL Injection 취약점 (CVE-2024-56042, CVE-2024-56047, CVE-2024-56039, CVE-2024-56041) (0) | 2025.01.01 |
공항 보안 우회가 가능한 SQL Injection 취약점 (5) | 2024.10.14 |
Ivanti Endpoint Manager(EPM) SQL Injection (CVE-2024-29824) (1) | 2024.10.05 |
Ivanti Cloud Service Appliance OS Command Injection (CVE-2024-8190) (0) | 2024.09.23 |