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 (P5).

10. Sử dụng cookie an toàn

- Nguy cơ:

  • Khi người dùng không thiết lập thuộc tính "HTTPOnly" cho session cookie. Hacker có thể sử dụng mã javascript để đánh cắp session cookie của người dùng.
  • Với các ứng dụng web có sử dụng HTTPS cho các chức năng quan trọng như đăng nhập, sử dụng HTTP cho các chức năng khác, nhưng không thiết lập thuộc tính "secure" cho session cookie thì hacker nghe lén đường truyền để lấy cắp session cookie của người dùng, phiên làm việc của người dùng vẫn không được bảo vệ bởi cơ chế mã hóa của HTTPS.

- Phòng chống:

  • Yêu cầu thiết lập thuộc tính "HTTP Only cho session cookie". Ta có thể cấu hình bên phía Webserver. Ví dụ 1: Đối với tomcat, sửa file /tomcatdir/conf/context.xml, thêm thuộc tính "secure=true" vào khai báo kết nối HTTP như sau:
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" secure="true" />

Code java thiết lập thuộc tính secure cho session cookie:

response.setHeader("SET-COOKIE", "JSESSIONID=" + sessionid + ";secure");

11. Chuyển hướng và chuyển tiếp thiếu thẩm tra

- Nguy cơ:

  • Hacker có thể lừa người dùng redirect đến URI có nhiễm mã độc để cài phần mềm độc hại, hoặc lừa nạn nhân khai báo mật khẩu, hoặc những thông tin nhạy cảm khác.
  • Ví dụ 1: http://www.example.com/redirect.jsp?url=evil.com, ở đây "evil.com" chính là trang hacker muốn lừa người dùng chuyển đến.

- Phòng chống:

  • Hạn chế sử dụng việc chuyển hướng và chuyển tiếp đến URI khác.
  • Nếu sử dụng thì nên hạn chế truyền tham số là trang sẽ chuyến hướng đến mà nên fix trang sẽ được tham số đến.
  • Nếu yêu cầu bắt buộc phải truyền tham số trang redirect thì tham số cần phải được kiểm tra tính hợp lệ của nó thông qua whitelist các trang hợp lệ. Ví dụ 1: Trước khi chuyển tiếp hệ thống tới một url khác cần kiểm tra url đó có hợp lệ không, tạo 1 whitelist các url hợp lệ:
if (checkUrl(actionURL)) response.sendRedirect(actionURL);
else response.sendRedirect(urlError);
private boolean checkUrl(String url) {
    String[] urls = {"site1.com.vn", "site2.com.vn", "site3.com.vn"};
    if (urls.containsValue(url)) {
        return true;
    } else {
        return false;
    }
}

12. Để lộ dữ liệu của hệ thống

- Nguy cơ: Trên hệ thống tồn tại các chức năng cho phép kết xuất dữ liệu truy vấn, kết quả làm việc ra dưới dạng các file excel, tuy nhiên chứ năng này có các lỗ hổng sau có thể làm lộ dữ liệu của hệ thông:

  • File excel được lưu trữ trong thư mục con của thư mục ứng dụng.
  • File excel sau khi được người dùng tải về không được xóa.
  • Cho phép truy cập trực tiếp vào các file excel này mà không qua xác thực.
  • Ví dụ 1: Những đường link sau sẽ cho phép tải một file excel mà hệ thống đã xuất ra trước đó về mà không cần qua các bước xác thực: http://localhost:8080/ams/share/repor_out/expItems20190410090909.xls

- Phòng chống:

  • Các dữ liệu này lưu trong thư mục bên ngoài thư mục cài đặt web server, việc thự hiện download các dữ liệu này phải qua bước xác thực và tham số phải mã hóa. Ví dụ 1: Việc download file phải thực hiện qua action, việc kiểm tra này được kiểm tra quyền qua passport. Cấu hình trong struts
<action name="download" class="com.demmo.fwtest.database.DAO.Download method="downloadFile">
    <result type="stream" name="download">
        <param name="contentType">application/octect-stream</param>
        <param name="inputName">inputStream</param>
        <param name="bufferSize">1024</param>
    </result>
</action>

Action download

public String downloadFile() {
    try {
        RequestParameterObject rpo = QueryCrypt.decrypt(getRequest());
        String filename = FileUtils.getSafeFileName(rpo.getParameter("filename"));
        
        File file = new File(getRequest().getRealPath("/download/" + filename));
        inputStream = new FileInputStream(file);
        HttpServletResponse response = getResponse();
        response.setHeader("Cache-Control", "no-cache");
        response.setHeader("Cache-Disposition", "attachment; filename=\"" + filename + "\"");
        response.setHeader("Pragma", "public");
        response.setHeader("Expires", "0");
        response.setHeader("Content-Transfer-Encoding", "binary");
        response.getOutputStream().flush();
    } catch (Exception ex) {
        return "error";
    }
    return "download";
}

Gọi đến action download file từ file JSP kèm tham số tên file

document.location.href="${contextPath}/download.do?${filename}";