Các lỗ hổng thường gặp và cách thực hiện lập trình an toàn trong phát triển ứng dụng web (P3).

5. Mã hóa dữ liệu nhạy cảm

- Nguy cơ: Khi hệ thống bị tấn công và kẻ tấn công lấy được thông tin trong cơ sở dữ liệu, các dữ liệu nhạy cảm sẽ bị lộ nếu không được mã hóa hoặc mã hóa không an toàn. Note: các thông tin sau được cho là nhạy cảm: Thông tin về tài khoản/mật khẩu, thẻ ngân hàng, thông tin về tiền ...

- Phòng chống:

  • Mã hóa các dữ liệu nhạy cảm trong cơ sở dữ liệu.
  • Các hàm mã hóa 1 chiều phải có thê salt. Chú ý: salt phải đảm bảo tính ngẫu nhiên. Ví dụ 1:
  • Mật khẩu của người dùng được mã hóa trong cơ sở dữ liệu bằng hàm mã hóa 1 chiều. Kẻ tấn công lấy được mật khẩu đã mã hóa là: "QL0AFWMIX8NRZTKeof9cXsvbvu8=" và có thể tìm được mật khẩu chưa mã hóa là 123, thuật toán mã hóa là hash = base64(SHA1(pass)) bằng cách tìm kiếm trên Internet. Các mật khẩu phổ biến dễ bị dò ngược lại bằng phương pháp này.
  • Để sửa lỗi này ta cần thêm salt vào hàm mã hóa. Thay vì hash = encrypt(pass), hàm mã hóa sẽ chuyển thành hash = encrypt(salt + pass) và khi bị lộ hash cũng không thể tìm kiếm được trên Internet để tìm ra mật khẩu chưa mã hóa. Salt được sinh ngẫu nhiên cho từng user, và được lưu trong CSDL.

6. Kiểm tra quyền truy cập của người dùng

- Nguy cơ: Trong các hệ thống có phân quyền, mỗi người dùng chỉ được phép truy cập các chức năng, các dữ liệu mà mình được phép. Tuy nhiên, nếu việc kiểm tra quyền không được kiểm soát tốt thì người dùng có thể truy cập được các chức năng, các dữ liệu không được quyền.

- Phòng chống: Kiểm tra quyền trong từng request gửi lên server. Việc kiểm tra quyền gồm 2 nội dung kiểm tra là:

  • Người dùng có được phép thực thi chức năng theo request hay không?
  • Nếu người dùng được phép thực thi chức năng thì kiểm tra tiếp người dùng có được phép thao tác chức năng đó trên dữ liệu trong request hay không? Ví dụ 1: Hàm bên dưới mắc lỗi không kiểm tra quyền của người dùng, mà cho phép luôn quản trị khóa tài khoản người dùng với đầu vào là ID của người dùng được gửi từ client.
public String deleteFileofUser() {
    String strFileId = getRequest().getParameter("fileId");
    Long fileId = Long.parseLong(strFileId);
    doDeleteFileofUser(fileId);
    return SUCCESS;
}

Như vậy, bằng cách thay đổi ID của người dùng từ client, người quản trị này có thể khóa tài khoản của các người dùng mà mình không được phép quản lý. Để sửa lỗi này, ta cần kiểm tra quyền khóa của quản trị đối với người dùng này trước khi thực hiện khóa.

public String deleteFileofUser() {
    String strFileId = getRequest().getParameter("fileId");
    Long fileId = Long.parseLong(strFileId);
    if(checkLockPermission(userId)) {
        doDeleteFileofUser(fileId);
        return SUCCESS;
    } else {
        return ERROR;
    }
}