PDA

View Full Version : Gửi các header của HTTP request bằng ActionScript trong Flash



vietanh143
19-10-2007, 08:49 PM
Bài viết này sẽ trình bày cơ chế dùng để gửi các HTTP request bất kì bằng ActionScript trong Flash. Hậu quả về khía cạnh bảo mật của kỹ thuật này cũng được bàn đến trong đây

Thông tin về Flash
==========================
Flash Player là môt tiện ích phụ trợ (add-on) rất phổ biến ,dùng cho trình duyệt Web , do Adoble đưa ra (thật ra thì ban đầu hãng Macromedia phát minh ra Flash, sau này được Adobe mua lại). Bài viết sẽ nhắm đến Flash ở phiên bản 7 và 8, cùng với hầu như 94% các máy tính để bàn có kết nối Internet (theo NPD Online Survey cung cấp vào tháng 4/2006, trích ở website của Adobe [1],[2]). Các phim dạng flash (flash movies) được truyền tải theo định dạng SWF (ShockWave File). Adobe đã phát triển một ngôn ngữ rất mạnh và giống như Javascript gọi là ActionScript. Ngôn ngữ này (ActionScript) cho phép khả năng dùng nó để soạn thảo các chương trình nhỏ ( Script ) chạy bên trong Flash . Một trong những đặc điểm thú vị của ActionScript là khả năng gửi HTTP request đến những site thứ ba ,thông qua trình duyệt đang chạy ActionScript này. Chính đặc điểm này làm cho Flash trở thành góc độ bảo mật thú vị. Với Flash có thể sửa đổi đươc (nội dung) các yêu cầu (request) gửi đến môt site thứ ba , trong khi các 'STANDARD' JavaScript không làm đươc như vậy . Khả năng gửi các HTTP header cùng với HTTP request chính là điểm quan trọng đặc biệt của Flash.


Gửi các HTTP header bằng Flash
================================================
Mã ActionScript 2.0 dưới đây sẽ thực hiện việc gửi một request dạng GET (giả sử đến website http://www.vuln.site/some/page.cgi?p1=v1&p2=v2) cùng với một HTTP header bất kì (Foo:Bar). Mã này hoạt động trong Flash 7 và 8 (cũng như là Flash 6)

Code:

var req:LoadVars=new LoadVars();
req.addRequestHeader( "Foo", "Bar" );
req.send( "http://www.vuln.site/some/page.cgi?p1=v1&p2=v2",
"_blank", "GET" );



Đoạn mã dưới đây cũng tương tự như trên nhưng với request dạng POST (cùng URL và tham số là a=b&c=d)

Code:

var req:LoadVars=new LoadVars();
req.addRequestHeader( "Foo", "Bar" );
req.decode( "a=b&c=d" );
req.send( "http://www.vuln.site/some/page.cgi?p1=v1&p2=v2",
"_blank", "POST" );



(chú ý: phương thức LoadVars.decode() được bổ sung trong Flash 7, nếu không dùng phương thức này ta cũng có thể tự thực hiện, ở Flash 6 thì làm khác nhau một chút).

Đối tượng Flash nằm trong trình duyệt thực hiện việc gửi request, đồng thời nó cũng gửi kèm theo cookie (giống như trình duyệt vẫn làm khi gửi request). Flash cũng gửi User-Agent của trình duyệt cùng với mọi header chuẩn khác. Nó cũng hỗ trợ liên kết HTTPS.

Các công việc trên đã thực hiện thành công ở Microsoft IE 6.0, Microsoft IE 6.0 SP2 và Firefox 1.5.0.4, các trình duyệt đó đều chạy Flash 8.0.22.0 và Flash 7.0.19.0

Trong IE, lời gọi hàm addRequestHeader sẽ thay thế giá trị các header thông thường của trình duyệt, bao gồm cả Referer và User-Agent. Trong Firefox 1.5.0.4, khi dùng các header đó trong hàm addRequestHeader thì chúng (header) sẽ được đưa vào cuối sector header của HTTP request

Code:

// tạo một header UA trong IE 6.0 SP2 và 2 header UA trong FF 1.5.0.4
req.addRequestHeader("User-Agent","Hacker/1.0");

// tạo một header Referer trong IE 6.0 SP2 và 2 header Referer trong FF 1.5.0.4
req.addRequestHeader("Referer","http://somewhere/");



Cũng có thể thay giá trị của nhiều header quan trọng khác trong IE bằng cách thêm dấu hai chấm ( : ) sau tên header (kĩ thuật này sẽ mô tả ở [3] trong nội dung XmlHttpRequest)

Code:

req.addRequestHeader("Host:","foobar.site");



Tuy nhiên cách này sẽ không làm được trên Firefox 1.5.0.4

Chú ý: khi URL truy cập đến là nằm trong cùng domain với Flash, ta có thể dùng LoadVars để đọc dữ liệu HTTP response, thấy rõ rằng cách dùng LoadVars là điểm cơ bản trong nhiều framework dạng AJAX mà dựa trên Flash (tựa như đối tượng XmlHttpRequest trong Javascript)


The security implications
========================

Khả năng một kẻ tấn công buộc trình duyệt của nạn nhân gởi HTTP request chứa các header bất kì đến các site khác đã tạo ấn tượng mạnh đến sự hiểu biết về bảo mật ứng dụng web của chúng tôi - kể cả việc đánh giá hiện tượng liên quan bảo mật lẫn tính minh xác của một số cơ chế bảo mật.

Điều quan trọng là phải hiểu những cách tấn công được mô tả ở đây không phải là tấn công cross-site scripting, không phải dạng cross-site-scripting (nói một cách chính xác) mà cũng chẳng phải dạng xâm phạm tín thực liên vùng (cross-domain trust) trong object của Flash hoặc giữa các Flash object và các trang nhúng HTML

Sự thật thì đối tượng Flash có thể gửi request đến bất kì URL nào và với bất kì HTTP header nào mà kẻ tấn công muốn. Vấn đề chính là điều này, nó cho phép kẻ tấn công gửi một liên kết (đến một trang HTML có nhúng đối tượng Flash, hay đến thẳng đối tượng Flash nằm trên website của kẻ tấn công), liên kết này cho phép đối tượng Flash sẽ chạy trên trình duyệt của nạn nhân. Chính đối tượng Flash này sẽ gửi HTTP request (cùng với các HTTP header mà kẻ tấn công đã chọn trước) đến website mong muốn và điều này sẽ làm hại đến trình duyệt (của nạn nhân)

Nói cách khác, nhiều nhà phát triển phần mềm (và cũng có thể là các nhà nghiên cứu bảo mật) luôn cho rằng hầu hết các HTTP header không thể bị kẻ tấn công thay đổi bằng một giá trị bất kì. Bài viết sẽ chỉ ra sự sai lầm và cũng là lỗi trong cách hiểu này

VD 1: header "Expect"
------------------------------------

Trong [4], một lỗi nằm trong trong Apache 1.3.34, 2.0.57 và 2.2.1 xem là nguy hiểm vì có thể chèn dữ liệu HTML vào trong header Expect. Tại [5], những lời góp ý chân thành, liên quan đến "Nói về XSS, hiện tượng này không phải là XSS như đã thấy. Trừ phi ai đó cho tôi thấy rằng làm thế nào để làm cho trình duyệt gửi header Expect đến website mong muốn". Nhưng khi dùng đối tượng Flash, việc tấn công trở nên dễ dàng. Hãy xem khi nạn nhân click vào link dưới đây: http://www.evil.site/attack.swf

URL này là một đối tượng Flash, đối tượng này sẽ chạy các ActionScript sau

Code:

var req:LoadVars=new LoadVars();
req.addRequestHeader( "Expect",
"<script>alert('gotcha!')</script>" );
req.send( "http://www.target.site/", "_blank", "GET" );



ActionScript này gửi một request từ trình duyệt nạn nhân đến website www.target.site, trong request có header Expect chứa mã HTML (Javascript) gây hại. Nếu website bị tấn công (www.target.site) chạy phiên bản Apache bị lỗi, kết quả tiếp theo sẽ là cross-site scripting. Vì thế đã rõ ràng - Apache phiên bản 1.3.34, 2.0.57 và 2.2.1 sẽ bị tấn công XSS (cùng với trình duyệt là IE hay Firefox và hỗ trợ Flash 6, 7). Trong [5] cũng lưu ý với Aapche 2.0/2.2, server trả về XSS response chỉ sau khi hết thời gian timeout của request. Xin nói thêm là Apache đã sửa lỗi này trên cả 3 phiên bản trên

VD 2 - CSRF và Referer
------------------------------------------

Tấn công CSRF (Cross Site Request Forgery) là kĩ năng cần thiết để một kẻ tấn công buộc trình duyệt nạn nhân thực hiện một thao tác (gửi HTTP request) đến website mong muốn. Khái niệm này được nói đến một vài lần, đầu tiên là trên mailing list Zope (với tiêu đề "Client Side Trojans", [6], và một lần khác tại BugTraq, dưới tiêu đề này, bây giờ nó đã trở thành tên bán tiêu chuẩn, CSRF [7]. Cả 2 bài góp ý trên, đều dựa trên header Referer như là dấu hiệu để trình duyệt sinh ra HTTP request có liên kết bắt nguồn từ trong website. Thật ra, nếu chỉ dùng HTML và Javascript thì không thể giả mạo Referer (trừ ngoại lệ trong [8], nhưng điều này chỉ hiệu quả trong một số điều kiện giới hạn; như khi sử dụng HTTPS thì không hiệu quả). Tuy nhiên, rõ ràng rằng với Flash thì đièu này không thành vấn đề, và Referer có thể bị giả mạo để yêu cầu các tài nguyên HTTPS, mọi thứ trong khi trình duyệt gởi cookie của site với request. Như phía trên đã minh hoạ, cả request dạng GET (với host và query bất kì) và POST (với phần host, query và phần thân theo định dạng chuẩn Content-Type là "application/x-www-form-urlencoded") đều gửi đi được.

Chú ý: đoạn phân tích trên không có nghĩa là chỉ có header Referer là bị giả mạo. Nên thấy rõ rằng bất kì header nào cũng có thể bị giả mạo. Trong trường hợp của IE, kẻ tấn công tạo các header giả để thay đổi header của trình duyệt (như là Referer).
Với Firefox, kỹ thuật giả mạo Referer không thể làm được vì Firefox thêm header vào bên dưới cùng của các header HTTP request. Tuy nhiên, một số ứng dụng web vẫn có thể vẫn dùng giá trị cuối của header, và như thế vẫn có thể bị nguy hiểm đối với kỹ thuật này

Hiện nay, mọi khả năng tấn công cross-site scripting qua các header HTTP request (Referer, User-Agent, Expect, Host, Content-Type) đều làm được.

Flash 9
==============

Flash 9 được thông báo vào ngày 28/06/2006 [9]. Ở Flash 9, những kĩ thuật đã nói trên (như dùng lớp LoadVars) không hỗ trợ các header mà trình duyệt dùng (như User-Agent, Host and Referer) và các header được bảo vệ như Content-Length. Tuy nhiên, các header như Expect vẫn được gữi đi và một vào kiểu tấn công (như VD 1 trên) vẫn hiệu quả trong Flash 9



Những giới hạn
===========================

* URL và phần body luôn ở dạng URL-encoded (URL được mã hoá). Tức là không thể cho các kí tự SP, HT, CR và LF (và nhiều kí tự khác) hiển thị ở dạng raw trong request URL và body.
* Chỉ có thể dùng GET và POST
* Trong IE, chỉ có header của mỗi lần truy cập được gởi một lần

* Tổng quát, không thể điều chỉnh hoàn toàn section header (kẻ tấn công sẽ gặp rắc rối khi muốn gửi những kí tự đặc biệt trong các header)

Giải pháp đơn phần
===============

Hãy chú ý hạn chế đầu tiên của kĩ thuật này - kí tự CR và LF không thể đặt trong section body ở định dạng raw. Nghĩa là cơ chế này không thể dùng để gửi request POST mà phần body của request này được biên dịch thành content-type là "multipart/form-data" (định dạng này dùng các kí tự CR,LF ở dạng raw để đánh dấu phần header với body). Nói cách khác, một Flash player không thể gửi đi POST request mà phần body của nó là một luồng "multipart/form-data" hợp lệ được. Vì thế, tác giả của những ứng dụng web có thể dùng các HTML form và đặt thuộc tính ENCTYPE là "multipart/form-data", điều này đảm bảo rằng thông tin đưa lên web với body multipart/form-data hoàn toàn hợp lệ. Một khi dùng cách này thì ta có thể biết được request đi đến có xuất phát từ Flash player hay không, và việc phá hoại sẽ trở nên vô tác dụng.


Giải pháp này dĩ nhiên hơi áp đặt - cả trang HTML và script phải được sửa đồi để dùng multipart/form-data. Với vài nền tảng phát triển web, điều này là bình thường, còn với số khác (raw Perl, ASP) thì không. Hơn nữa, trong trường hợp như VD 1 trên, web server (Apache) thông dịch rồi sử dụng các HTTP header, và tiến trình này sẽ không đi đến lớp ứng dụng web, vì vậy trong những trường hợp như thế, giải pháp này không áp dụng được

Hướng dẫn thêm
================

HTTP Request Splitting ([8]) và HTTP Request Smuggling ([10]) trong IE với Flash 7/8 có thể gữi header Content-Length với bất kì giá trị nào. Điều này cho phép thực hiện tấn công HTTP Request Splitting. Cũng như thế, việc chèn header Transfer-Encoding, hay thêm một header Content-Length thứ hai sẽ mơ ra cơ hội cho HTTP Request Smuggling. Cần phải nghiên cứu xa hơn để nắm rõ những cách thực hiện như vậy có đưa đến khả năng khai thác lỗi hay không

Các kinh nghiệm đã cho phép Flash 9 giới hạn nhiều hơn những header sẽ dùng trong LoadVars.addRequestHeader(), ngôn ngữ ActionScript 3.0 sẽ mạnh hơn là 2.0. Như thế, phiên bản mới này cung cấp những tính năng đáng giá tại mức HTTP, như là khả năng gửi nhiều loại HTTP, không chĩ GET và POST. Tốt hơn nên tìm hiểu Flash 9 và ActionScript 3.0 để nắm rõ những tiềm năng của chúng, lưu ý về các mẹo trong HTTP request


Kết luận
-==========

Việc xác thực dựa trên các header của HTTP request mà trình duyệt gửi đi không phải là ý hay. Thực tế thì mọi header có thể bị giả nếu client đang phải chạy một Flash movie xấu, và điều này hoàn toàn đúng với trên 80% máy tính để bàn truy cập Internet. Do đó, khả năng tấn công cross-site scripting trên những header như trên, cũng như tấn công bằng các request giả để cross site (cho những site mà tự bảo vệ bằng cách kiểm tra header Referer) là cao hơn so với những gì người ta nhận thấy

Bài viết khuyên nên dùng giải pháp đơn phần cho trường hợp về sau, tuy nhiên giải pháp này phụ thuộc rất nhiều vào Flash, và như thế có thể không cung cấp phần bảo vệ chống đỡ những biến thái được sử dụng với các công nghệ khác, hoặc những phát triển khác trong Flash. Vì thế, với giả mạo request cross site, nên xem xét những giải pháp khác mà không dựa vào Referer


Tham khảo
-=========

[1] "Technology Breakdown" (Adobe website)
http://www.adobe.com/products/player_census/flashplayer/tech_breakdown.html

[2] "Macromedia Flash Player Version Penetration" (Adobe website)
http://www.adobe.com/products/player_census/flashplayer/version_penetration.html

[3] "Re: 'Exploiting the XmlHttpRequest object in IE' - paper by Amit
Klein" by Anonymous, BugTraq posting, September 27th, 2005
http://www.securityfocus.com/archive/1/411823

[4] "Unfiltered Header Injection in Apache 1.3.34/2.0.57/2.2.1" by Thiago
Zaninotti, BugTraq posting, May 8th, 2006
http://www.securityfocus.com/archive/1/433280

[5] "Re: Unfiltered Header Injection in Apache 1.3.34/2.0.57/2.2.1" by
Amit Klein, BugTraq posting, May 18th, 2006
http://www.securityfocus.com/archive/1/434729

[6] "Client Side Trojans", Zope developers mailing list, May 2000
http://www.zope.org/Members/jim/ZopeSecurity/ClientSideTrojan

[7] "Cross Site Request Forgeries" by Peter Watkins, BugTraq posting, June
15th, 2001
http://www.tux.org/~peterw/csrf.txt

[8] "Exploiting the XmlHttpRequest object in IE - Referrer spoofing, and a
lot more..." by Amit Klein, BugTraq posting,
September 24th, 2005
http://www.securityfocus.com/archive/1/411585

[9] "Adobe Flash Player 9 Leads a New Generation of Dynamic Media and Rich
Internet Applications" (Adobe website), June 28th, 2006
http://www.adobe.com/aboutadobe/pressroom/pressreleases/200606/062806Flash9.html

[10] "HTTP Request Smuggling" by Chaim Linhart, Amit Klein, Ronen Heled
and Steve Orrin, June 6th, 2005
http://www.cgisecurity.com/lib/HTTP-Request-Smuggling.pdf

hijack
19-10-2007, 11:52 PM
Standar Javascript không gửi được HTTP request, nhưng chữ J trong AJAX có thể gửi được:


// FF and Opera
xmlHttp = xmlHttpRequest;
.....
xmlHttp.Open('GET','http://www.vuln.site/some/page.cgi?p1=v1&p2=v2',true);
xmlHttp.Send(null);

ferrari
22-10-2007, 01:49 PM
ko biết thằng pé c9 nì copy ở đâu nhưng về làm web có tài năng đấy !