Từ chối các truy xuất (Request) nguy hiểm từ người sử dụng trong ASP

Khi lập trình các ứng dụng Web, việc phân chia các trang web xử lý các công đoạn công việc khác nhau khác nhau không có gì hiếm gặp. Trong trường hợp đó, một trong những cách phổ biến nhất để truyền tham số từ một trang ASP tới một trang khác là thông qua QueryString. Mục đích của bài viết này sẽ chỉ ra cho bạn làm cách nào để ngǎn chặn những truy xuất không được phép trong ASP. Giới thiệu Khi lập trình các ứng dụng Web, việc phân chia các trang web xử lý các công đoạn công việc khác nhau khác nhau không có gì hiếm gặp. Trường hợp điển hình nhất là khi chúng ta có một trang cung cấp nhiều lựa chọn khác nhau (trang menu) và một trang khác xử lý yêu cầu, truy vấn cơ sở dữ liệu và hiển thị kết quả phù hợp với sự lựa chọn của người sử dụng. Trong trường hợp này, một trong những cách phổ biến nhất để truyền tham số từ một trang ASP tới một trang khác là thông qua QueryString. Phương pháp này rất dễ vận dụng và trong một số tình huống là phương pháp khả thi duy nhất. Không may, sử dụng phương pháp này luôn luôn tiềm ẩn những rủi ro nhất định. Điều gì sẽ xảy ra nếu người sử dụng gửi yêu cầu trực tiếp từ thanh địa chỉ của trình duyệt? Liệu họ có thể khám phá các thông tin bí mật của công ty bạn? Những khả nǎng như vậy là hoàn toàn có thể xảy ra và bài viết này sẽ chỉ ra cho bạn làm cách nào để ngǎn chặn những truy xuất không được phép này. Phần 1 - Một thí dụ đơn giản Trước hết, chúng ta hãy xem xét một ứng dụng rất đơn giản: chỉ gồm trang Menu.asp cung cấp một danh sách lựa chọn và trang Respone.asp xử lý yêu cầu của người sử dụng và truy vấn cơ cở dữ liệu để trả về kết quả phù hợp. Menu.asp Menu có 3 lựa chọn: Dữ liệu khách hàng, Đặt hàng và Hoá đơn <% Response.Write "List" & "
" Response.Write "Dữ liệu khách hàng
" Response.Write "Đặt hàng
" Response.Write "Hóa đơn
" %> Tất cả các lựa chọn trong trang Menu.asp đều trỏ tới trang Response.asp, nơi hiển thị kết quả truy vấn. Lưu ý mã khách hàng (custcode = 13 trong trường hợp này) được biểu diễn dưới dạng text bình thường mà không hề được mã hoá. Mặc dầu đây không phải là một thói quen lập trình tốt nhưng chúng ta cố tình làm như vậy để tiện cho sự giải thíchtrong bài này. Response.Asp Trang Respone.asp sẽ truy vấn cơ sở dữ liệu và hiển thị kết quả trả về <% ' khai báo, khởi tạo và mở một Connection (Conn) ' khai báo và khởi tạo recordset (Rs) SELECT CASE Request.QueryString("list") CASE 1 strSQL = "SELECT * FROM tableCustomers WHERE custcode=" & _ Request.QueryString("custcode") CASE 2 strSQL = "SELECT * FROM tableOrders WHERE custcode=" & _ Request.QueryString("custcode") CASE 3 strSQL = "SELECT * FROM tableInvoices WHERE custcode=" & _ Request.QueryString("custcode") END SELECT Rs.Open strSQL, Conn Do While Not Rs.Eof ' Show Records Rs.MoveNext Loop ' Close Rs & Conn %> Phương pháp này luôn luôn tiềm ẩn rủi ro. Người sử dụng có thể thay đổi tham số truyền vào bằng cách nhập các giá trị khác nhau từ thanh địa chỉ trình duyệt. Ví dụ, họ có thể nhập địa chi URL như sau: http://www.mysite.com/Response.asp?list=4&custcode=789 Trong thí dụ trên, người sử dụng đã thay đổi cả hai tham số Type và CustCode. Trong trường hợp thứ này, người sử dụng có thể đọc các thông tin mà họ không được quyền truy nhập. Hơn thế nữa, trang Response.asp được lưu trong History của trình duyệt, vì vậy những người khác có thể sử dụng để đọc những thông tin không được phép. Làm thế nào để tránh sự thâm nhập trái phép này? Chúng ta hoàn toàn có thể chặn được sự truy nhập trái phép nhờ sử dụng một trang trung gian thực hiện một vài biến đổi nhất định. Trang trung gian sẽ chuyển các tham số QueryString thành các giá trị Session. Tất nhiên, chúng ta phải thay đổi một chút đoạn mã ở trên. Menu.Asp Trang Menu.asp sau khi sửa sẽ thành: <% Response.Write "List" & "
" Response.Write "My Data
" Response.Write "My Orders
" Response.Write "My Invoices
" %> Như bạn có thể thấy, những thay đổi (in đậm) là rất ít. Vì vậy, chúng ta không phải thiết kế lại toàn bộ ứng dụng. Prepare.asp Đây là trang trung gian, nhận dữ liệu từ form của trang trước và chuyển đổi nó thành các giá trị Session (ẩn đối với người sử dụng) và sau đó chuyển yêu cầu xử lý tới trang truy vấn. Session("list")=Request.QueryString("list") Session("custcode")=Request.QueryString("custcode") Response.Redirect "Response.asp" Response.asp Trang Respone.asp sẽ được thay đổi như sau: <% ' khai báo, khởi tạo và mở connection (Conn) ' khai báo và khởi tạo recordset (Rs) SELECT CASE Session("list") CASE 1 strSQL = "SELECT * FROM tableCustomers WHERE custcode=" & _ Session("custcode") CASE 2 strSQL = "SELECT * FROM tableOrders WHERE custcode=" & _ Session("custcode") CASE 3 strSQL = "SELECT * FROM tableInvoices WHERE custcode=" & _ Session("custcode") CASE ELSE Response.Redirect("Menu.asp") END SELECT Rs.Open strSQL, Conn Do While Not Rs.Eof ' Hiển thị các bản ghi Rs.MoveNext Loop ' Close Rs & Conn %> Chỉ với một số không nhiều thay đổi, phương pháp này đem lại khá nhiều ưu điểm: ã Thanh địa chỉ của trình duyệt chỉ hiển thị tên trang ã Người sử dụng không thể thay đổi các tham số truyền vào cho Response.asp vì nó không đọc các tham số QueryString. Nó chỉ đọc một số giá trị Session mà người sử dụng không thể tự thiết lập. ã History của trình duyệt không lưu trang Prepare.asp có chứa tham số nên người sử dụng khó biết cách thâm nhập dữ liệu trái phép. (Cần lưu ý, nói "khó" ở đây không có nghĩa là không có thể. Tại sao? Trước hết, một ai đó có thể đọc trong thanh trạng thái của trinh duyệt, trừ khi bạn dùng Javascript để che đi. Hơn nữa, những người sử dụng thành thạo có thể đọc trực tiếp từ mã nguồn của Menu.asp và tìm đến dòng có lệnh gọi trang Prepare.asp để tạo lại lời gọi. Ngay cả trong trường hợp này, vẫn có giải pháp mà chúng ta sẽ nói tới ngay ở phần sau của bài viết này). Phần 2 ? Ngǎn chặn ngay từ bên ngoài Trong phần đầu của bài viết chúng ta đã bàn cách che Querystring trong thanh địa chỉ của trình duyệt để ngǎn ngừa một số hình thức sử dụng trái phép. Tuy nhiên, tại thời điểm này, chúng ta phải thừa nhận rằng những người sử dụng có kỹ nǎng vẫn không khó khǎn gì để dỡ bỏ hàng rào bảo vệ. Trường hợp xấu hơn, một số người sử dụng có kiến thức về ASP cũng vẫn có thể viết script với một số kết hợp của các tham số dầu vào để đọc nội dung từ cơ sở dữ liệu của bạn. Vì vậy, chúng ta phải tìm cách tránh những tình huống đó. Y' tưởng cơ bản là phải chặn những yêu cầu xuất phát từ bên ngoài Website. Liệu có biến server nào có thể cho chúng ta biết về nơi xuất phát của một yêu cầu cụ thể từ phía người dùng? Có, đó là biến HTTP_REFERER mà chúng ta có thể sử dụng theo cú pháp : Request.ServerVariables("HTTP_REFERER"). Chúng ta hãy xem giải thích về biến này (từ Site của Microsoft) HTTP_REFERER: Trả về một chuỗi chứa URL cả trang gửi yêu cầu tới trang hiện thời sử dụng thẻ HTML Tốt. Đây chính là biến chúng ta cần. Hãy lưu ý tới một đặc điểm rất quan trọng khác: khi bạn yêu cầu một trang Web bằng cách đánh URL trong thanh địa chỉ, HTTP_REFERER sẽ nhận giá trị rỗng, ngay cả khi bạn đánh chính xác toàn bộ URL. Tới đây, việc triển khai một lược đồ bảo vệ đã không còn nhiều khó khǎn. Việc cần làm trước tiên là so sánh địa chỉ của yêu cầu với địa chỉ Website của chúng ta: IF INSTR(Request("HTTP_REFERER"), "http://www.mysite.com/") <> 1 Then Response.Redirect "Menu.asp" End If IF INSTR(Request("HTTP_REFERER"), "http://10.10.10.212/") <> 1 Then Response.Redirect "Menu.asp" End If Trong thí dụ, những trang nào cần phải bảo vệ? Trước hết, đó là Prepare.asp vì đây là trang đọc QueryString. Chúng ta không cần bảo vệ Request.asp vì trang này dựa vào nội dung của biến Session, không phải QueryString. Hơn nữa, cần nhớ rằng một yêu cầu từ bên ngoài không thể truyền một biến Session cho ứng dụng của chúng ta. Prepare.asp (Những thay đổi được in đậm) IF INSTR(Request("HTTP_REFERER"), "http://www.mysite.com/") < 1 Then Response.Redirect "Menu.asp" End If IF INSTR(Request("HTTP_REFERER"), "http://10.10.10.212/") < 1 Then Response.Redirect "Menu.asp" End If Session("list")=Request.QueryString("list") Session("custcode")=Request.QueryString("custcode") Response.Redirect "Response.asp" Trong thí dụ nhỏ này, đó là tất cả những công việc chúng ta cần làm để chặn những yêu cầu trái phép từ bên ngoài. Tất nhiên, các ứng dụng trong thực tế thì phức tạp hơn nhiều. Chúng ta có thể viết một hàm để kiểm tra tính hợp pháp về nơi xuất phát của một yêu cầu đối với ứng dụng. Hàm đó có thể như sau: Function FromSite() IF INSTR(Request("HTTP_REFERER"), "http://www.mysite.com/") = 1 Then FromSite = True: Exit Function IF INSTR(Request("HTTP_REFERER"), "http://10.10.10.212/") = 1 Then FromSite = True: Exit Function FromSite = False End Function Sau đó, chúng ta gọi và sử dụng hàm này bằng cách If Not FromSite Then Response.Redirect "Menu.asp" End If Kết luận Một ứng dụng Web có thể được xây dựng để đáp ứng nhiều chức nǎng nhờ những công nghệ như ASP. Nhưng một điều không thể quên: các ứng dụng Web, với bản chất có thể truy nhập công cộng, bị phơi bày trước rất nhiều khả nǎng bị tấn công. Trong bài này, chúng ta đã học cách ngǎn chặn các yêu cầu không phải xuất phát từ chính Website bằng cách thiết lập một bức tường lửa ảo về phía những yêu cầu từ bên ngoài, không có thẩm quyền và luôn luôn ẩn chứa các nguy hiểm tiềm tàng. Chu Đình Phú (Theo builder.com)
Thứ Tư, 10/12/2003 01:54
31 👨 856
0 Bình luận
Sắp xếp theo
❖ Tổng hợp