sách gpt4 ăn đã đi

Giải thích dự án về các lỗ hổng bảo mật phổ biến

In lại Tác giả: Tôi là chú chim nhỏ Thời gian cập nhật: 2023-04-19 06:31:20 25 4
mua khóa gpt4 giày nike

Bài viết này được lọc từ mô tả văn bản của bản ghi đệ trình của dự án nguồn mở RuoYi dựa trên từ khóa lỗ hổng|bảo mật|chặn. Nó nhằm mục đích giới thiệu cho bạn một số vấn đề bảo mật cần được chú ý trong quá trình phát triển dự án hàng ngày và cách giải quyết chúng.

Bảo mật dự án là vấn đề mà mọi nhà phát triển cần chú trọng. Nếu một dự án có quá nhiều lỗ hổng sẽ dễ bị hacker tấn công và rò rỉ thông tin người dùng. Bài viết này sẽ tổng hợp 3 trường hợp điển hình để giải thích các lỗ hổng bảo mật thường gặp và giải pháp sửa chữa nhằm giúp mọi người nâng cao hơn nữa nhận thức về bảo mật trong quá trình phát triển dự án.

  • Địa chỉ dự án RuoYi: https://gitee.com/y_project/RuoYi
  • Địa chỉ github của Blogger: https://github.com/wayn111, mời mọi người chú ý

1. Đặt lại mật khẩu người dùng

Có một giao diện để đặt lại mật khẩu người dùng trong dự án RuoYi. Mã trước khi gửi bản ghi dd37524b như sau:

                        
                          @Log(title = "Đăng nhập", businessType = BusinessType.UPDATE) @PostMapping("/resetPwd") @ResponseBody public AjaxResult resetPwd(SysUser user) { user.setSalt(ShiroUtils.randomSalt()); user.setPassword(passwordService.encryptPassword(user.getLoginName(), user.getPassword(), user.getSalt())); int rows = userService.resetUserPwd(user); if (rows > 0) { setSysUser(userService.selectUserById(user.getUserId())); return success(); } return error(); }

                        
                      

Có thể thấy giao diện này sẽ đọc thông tin người dùng đến. Sau khi đặt lại mật khẩu người dùng, cơ sở dữ liệu và bộ đệm sẽ được cập nhật dựa trên userId đến.

Một vấn đề bảo mật rất nghiêm trọng ở đây là tin tưởng một cách mù quáng vào thông tin người dùng đến. Nếu kẻ tấn công xây dựng một yêu cầu thông qua giao diện và đặt userId trong tham số người dùng đến thành userId của những người dùng khác, thì giao diện này sẽ khiến một số người dùng nhất định phải nhập Mật khẩu. thiết lập lại và do đó bị xâm phạm bởi những kẻ tấn công.

1.1 Quá trình tấn công

Nếu kẻ tấn công có userId và tên tài khoản đăng nhập của người dùng khác.

  1. Xây dựng yêu cầu đặt lại mật khẩu
  2. Đặt userId thành userId của người dùng khác
  3. Máy chủ thay đổi mật khẩu người dùng dựa trên userId đến.
  4. Đăng nhập bằng tài khoản người dùng mới của bạn và đặt lại mật khẩu
  5. Tấn công thành công

1.2 Cách giải quyết

Sau khi ghi lại cam kết dd37524b, mã được cập nhật như sau:

                        
                          @Log(title = "Mật khẩu đăng nhập", businessType = BusinessType.UPDATE) @PostMapping("/resetPwd") @ResponseBody public AjaxResult resetPwd(String oldPassword, String newPassword) { SysUser user = getSysUser(); if (StringUtils.isNotEmpty(newPassword) && passwordService.matches(user, oldPassword)) { user.setSalt(ShiroUtils.randomSalt()); user.setPassword(passwordService.encryptPassword(user.getLoginName(), newPassword, user.getSalt())); if (userService.resetUserPwd(user) > 0) { setSysUser(userService.selectUserById(user.getUserId())); return success(); } return error(); } else { return error("修改密码失败,旧密码错误"); } }

                        
                      

Giải pháp thực sự rất đơn giản. Đừng tin tưởng một cách mù quáng vào các tham số do người dùng truyền vào. Hãy lấy userId của người dùng hiện đang đăng nhập thông qua trạng thái đăng nhập. Đoạn mã trên lấy userId của người dùng hiện đang đăng nhập thông qua phương thức getSysUser() và sau đó đặt lại mật khẩu dựa trên userId.

2. Tải tập tin

Tải xuống tệp là một chức năng sẽ gặp trong mọi dự án phát triển web. Tôi tin rằng nó quen thuộc với mọi người. Logic tải xuống tệp của RuoYi trước khi gửi bản ghi 18f6366f như sau:

                        
                          @GetMapping("common/download") public void fileDownload(String fileName, Boolean delete, HttpServletResponse response, HttpServletRequest request) { try { if (!FileUtils.isValidFilename(fileName)) { throw new Exception(StringUtils.format( "Không thể thực hiện được ({}), không thể thực hiện được nữa.", fileName)); } String realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1); String filePath = Global.getDownloadPath() + fileName; response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); FileUtils.setAttachmentResponseHeader(response, realFileName); FileUtils.writeBytes(filePath, response.getOutputStream()); if (delete) { FileUtils.deleteFile(filePath); } } catch (Exception e) { log.error("Không tìm thấy tệp nào", e); } } public class FileUtils { public static String FILENAME_PATTERN = "[a-zA-Z0-9_\\-\\|\\.\一-\龥]+"; public static boolean isValidFilename(String filename) { return filename.matches(FILENAME_PATTERN); } }

                        
                      

Bạn có thể thấy rằng khi tải xuống một tệp trong mã, nó sẽ xác định xem tên tệp có hợp pháp hay không. Nếu không hợp pháp, nó sẽ nhắc rằng tên tệp ({}) là bất hợp pháp và không được phép tải xuống. của các từ. Thoạt nhìn, có vẻ như không có vấn đề gì. Tệp tải xuống trong dự án công ty của blogger cũng có mã tương tự. Nhập tên của tệp đã tải xuống, sau đó sau khi tìm thấy tệp cần tải xuống trong thư mục đã chỉ định, hãy ghi tệp đó vào máy khách thông qua luồng ngược.

Trong trường hợp này, chúng ta hãy xem thông tin mô tả của bản ghi gửi 18f6366f. Nếu không biết, bạn sẽ bị sốc. Hóa ra trước lần gửi này, đã có một lỗ hổng tải xuống tệp tùy ý trong dự án. Sau đây blogger sẽ giải thích cho bạn lý do tồn tại lỗ hổng tải file tùy ý.

2.1 Quá trình tấn công

Nếu thư mục tải xuống là /data/upload/.

  1. Xây dựng yêu cầu tải file
  2. Đặt tên tệp tải xuống thành: ../../home/important files.txt
  3. Máy chủ ghép tên tệp và thư mục tải xuống để có được đường dẫn đầy đủ của tệp đã tải xuống thực tế: /data/upload/../../home/important files.txt
  4. Vì tệp tải xuống có chứa .. các ký tự, logic nhảy lên thư mục sẽ được thực thi.
  5. Logic nhảy lên thư mục đã được thực thi và tệp được tải xuống thực tế là /home/tập tin quan trọng.txt
  6. Tấn công thành công

2.2 Cách giải quyết

Chúng ta hãy xem bản ghi cam kết 18f6366f chủ yếu làm gì. Mã như sau:

                        
                          @GetMapping("common/download") public void fileDownload(String fileName, Boolean delete, HttpServletResponse phản hồi, HttpServletRequest request) { try { if (!FileUtils.checkAllowDownload(fileName)) { ném ngoại lệ mới(StringUtils.format( "Tên tệp ({})Bất hợp pháp, không được phép tải xuống ", fileName)); } Chuỗi realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1); Chuỗi filePath = Global.getDownloadPath() + fileName; reply.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); FileUtils.writeBytes(filePath, reply.getOutputStream()); if (xóa) { FileUtils.deleteFile(filePath); } } Catch (Ngoại lệ e) { log.error("Không thể tải xuống tệp", e); * Kiểm tra xem tệp có thể được tải xuống không* * @param Resource Tệp sẽ được tải xuống* @return true Bình thường sai Bất hợp pháp*/ public static boolean checkAllowDownload(String Resource) { // Vô hiệu hóa mức nhảy thư mục if (StringUtils.contains(resource, "..")) { return false; } // Kiểm tra các quy tắc tệp được phép tải xuống if (ArrayUtils.contains(MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, FileTypeUtils.getFileType(resource ))) { return true; } // Các quy tắc tệp không được phép tải xuống return false; } } ... Chuỗi cuối cùng tĩnh công khai[] DEFAULT_ALLOWED_EXTENSION = { // ảnh "bmp", "gif", "jpg", "jpeg", "png", // word excel powerpoint "doc", "docx", "xls", "xlsx", "ppt" , "pptx", "html", "htm", "txt", // Tệp nén "rar", "zip", "gz", "bz2", // Định dạng video "mp4", "avi", "rmvb", // pdf "pdf" }; ... public class FileTypeUtils { /** * Lấy loại tệp* 

* Ví dụ : ruoyi .txt, return: txt * * @param fileName tên tệp * @return hậu tố (không bao gồm ".") */ public static String getFileType(String fileName) { int SeparatorIndex = fileName.lastIndexOf("."); if (separatorIndex < 0) { return ""; } return fileName.substring(separatorIndex + 1).toLowerCase();

Có thể thấy, trong submit record 18f6366f, phương thức FileUtils.isValidFilename(fileName) khi tải file đã được thay thế bằng phương thức FileUtils.checkAllowDownload(fileName). Phương pháp này sẽ kiểm tra xem tham số tên tệp có chứa .. để ngăn việc nhảy thư mục hay không, sau đó kiểm tra xem tên tệp có nằm trong danh sách trắng hay không. Điều này tránh các lỗ hổng tải tập tin tùy ý.

Truyền tải đường dẫn cho phép kẻ tấn công truy cập vào nội dung của các thư mục và tệp bằng cách thao tác các phần khác nhau của đường dẫn. Khi xử lý tải lên, tải xuống tệp và các hoạt động khác, chúng tôi cần xác minh nghiêm ngặt các tham số đường dẫn để ngăn chặn các lỗ hổng truyền tải thư mục.

3. Tham số sắp xếp truy vấn phân trang

Là một dự án quản lý nền, dự án RuoYi sử dụng truy vấn phân trang trong hầu hết mọi menu, do đó, lớp truy vấn phân trang PageDomain được gói gọn trong dự án và những lớp khác sẽ đọc tham số orderByColumn do máy khách truyền vào. Trước khi gửi bản ghi 807b7231, mã truy vấn phân trang như sau:

                        
                          public class PageDomain { ... public void setOrderByColumn(String orderByColumn) { this.orderByColumn = orderByColumn; } ... } /** * Biểu thức chính tả */ public static void startPage() { PageDomain pageDomain = TableSupport.buildPageRequest(); Integer pageNum = pageDomain.getPageNum(); Integer pageSize = pageDomain.getPageSize(); String orderBy = pageDomain.getOrderBy(); Boolean reasonable = pageDomain.getReasonable(); PageHelper.startPage(pageNum, pageSize, orderBy).setReasonable(reasonable); } /** * Phân quyền */ @RequiresPermissions("system:post:list") @PostMapping("/list") @ResponseBody public TableDataInfo list(SysPost post) { startPage(); List list = postService.selectPostList(post); return getDataTable(list); }

                        
                      

Như bạn có thể thấy, các truy vấn phân trang thường sử dụng trực tiếp phương thức startPage() được đóng gói và đặt trực tiếp thuộc tính orderByColumn của PageDomain vào PageHelper và cuối cùng nó sẽ được ghép vào câu lệnh truy vấn SQL thực tế.

3.1 Quá trình tấn công

Nếu kẻ tấn công biết tên bảng người dùng là người dùng, .

  1. Xây dựng một yêu cầu truy vấn phân trang
  2. đến orderByColumn Các thông số là 1; Người dùng DROP TABLE;
  3. SQL được thực thi thực tế có thể là: CHỌN * TỪ người dùng NƠI tên người dùng = 'admin' SẮP XẾP THEO 1; XÓA BẢNG người dùng;
  4. Thực thi SQL, Người dùng DROP TABLE; Hoàn thành, bảng người dùng sẽ bị xóa
  5. Tấn công thành công

3.2 Cách giải quyết

Sau khi gửi bản ghi 807b7231, các tham số sắp xếp đã được thoát. Mã mới nhất như sau.

                        
                          public class PageDomain { ... public void setOrderByColumn(String orderByColumn) { this.orderByColumn = SqlUtil.escapeSql(orderByColumn); } } /** * lớp công cụ thao tác sql* * @author ruoyi */ public class SqlUtil { /** * Chỉ hỗ trợ chữ cái, số, dấu gạch dưới, dấu cách, dấu phẩy và dấu thập phân (hỗ trợ sắp xếp theo nhiều trường) */ public static Chuỗi SQL_PATTERN = "[a-zA-Z0-9_\\ \\,\\.]+"; /** * Kiểm tra các ký tự để tránh bỏ qua việc tiêm*/ public static String escapeOrderBySql(String value) { if (StringUtils. isNotEmpty (value) && !isValidOrderBySql(value)) { ném UtilException mới("Các tham số không đáp ứng các thông số kỹ thuật và không thể truy vấn được" } giá trị trả về; } /** * Xác minh xem thứ tự theo cú pháp có tuân thủ đặc tả*/ public static boolean isValidOrderBySql(String value) { return value.matches(SQL_PATTERN);

                        
                      

Bạn có thể thấy rằng việc khớp thông thường được thực hiện đối với các chuỗi có thể được ghép nối sau thứ tự theo câu lệnh. Chỉ hỗ trợ các chữ cái, số, dấu gạch dưới, dấu cách, dấu phẩy và dấu thập phân (hỗ trợ sắp xếp nhiều trường). Điều này có thể tránh trật tự bằng cách được theo sau bởi các ký tự không hợp lệ khác, chẳng hạn như drop|if()|union, v.v., do đó tránh được các vấn đề về trật tự bằng cách tiêm.

SQL SQL là một trong những lỗ hổng phổ biến và nghiêm trọng nhất trong các ứng dụng web. Nó cho phép kẻ tấn công thực thi các lệnh SQL bất hợp pháp trong cơ sở dữ liệu bằng cách chèn các lệnh SQL vào các lần gửi biểu mẫu web. Không bao giờ tin tưởng vào dữ liệu đầu vào của người dùng, đặc biệt là khi ghép các câu lệnh SQL lại với nhau. Chúng ta nên lọc các tham số không thể kiểm soát do người dùng truyền vào.

4. Tóm tắt

Thông qua các trường hợp mã trong ba dự án RuoYi này, chúng ta có thể tóm tắt một số điểm cần chú ý trong quá trình phát triển dự án.

  1. Đừng tin tưởng một cách mù quáng vào các tham số do người dùng truyền vào. Cho dù bạn đang thay đổi mật khẩu hay tải xuống tệp, bạn không nên trực tiếp sử dụng các tham số do người dùng truyền vào để xây dựng các câu lệnh SQL hoặc đường dẫn nối. Điều này sẽ dẫn đến các lỗ hổng bảo mật như SQL SQL và truyền tải đường dẫn. Chúng tôi nên lấy ID người dùng thực hoặc các thông số khác dựa trên hoạt động kinh doanh thực tế trước khi tiếp tục.
  2. Các tham số SQL cần phải được thoát. Khi ghép các câu lệnh SQL, các tham số không thể kiểm soát được người dùng truyền vào phải được thoát để ngăn chặn việc tiêm SQL.
  3. Đường dẫn cần được xác minh. Khi xử lý các hoạt động như tải lên và tải xuống tệp, các tham số đường dẫn phải được xác minh để ngăn chặn các lỗ hổng truyền tải thư mục. Ví dụ: xác định xem đường dẫn có chứa .. tính cách.
  4. Quyền cần được đặt cho giao diện. Đối với một số giao diện nhạy cảm như đặt lại mật khẩu, chúng ta cần đặt quyền tương ứng để ngăn chặn người dùng truy cập trái phép.
  5. Ghi lại thông tin nộp hồ sơ. Khi ghi lại thông tin gửi bài, tốt nhất bạn nên mô tả chi tiết nội dung bài gửi này, chẳng hạn như lỗi đã được sửa hoặc tính năng mới được thêm vào. Điều này có thể hữu ích trong quá trình kiểm tra mã tiếp theo hoặc xem lại lịch sử cam kết của dự án.
  6. Kiểm tra mã thường xuyên. Với tư cách là người bảo trì dự án, chúng ta cần tiến hành kiểm tra mã thường xuyên để xác định các lỗ hổng có thể có trong dự án và sửa chữa chúng kịp thời. Điều này có thể đảm bảo tính bảo mật và mạnh mẽ của mã dự án ở mức độ lớn nhất.

Tóm lại, viết mã không chỉ là hoàn thành các yêu cầu. Chúng ta cũng cần chú ý hơn đến từng chi tiết, cảnh giác với các tham số do người dùng truyền vào, ghép nối các câu lệnh SQL một cách cẩn thận và xác minh nghiêm ngặt các đường dẫn. Kiểm tra mã thường xuyên có thể phát hiện và khắc phục các lỗ hổng của dự án càng sớm càng tốt, mang đến cho người dùng những sản phẩm an toàn và đáng tin cậy hơn. Tôi hy vọng rằng thông qua những trường hợp này, chúng tôi có thể nhắc nhở mọi người tăng cường hơn nữa nhận thức về bảo mật trong quá trình viết mã.

Bài viết này đã được giải thích. Cảm ơn bạn đã đọc. Bạn bè quan tâm có thể thích và theo dõi. Sự ủng hộ của bạn sẽ là động lực để tôi cập nhật.

Tài khoản công khai [waynblog] cập nhật các bài viết kỹ thuật mới nhất của các blogger hàng tuần, mời mọi người chú ý theo dõi.

Cuối cùng, bài viết về các lỗ hổng bảo mật phổ biến trong giải thích dự án kết thúc tại đây. Nếu bạn muốn biết thêm về các lỗ hổng bảo mật phổ biến trong giải thích dự án, vui lòng tìm kiếm các bài viết của CFSDN hoặc tiếp tục duyệt các bài viết liên quan. blog! .

25 4 0
tôi là một con chim nhỏ
Hồ sơ

Tôi là một lập trình viên xuất sắc, rất giỏi!

Nhận phiếu giảm giá taxi Didi miễn phí
Phiếu giảm giá taxi Didi
Chứng chỉ ICP Bắc Kinh số 000000
Hợp tác quảng cáo: 1813099741@qq.com 6ren.com
Xem sitemap của VNExpress