bookmark_borderMySQL issue – Type conversion – Bug or Feature?

Nay gặp một bug security củ chuối liên quan đến Laravel và MySQL.

Như mọi người đều biết thì hầu hết các framework hiện nay thằng nào cũng truy vấn CSDL dựa trên Query Builder thay vì phải viết raw query như hồi xưa. Một lợi ích của nó là cung cấp 1 phương thức giúp các dev binding dữ liệu vào câu query được an toàn. Nhưng cũng chính vì thế mà Query Builder trở thành 1 cái blackbox. Dev viết truy vấn CSDL bằng Query Builder mà không cần biết câu raw query thằng Builder đó sinh ra sẽ như thế nào (trừ những lúc cần thiết lắm thì mới phải trace debug xem hình thù nó ra làm sao). Và điều đó vô tình dẫn đến mấy cái lỗi trời ơi đất hỡi mà nếu không “ngẫu nhiên” được “trải nghiệm” thử thì cũng chẳng biết nó tồn tại.

Bắt đầu với câu truy vấn đơn giản như sau, khi muốn lấy ra record trong bảng usersid bằng 1:

select * from `users` where `id` = 1

Với Laravel, việc thực hiện điều trên trở nên kín đáo hơn:

// User.php
class User extends Model {
    public $table = 'users';
}

// Query user whose id equals to 1
$id = 1; 
$user = User::find($id);

// Dumping data
var_dump($user); // User object

Rồi, tiếp theo thử dự đoán kết quả cho câu sau:

// Query user whose id equals to something else
$id = '1+23456789';
$user = User::find($id);

// Guess the data ?
var_dump($user); // User object is still here

Điều gì đã xảy ra:

// Case 1
$id = 1;
$user = User::find($id); // => select * from `users` where `id` = '1' limit 1

// Case 2
$id = '1+23456789';
$user = User::find($id); // => select * from `users` where `id` = '1+23456789' limit 1

Như đã thấy, ở cả 2 trường hợp, dữ liệu binding vào câu query đều được Query Builder bao trọn trong dấu nháy đơn ( ' – single quote ). Và khi câu query này được send tới MySQL để thực hiện thì điều duy nhất mong muốn xảy ra ở đây là trường hợp 1 truy vấn được kết quả, trường hợp 2 phải gặp lỗi – do id là field có kiểu int.

Nhưng mà đời không như là mơ. Theo “quy tắc” của MySQL (tham khảo ở đây: https://dev.mysql.com/doc/refman/8.0/en/type-conversion.html), câu lệnh của trường hợp 2 vẫn thực hiện được:

-- This query is .. 
select * from `users` where `id` = '1+23456789' limit 1

-- .. becoming this .. 
select * from `users` where `id` = cast('1+23456789' as int) limit 1

-- .. and finally it turns into this. Bravo! 
select * from `users` where `id` = 1 limit 1

Give thanks to MySQL. You did a great job!

MySQL đã “tự ý” chuyển đổi chuỗi giá trị thành kiểu số, khiến cho câu truy vấn trở nên hợp lệ. Kết quả vẫn được trả về dẫu cho input đầu vào theo mắt thường thì rõ ràng sai rành rành. Việc kết hợp giữa cách binding dữ liệu của công cụ Query Builder nằm trong Laravel cùng với kỹ thuật Type conversion của MySQL đã làm nảy sinh 1 lỗi tiềm ẩn nên được chú ý trong thời gian tới.

bookmark_borderLet’s Encrypt for Custom Domain in Azure’s App Services

1. Đóng gói chứng chỉ SSL đã tạo bởi Let’s Encrypt

Sau khi tạo chứng chỉ SSL sử dụng Let’s Encrypt và muốn dùng để chứng nhận bảo mật lúc tạo Custom Domain cho Azure’s App Service, các file chứng chỉ cần được đóng gói lại bằng câu lệnh sau:

# Go to where Let's Encrypt keeps your certificate 
cd /etc/letsencrypt/live/linhntaim.com 

# Pack the certificate files and create the bundle 
openssl pkcs12 -export \ 
    -out bundle.pfx \ # Bundle file 
    -inkey privkey.pem \ 
    -in cert.pem \ 
    -certfile chain.pem \ 
    -password pass:%password% # Replace %password% with your desired password

2. Cài đặt chứng chỉ cho Custom Domain trong App Service

Sau khi thêm Custom Domain cho App Service, tiến hành cấu hình SSL cho custom domain vừa thêm.

Chọn Upload PFX Certificate:

azure_app_service_custom_domain_ssl_01

Tim và chọn file bundle.pfx (chứng chỉ đã được đóng gói) vừa tạo ở mục 1, đồng thời điền password đã dùng khi tạo file.

azure_app_service_custom_domain_ssl_02

Chọn Upload ở cuối màn hình là xong.