Một phương pháp chống DDoS bằng xFlash

Ý tưởng

Dựa vào gợi ý của Amit Klein:

Notice the first limitation of the technique - it states that no raw CR and LF can be placed in the body section. This means that the technique cannot be used to send (POST) requests whose body complies with the "multipart/form-data" content-type format (this format uses raw CRs and LFs to mark headers and boundaries). In other words, a (POST) request whose body is a valid "multipart/form-data" stream is guaranteed (as far as today's knowledge extends) not to be sent from a Flash player. Web application authors can therefore use HTML forms whose ENCTYPE attribute is set to "multipart/form-data", and enforce that the submission contains a valid multipart/form-data body. Once these mechanisms are in place, and a request passes through, it is known not to originate from a Flash player, so the attack
described here is irrelevant.
Gợi ý ở trên có thể được diễn giải như sau:
  • Cách thức browser xử lí các HTML form có enctype = "multipart/form-data" và enctype = "application/www-urlencoded" (default) hoàn toàn khác nhau. Điểm khác nhau đặc trưng là khi submit (nghĩa là tạo ra POST request) form "multipart/form-data", browser sẽ tự động set Content-type là "multipart/form-data", còn khi submit các form khác, browser sẽ sử dụng Content-type là "application/www-urlencoded".
  • Flash (với các hàm thường được sử dụng để DDoS như LoadVars, GetURL hay SendtoURL, etc...) không thể gửi POST request theo định dạng "multipart/form-data". Đây chính là "gót chân Asin" của Flash.
  • Do đó nếu bằng một cách nào đó, ta có thể set tất cả các form thành enctype = "multipart/form-data", nghĩa là ép tất cả POST request có Content-type là "multipart/form-data", ta sẽ có thể phát hiện ra những POST request xuất phát từ Flash, vốn dĩ luôn có Content-type là "application/www-urlencoded".
Hiện thực

Để hiện thực hóa ý tưởng này, ta cần phải có một cách nào đó biến tất cả các HTML form thành enctype = "multipart/form-data", rồi sau đó phải chỉnh sửa lại server-side code để xử lí các form này (tin vui: thử nghiệm với một vài ngôn ngữ lập trình phổ biến như PHP, Java và Ruby, tôi thấy rằng không cần phải chỉnh sửa server-side code, các ngôn ngữ này đều có cách thức xử lí giống nhau với hai loại enctype của HTML form).

Vậy nhiệm vụ còn lại là điều chỉnh HTML form. Cách dễ thấy nhất là sửa code HTML. Phần còn lại của bài này tôi trình bày một cách khác, không cần chỉnh sửa code HTML. Đó là sử dụng output filter của Apache 2.x.

Ý tưởng cơ bản là triển khai một cái reverse proxy bằng Apache 2.x, đứng trước tất cả các server cần được bảo vệ khỏi xFlash. Trên cái reverse proxy đó, ta sẽ sử dụng một output filter module làm nhiệm vụ tự động thêm attribute enctype="multipart/form-data" vào tất cả các HTML form mà nó thấy.

Ban đầu tôi tính viết riêng một cái Apache 2.x module để làm chuyện này, nhưng rồi vô tình phát hiện ra có sẵn một module đã làm chuyện đó rồi. Đó là module mod_line_edit:
mod_line_edit is a general-purpose filter for text documents. It operates as a simple on-the-fly line editor, applying search-and-replace rules defined in a configuration or .htaccess file.
Để sử dụng mod_line_edit, trước tiên bạn cần phải biên dịch nó. Có hai cách biên dịch: biên dịch mod_line_edit thành một module tĩnh hoặc thành một module động (DSO). Nói chung để tối ưu hóa tốc độ xử lý, nên biên dịch mod_line_edit thành một module tĩnh theo cách sau đây:

server$ cd /usr/local/src
server$ wget http://www.tux.org/pub/net/apache/dist/httpd/httpd-2.2.4.tar.gz
server$ wget http://apache.webthing.com/mod_line_edit/mod_line_edit.c
server$ tar -xzf httpd-2.2.4.tar.gz

server$ mkdir -p httpd-2.2.4/modules/line_edit
server$ cp mod_line_edit.c httpd-2.2.4/modules/line_edit
server$ cp httpd-2.2.4/modules/echo/Makefile.in httpd-2.2.4/modules/line_edit
server$ cd httpd-2.2.4/
server$ "./configure" \
"--prefix=/opt/httpd" \
"--with-module=line_edit:mod_line_edit.c"

Cấu hình mod_line_edit cực kì đơn giản. Đầu tiên thêm hai dòng này vào httpd.conf để kích hoạt mod_line_edit:
FilterProvider textedit line-editor resp=Content-Type $text/
FilterChain textedit
Để mod_line_edit tự động thêm attribute enctype="multipart/form-data" vào tất cả các HTML form, thêm dòng sau đây vào nơi thích hợp (virtual host, location, etc...)
LERewriteRule '(<>' '$1 enctype="multipart/form-data">' Ri
Rồi xong, tất cả các form HTML của bạn sẽ tự động có enctype = "mutilpart/form-data". Nghĩa là POST request của bạn sẽ luôn có Content-type là "multipart/form-data".

Việc còn lại là cấu hình mod_security để nó phát hiện và loại bỏ các POST request có Content-type là "application/www-urlencoded" xuất phát từ xFlash. Tôi dành phần này lại cho các bạn tự làm.

Ưu điểm và nhược điểm


Phương thức mà tôi trình bày ở trên có những ưu điểm nhất định so với các phương thức phổ biến hiện nay:
  • Thứ nhất, do phương thức này đánh vào "gót chân Asin" của xFlash nên bạn không cần thay đổi cấu hình mà vẫn có thể phát hiện được xFlash dẫu kẻ tấn công có thay đổi nơi chứa xFlash hay thay đổi mục tiêu tấn công.
  • Thứ hai, nếu áp dụng theo mô hình reverse proxy, bạn sẽ có thể cùng một lúc bảo vệ được nhiều web-server bên trong khỏi xFlash, rất thích hợp với các hosting provider.
Tuy vậy, phương thức này cũng có những nhược điểm:
  • Thứ nhất, nó chỉ chống được thế hệ xFlash hiện tại. Theo nghiên cứu của riêng tôi, Flash, cụ thể là Flash Player 9 với ActionScript 3, cực kì nguy hiểm. Cách làm này sẽ không thể chống được thế hệ xFlash mới được phát triển dựa trên tính năng của ActionScript 3. Ngoài ra, nếu kẻ tấn công biết cách khai thác các lỗ hổng của Flash 9 trở về trước, phương thức này cũng sẽ trở nên vô tác dụng.
  • Thứ hai, nó chỉ phát hiện và chống được POST request từ xFlash. Theo anh con-ma-le cho biết, một số biến thể xFlash hiện tại chỉ chơi GET request mà thôi.
  • Thứ ba, đối với những website có áp dụng AJAX, phương thức này có khả năng sẽ gây ra false positive. Lý do là XMLHTTPRequest của Javascript cũng gửi POST request có Content-type là "application/www-urlencoded". May mắn là tất cả các AJAX framework mà tôi biết đều có khả năng thêm custom header vào HTTP request, do đó bạn có thể nhìn vào header này để phân biệt giữa xFlash và AJAX.
  • Thứ tư, với cái rule của mod_line_edit ở trên, website của bạn có nguy cơ không còn tuân theo chuẩn của W3C nữa. Ví dụ như nếu một webpage của bạn đã có sẵn enctype = "multipart/form-data", khi mod_line_edit thêm vào một attribute tương tự, webpage này sẽ không còn đúng chuẩn W3C.
Kết luận

Phương thức này không phải là "silver bullet" có thể giải quyết dứt điểm xFlash. Tuy vậy nó cũng có khả năng hạn chế được sức tàn phá của thế hệ xFlash hiện tại. Tôi nghĩ chỉ có hai cách có thể giải quyết dứt điểm xFlash:
  • Không sử dụng Flash. Nếu bạn hiểu rõ Flash nguy hiểm đến cỡ nào, hoặc nếu bạn tin tưởng tôi, tôi khuyên bạn không nên sử dụng Flash hoặc it nhất mặc định là không cho chạy Flash, rồi có thể enable theo từng website cụ thể. NoScriptFlashBlock có thể giúp bạn làm chuyện này dễ dàng!
  • Đừng cố chống xFlash bằng cách nhìn vào các đặc trưng của nó. xFlash hoàn toàn có thể tạo ra những request giống y những request hợp lệ. Hãy chống xFlash như chống các loại DDoS khác, nghĩa là: a) đầu tư vào cơ sở hạ tầng, bao gồm hệ thống server, đường truyền và con người; b) tối ưu hóa hệ thống, đảm bảo tốc độ xử lí tốt nhất với chi phí bỏ ra; c) thiết kế hệ thống thật scalable, bởi xét cho cùng, bị xFlash tấn công cũng tương tự như lượng user của bạn tăng lên đột biến.

Comments

conmale said…
Một nhận định rất lý thú :).

Hơn một năm nay chưa hề thấy x-flash POST tấn công HVA có lẽ không phải do những điều mrro phát hiện mà do tính nặng nề của nó.

Nói về phương diện cản như mrro đưa ra, chắc chắn dùng x-flash POST sẽ không đi quá tầng apache được. Bởi thế, ý định DDoS để tăng server load (vì tạo truy vấn đến CSDL như HVA bị ngày trước) thì chắc chắn sẽ không được. Tuy nhiên, nói trên bình diện bị DDoS thuần túy thì băng thông, máy chủ và chính apache vẫn bị trì trệ nếu như số lượng request đủ nhiều. Giả sử, nếu một số lượng người dùng cùng được huy động để load x-flash vào tạo khoảng 10 ngàn SYN 1 giây thì server sẽ cực kỳ mệt nhọc vì chính kernel điều tác memory để xử lý cũng đã vất vả. Nếu chỉ để một mình apache gánh vác phần "inline edit" luôn thì nguy cơ bị cạn kiệt tài nguyên càng nhanh nữa.

Nói chung, chống DDoS ở bất cứ dạng nào cũng nên trải dài từ tầng thấp nhất lên tầng cao nhất. Tài nguyên cho hệ thống cần được trang bị đầy đủ. Có lẽ, cân bằng tải giữa nhiều servers là một giải pháp xem ra là khả thi nhất hiện nay. Tuy nhiên, không phải ai cũng có điều kiện tài chính để làm được điều này.

Thân mến.
Anonymous said…
Flash có thể tạo cả 1 socket thông qua XMLSocket Class đó mrro à. Chẹp nếu mà kẻ tấn công dùng cả thứ này thì tớ tin là nó còn ác hơn là dùng các hàm getURL, LoadVariable .v.v. nhiều rất nhiều vì chúng trong chỉ truy cập mà còn dội cả packet vào server.
Anonymous said…
conmale: hoàn toàn đồng ý với ý kiến của hai anh. Như em đã nói trong bài viết của mình, phương thức này không phải là silver bullet, có thể giải quyết dứt điểm xFlash. Ưu điểm lớn nhất của nó là có thể phát hiện ra được xFlash bất kể thằng xFlash có thay hình đổi dạng đến cỡ nào (ý em là thế hệ xFlash gửi POST request như hiện nay).

nohat: tôi biết rõ ActionScript 3 nguy hiểm cỡ nào và trong bài viết của tôi cũng có đề cập đến điểm này. Phương thức này chỉ có thể chống lại đám xFlash hiện tại thôi, còn nếu kẻ tấn công cố ý khai thác những tính năng mới của ActionScript 3 thì phương thức này sẽ hoàn toàn bó tay. BTW, XMLSocket không phải là tính năng nguy hiểm nhất của ActionScript 3 đâu.

-Thai