Xây dựng các ứng dụng bảo mật: nhất quán bản ghi

Bài này chúng tôi sẽ khảo sát nghiên cứu trạng thái ghi của lớp ứng dụng đã được nghiên cứu qua nhiều năm kinh nghiệm trong thực hiện phân tích bảo mật mã nguồn đối với hàng triệu dòng mã. Việc ghi chép hiệu quả thường bị bỏ qua bởi vấn đề bảo mật ứng dụng và việc minh chứng các ứng dụng có những lợi ích như thế nào từ việc phát hiện những tấn công thời gian thực. Ý tưởng bổ sung cho vấn đề thực hành được thảo luận cùng với khảo sát về một số rủi ro và giá thành có liên quan.

Vấn đề bảo mật

Các nhân viên bảo mật và phát triển phần mềm đều nhấn mạnh đến vấn đề tiến hành viết mã bảo mật. Thực vậy, các hãng đang tập trung vào hướng này bằng việc hứa hẹn sự bảo mật của các ứng dụng và cơ sở hạ tầng. Tuy nhiên, một số người lại coi sự kiểm soát truy vập và sự mã hóa có thể liên quan nhiều hoặc ít đến miền bảo mật ứng dụng. Trong thực tế, một số miền khác hoàn toàn chọn vẹn với sự bảo mật ứng dụng. Hướng dẫn OWASP Guide thường được coi như một điểm khởi đầu tốt cho việc nhận ra các miền này. Các nhóm phát triển trong lĩnh vực này cũng có rất nhiều kiến thức về các miền OWASP. Ví dụ, hầu hết các chuyên gia phát triển phần mềm đều hiểu rằng họ không nên viết mã cho các thuật toán mã hóa của riêng họ, vì một số thực sự có liên quan trong việc tạo các session ID của chính họ với chuẩn Pseudo Random Number Generator (ví dụ như java.util.Random). Một miền cụ thể mà có sự hợp nhất, bản ghi được thực hiện ghi chép và kiểm tra.

Phát hiện các tấn công mức ứng dụng

Số ít các ứng dụng trong môi trường công ty được xây dựng với khả năng phát hiện và thông báo các hành động nguy hiểm tiềm ẩn, mà thay vì đó chỉ nhờ vào các thiết bị cơ sở hạ tầng và các dụng cụ như tường lửa để thực hiện chức năng này. Tuy nhiên có một số tấn công sẽ vòng tránh được các cơ chế bảo vệ này: ví dụ tấn công từ chối dịch vụ DoS thực hiện từ bên trong mạng, hoặc các tấn công vòng tránh sự hợp lệ hóa trình khách vẫn xuất hiện khi hợp pháp hóa lưu lượng đối với mạng công ty. Rõ ràng một số hãng đưa ra khả năng có thể phát hiện xâm nhập và ngăn chặn các hệ thống ở mức mạng, nhưng với sự trông đợi ở khía cạnh các dịch vụ Web, sự phát triển của các mạng bên trong và sự truy cập rộng khắp toàn bộ danh giới của công ty, hệ thống IDS/IPS thực sự không thể đủ khả năng bảo vệ mạng của bạn khỏi các tấn công này.

Rõ ràng là không khả thi hoặc thậm chí mong muốn mỗi một ứng dụng đều có một cỗ máy phát hiện xâm nhập được xây dựng linh động theo bản thân nó. Quả thực, đó là một nhiệm vụ khó khăn trái với nguyên lý bảo mật ứng dụng “viết mã một cách an toàn thay vì bảo mật mã hoá”. Giải pháp có nhiều khả năng thực thi hơn là cải thiện hay nâng cao cơ chế phân tích file bản ghi đang tồn tại để nó có thể đọc được các file bản ghi theo thời gian thực và sử dụng các nguyên tắc thật thông minh, tìm kiếm các mẫu tấn công. Một vài công cụ đang tồn tại như SawmillNetwork Intelligence tuy không thiết kế một cách đặc biệt cho việc phân tích file bản ghi ứng dụng tùy chỉnh nhưng lại có khả năng cấu hình với những nhu cầu đó. Việc thảo luận sâu về các công cụ này nằm bên ngoài phạm vi của bài, trong bài này chúng tôi chỉ tập trung vào việc giới thiệu ứng dụng để đưa vào các công cụ đó. Những gì mà hầu hết các ứng dụng đang thiếu là một phương pháp nhất quán trong việc ghi chép, theo một định dạng chuẩn, có cơ chế phân tích để có thể phân tích chính xác ý nghĩa của các file bản ghi.

Sự thẩm định quyền

Nhiều ứng dụng sử dụng các mẫu bản ghi không nhất quán. Trong ví dụ dưới đây, chúng tôi sẽ thể hiện một ứng dụng Java mẫu ghi sai một yêu cầu (request) thẩm định quyền bằng Log4J. Lưu ý rằng trong ngôn ngữ lập trình C# .Net, một ví dụ tương tự đều có thể áp dụng bằng cách sử dụng công cụ Log4net. Trong bài này, chúng ta giả dụ một số kiểu công cụ bản ghi đã có sẵn để sử dụng – việc cấu hình và triển khai của công cụ như vậy không cần đề cập đến ở đây.

if (!request.password.equals(result.password))
{ //user supplied wrong p/w
log.debug("Invalid access attempt for " + request.usernane + "
with password " + request.password);
...

Ứng dụng tương tự cũng có thể có gì đó giống như vậy trong mô đun thẩm định quyền người dùng bằng cách sử dụng một giao diện khác:

if (myRequest.getPassword() != data.getPassword()) {
log.info("Login failed");
...

Khác hẳn với điểm yếu bảo mật trong việc ghi mật khẩu không được mã hóa, có một số vấn đề với kịch bản ở trên:

• Cả hai trường hợp đều sử dụng các mức bản ghi khác nhau (“debug” và “info”) để đăng ký một cố gắng thẩm định đã bị thất bại. Điều này làm cho mỗi một lập trình viên phải có những quyết định của riêng họ về sự nhạy cảm với một sự kiện bản ghi nào đó. Khi một lập trình viên cảm nhận được đây là một sự kiện gỡ rối thì họ sẽ có các phán đoán khác quan trọng hơn và ghi nó vào mức thứ hai “info”. Phụ thuộc vào sự bổ sung, điều này có thể có nghĩa rằng các sự kiện này được ghi vào những file bản ghi khác nhau. Sự tương quan và phân tích các cố gắng thẩm định thất bại là phức tạp nhất và có thể là bất khả thi.

• Mỗi trường hợp đều sử dụng một cú pháp khác nhau. Điều này bị phụ thuộc vào mỗi một tham chiếu cá nhân của người phát triển phần mềm về cách ghi. Nhiều chuyên gia phát triển phần mềm nghĩ việc ghi ở mức thấp (low-level) khi có một vấn đề mở rộng gỡ rối các thông báo và không thấy nhu cầu theo bất cứ một chuẩn cụ thể nào. Ví dụ này thể hiện đầu ra từ hai chuyên gia phát triển khác nhau; trong một ứng dụng thế giới thực, có đến hàng tá, hàng trăm, hoặc trong một số trường hợp có đến hàng nghìn người phát triển ứng dụng, thì việc sử dụng cách kiểm tra cú pháp của riêng họ đối với các thông báo này là một nhiệm vụ hết sức khó khăn. Với các ứng dụng có kích thước trung bình, họ sẽ rất khó khăn trong việc thực hiện phân tích ý nghĩa của file bản ghi bằng các cú pháp không nhất quán. Cũng không bảo đảm rằng sự phân tích sẽ duy trì ý nghĩa nếu các thông báo bản ghi thay đổi trong suốt các phát hành tương lai.

• Log4J, Log4Net và hầu hết các tiện ích có liên quan khác sẽ ghi một cách chính xác các thông báo mà người gọi gửi như các tham số. Nếu ứng dụng sử dụng một công cụ phân tích file bản ghi cho một cú pháp riêng nào đó (như “AppName, LogMessage, TimeStamp, Date” chẳng hạn) thì các chuyên gia phát triển phần mềm bắt buộc phải sử dụng cú pháp đó cho tất cả các sự kiện bản ghi. Nếu ở thời điểm nào đó, một công cụ phân tích mới được sử dụng hoặc cú pháp yêu cầu của công cụ đó thay đổi thì các chuyên gia phát triển cần phải cập nhật cuộc gọi đến công cụ ghi trong ứng dụng.

• Có điểm không đặc biệt ở đây là các sự kiện đã cho là bảo mật. Chúng đều được nhập vào trong các file bản ghi cùng với những thông tin gỡ rối xác thực (ví dụ như các biến không được đặt giá trị ban đầu), các lỗi logic trong (ví dụ như trường biểu mẫu không được điền) và các lỗi hệ thống khác (ví dụ như máy chủ cơ sở dữ liệu bị chết).

SQL Injection

Chúng ta hãy xem xét một ví dụ khác trong đó thường trình hợp lệ hóa đầu vào dưới dạng tìm ký tự đang được sử dụng cho SQL Injection. Lưu ý rằng ví dụ này sử dụng “blacklisting” hoặc “known-bad validation”, đây là phương pháp không đạt độ lý tưởng với việc hợp lệ hóa đầu vào nhưng lại là phương pháp thường được sử dụng:

if (!request.desc.indexOf(‘;’) != 0)
{ //possible SQL Injection character
log.fine("Possible SQL injection character ';' in request.desc value of " + request.desc);

Ở đây, những vấn đề phức tạp hay đơn giản liên quan đến tấn công nằm ở chỗ sự thận trọng của người phát triển phần mềm. Ngoài ra, không có một thông báo chuẩn nào để có thể tạo ra cơ chế dễ dàng trong việc tự động xác định sự hiện diện của một kiểu tấn công hợp lệ hóa đầu vào. Khi một ký tự mã độc có thể không vấn đề gì nhưng với vài trường hợp như vậy thì lại có thể là một vấn đề lớn. Không có khả năng tương quan giữa một vài tác động như vậy theo thời gian thực thì khả năng của hoạt động nhóm để đáp trả có thể bị cản trở một cách đáng kể.

Sự cần thiết trong việc nhất quán hóa việc ghi chép trở nên cực kỳ quan trọng trong ví dụ này. Hãy hình dung khi một kẻ tấn công đang tiến hành SQL Injection trên một số các trường khác nhau. Thông thường các trường này sẽ bản đồ hóa đến các đối tượng khác ở mức Data Access Object nằm ở tầng giữa (ví dụ như CustomerDAO.java, OrderDAO.java, …). Nếu những đối tượng này được viết bởi các nhà phát triển phần mềm khác nhau thì cú pháp trong các bản ghi sẽ phải chính xác. Điều này có thể cho ra một file bản ghi như thường lệ:

1st event:
Warning: SQL Injection detected: "Some description' OR 1=1 --;"
...
2nd event:
Possibility of malicious input, found character "-" in input field.

Đây là một cơ hội tốt để bất cứ ai cũng có thể thủ công hoặc tự động khai thác các trường và đưa ra một cảnh báo cho nhóm hoạt động rằng ứng dụng có thể đặt dưới tình trạng dễ bị tấn công. Kiểm tra đầu ra này, liệu công cụ phân tích có thể tương quan giữa hai sự kiện trong đó không hề biết chính xác về cú pháp mà mỗi nhà phát triển phần mềm sử dụng để mô tả cố gắng SQL injection như thế nào?

Phòng chống bằng cách sử dụng một bộ quản lý tập trung

Một phương pháp có thể giải quyết các vấn đề này là thiết kế một bộ quản lý bản ghi tập trung bên trong mức logic ứng dụng. Tạo một Singleton tĩnh (ví dụ “AppLog” chẳng hạn). AppLog sẽ đóng vai trò là một adapter giữa ứng dụng hiện hành và công cụ phân tích file bản ghi. AppLog, mức tối thiểu nhất, sẽ cung cấp 4 phương pháp truy cập chung dưới đây:

• AppLog.logDebugMessage(logMessage, logPriority, callingObject)
• AppLog.logSecurtyMessage(logMessage, logPriority, callingObject)
• AppLog.logBusinessLogicError(logMessage, logPriority, callingObject)
• AppLog.logSystemMessage(logMessage, logPriority, callingObject)

Cú pháp này yêu cầu các chuyên gia phát triển phần mềm phải chọn một kiểu bản ghi thay cho việc đơn giản chọn một ưu tiên, và tham số logPriority sẽ cho phép họ có khả năng chọn một mức ưu tiên. Tham số callingObject (của kiểu Object) sẽ cho phép AppLog tự động nối thêm dữ liệu vào lớp đối tượng gọi. Ngoài ra, mã của AppLog có thể thêm các tham số cú pháp được yêu cầu cho công cụ phân tích file bản ghi nào đó trước khi ghi vào file hoặc sử dụng các công cụ đang tồn tại như Log4J và Log4Net; các phân lớp AppLog có thể được xây dựng cho mỗi một công cụ phân tích. Khác với điều này, các chuyên gia phát triển phần mềm đơn lẻ lại không cần biết cú pháp yêu cầu cho các công cụ phân tích bên ngoài.

Chính vì vậy không thể giải quyết được các vấn đề đã được liệt kê ở trên. Hai chuyên gia phát triển phần mềm vẫn có thể gửi các thông báo khác nhau đến hàm logSecurityMessage(). Để giải quyết vấn đề này, các chuyên gia phát triển phần mềm cần phải thêm một số phương pháp nào đó vào AppLog cho các sự kiện bảo mật riêng, ví dụ như logInvalidAccessAttempt(user_id, timestamp, callingObject)logSQLInjectionAttempt(user_id, timestamp, maliciousChar, inputString, callingObject). Hàm này sẽ xây dựng một thông báo riêng và gọi hàm logSystemMessage. Sự kiện đã được ghi lại cuối cùng có thể như giới thiệu dưới đây:

"code:312,app:MyApp,event:Invalid_auth_attempt,user:admin,time:3713252,calling-obj:com.mycompany.package.MyClass"

Cú pháp này rất hữu ích đối với một công cụ phân tích file bản ghi nào đó, nếu công cụ thay đổi liên tục thì nó đơn giản chỉ là vấn đề thay đổi các chức năng bên trong AppLog hoặc sub-classing AppLog chứ không cần phải nâng cấp tất cả các cuộc gọi để ghi trong toàn bộ ứng dụng. Các chuyên gia phát triển phầm mềm từ nhiều mô đun khác nhau có cùng một cú pháp trong vấn đề tạo bản ghi cho việc ghi chép một cố gắng truy cập trái phép. Lấy lại ví dụ SQL injection, hai cuộc gọi khác loại đến một bộ tạo bản ghi trung tâm đều gọi logSQLInjectionAttempt và kết quả có thể như bên dưới:

1st event:
"code:312,app:MyApp,event:sql_injection_attempt,user:myuser1,mal-char:"-
",input-string:" Some description' OR 1=1 --; ",time:371245,calling-
obj:com.mycompany.DAO.CustomerDAO"


2nd event:

"code:312,app:MyApp,event:sql_injection_attempt,user:myuser1,mal-char:"-
",input-string:"An order name' OR 1=1 --;",time:371253,calling-
obj:com.mycompany.DAO.OrderDAO"

Các quản trị viên có thể định cấu hình cho một công cụ phân tích bản ghi để nó nhận ra rằng đã có hai hoặc nhiều cố gắng SQL injection từ một người dùng nào đó trong khoảng thời gian ngắn – một nhiệm vụ đã được tạo sự thuận tiện tuyệt vời bởi định dạng bản ghi nhất quán. Rõ ràng nếu ứng dụng bị tấn công giống như vậy thì có lẽ việc gửi một cảnh báo sau hai cố gắng SQL injection sẽ làm cho phân tích này gây bực mình cho người dùng hơn một tính năng bảo mật hiệu quả. Trong trường hợp đó, các quản trị viên có thể cấu hình một cách đơn giản công cụ để nó có thể gửi một cảnh báo với một số lượng lớn như 100 hoặc 1000 cố gắng injection chẳng hạn.

Logging – trách nhiệm của cơ sở hạ tầng?

Một số người sẽ cho rằng đây là một phán đoán hoàn toàn sai trong việc giải quyết vấn đề bản ghi lớp ứng dụng. Họ cho rằng chức năng này cần được quản lý ở một nơi nào đó bên trong cơ sở hạ tầng (như LDAP directory hoặc web-application firewall chẳng hạn). Trong khi đóng góp nhiều trong việc đẩy lùi các vấn đề có liên quan đến bảo mật từ các chuyên gia phát triển phần mềm một cách có thể thì lại không phải lúc nào cũng bảo mật ở mức cơ sở hạ tầng trong mỗi kiến trúc bản ghi các vấn đề (như một cơ sở dữ liệu chứng thực SQL sở hữu riêng cho một ứng dụng nào đó, quản lý session tùy chỉnh…). Ngoài ra còn có một số trường hợp không thể phát hiện các tấn công đó nếu không có việc áp dụng logic ứng dụng (ví dụ như ai đó đang nhập vào một giá trị sai cho ảnh “CAPTCHA” trong trang đăng ký). Cuối cùng chuyên gia phát triển phần mềm sẽ chia sẻ một số trách nhiệm cho việc nhận ra các sự kiện liên quan đến bảo mật cùng với cơ sở hạ tầng.

Đầu tư giá thành thấp

Khác với những chi phí của cơ chế tự phân tích file bản ghi, việc xây dựng kiểu chức năng ghi chép này khá đơn giản (góc độ chi phí). Việc bổ sung chỉ yêu cầu biên tập một chuẩn, xây dựng một công cụ adapter đơn giản cho chuẩn đó, tiếp đó là phổ biến chuẩn đó đến các chuyên gia phát triển phần mềm. Dù một công cụ phân tích file bản ghi sẽ không được sử dụng trong tương lai gần thì cần phải tăng cường thiết kế một ứng dụng cho phép nó lợi dụng chức năng này một cách nhanh chóng nếu được sử dụng. Thêm vào đó, chuẩn hóa sẽ khiến việc xem thủ công các bản ghi trở nên dễ dàng hơn. Hầu hết các chuyên gia phát triển phần mềm doanh nghiệp đều thừa nhận rằng họ chỉ sử dụng bản ghi lớp ứng dụng như một phương sách cuối cùng cho việc xử lý sự cố, việc phân loại thông qua chúng gây tốn nhiều thời gian và cồng kềnh do kích thước khổng lồ của chúng và cú pháp có hơi phần rối. Trong trường hợp phân tích thủ công, cần phải xem xét đến việc tạo các bản ghi theo một định dạng dễ phân tích cú pháp như CSV chẳng hạn để chúng có thể được phân tích bằng một ứng dụng bảng tính (spreadsheet) ưa thích nào đó.

Chi phí cho sự đơn giản cấu trúc

Một số chuyên gia phát triển phần mềm và kiến trúc sư chỉ ra rằng sẽ phải tốn một mức chi phí đáng kể và các rủi ro có liên quan với việc cải tiến và nâng cao mã. Nếu được bổ sung một cách đúng đắn và hợp lý thì việc ghi các bản ghi chuẩn hóa sẽ tối thiểu được sự ảnh hưởng về mặt chức năng và ít rủi ro vì nó chỉ thay đổi cú pháp của mã không chức năng (như việc ghi các cuộc gọi). Bản chất đó đã nói rằng, với các ứng dụng có rất nhiều dòng mã thì việc cải tiến mã đơn giản này lại là một công việc đòi hỏi phải có sự nỗ lực đáng kể. Trong trường hợp này, cần phải cân nhắc đến việc bắt đầu bằng cách bổ sung chuẩn mới cho các vùng nhậy cảm về bảo mật (ví dụ như thẩm định, chứng thực, quản lý session, hợp lệ hóa đầu vào, cấu hình và quản trị…) và bảo đảm rằng bất kỳ một mã mới được giới thiệu nào cần phải được đưa vào định dạng mới.

Thứ Ba, 25/03/2008 14:38
31 👨 82
0 Bình luận
Sắp xếp theo
    ❖ Tổng hợp