Thứ sáu, 05/07/2013 | 00:00 GMT+7

Cách bảo mật server cloud chống lại SQL Injection


Việc chèn SQL tận dụng thói quen viết mã lỏng lẻo. Đó là một cuộc tấn công theo đó một user thù địch gửi mã đến một trong các biểu mẫu web của bạn, thay vì bất kỳ dữ liệu nào bạn đang cố gắng thu thập. Mã thù địch hoặc truy vấn database của bạn theo cách bạn không mong đợi hoặc thoát ra khỏi ứng dụng web của bạn và thực hiện các hoạt động trực tiếp trên server cloud của bạn. Thật dễ dàng để chạy một cuộc tấn công chèn SQL vào một trang web không nghi ngờ. Đề phòng trước một cuộc tấn công như vậy nên là một trong những ưu tiên hàng đầu của bạn ngay từ ngày đầu tiên.

Bước một - Học cách nhận biết mã rủi ro bảo mật

Các cuộc tấn công SQL luôn có dạng một chuỗi do user gửi chứa hai phần. Phần đầu tiên là đoán cách kết thúc một cách an toàn lệnh mà mã của bạn đang cố gắng thực hiện; phần thứ hai là mã thù địch mà kẻ tấn công muốn chạy trên VPS của bạn. Dưới đây là ví dụ về một chuỗi do user gửi được thiết kế để tận dụng sự lỏng lẻo trong mã của bạn:

x' AND user.email IS NULL; --

Điều này gần giống như một cái gì đó mà bạn có thể đã tự viết ra - và đó là điểm chính. User hy vọng rằng mã của bạn sẽ lấy chuỗi này và sử dụng nó trong một truy vấn SQL trông giống như sau:

SELECT email, passwd FROM user
WHERE email = 'x' AND user.email IS NULL; --';

Điều này có vẻ không hiệu quả nhiều, nhưng tùy thuộc vào cách ứng dụng của bạn phản hồi, nó có thể thông báo cho kẻ tấn công rằng họ đã đoán đúng tên bảng có liên quan. Sau đó, có những cuộc tấn công khác có thể bắt đầu tiết lộ thêm thông tin, chẳng hạn như tên user và password .

Chi tiết quan trọng cần hiểu là mã thù địch cố gắng đóng câu trích dẫn SQL của bạn hoặc theo một cách nào đó thoát ra khỏi các ràng buộc của truy vấn SQL của bạn và yêu cầu hoặc chèn dữ liệu của chính nó.

Không phải tất cả các cuộc tấn công SQL injection đều yêu cầu đóng dấu ngoặc kép. Nếu mã của bạn thực hiện truy vấn về một số, bạn sẽ không đặt dữ liệu đó trong dấu ngoặc kép. Điều này khiến bạn dễ bị tiêm loại thuốc sau:

2097 OR 1=1

Kẻ tấn công hy vọng ứng dụng của bạn sẽ làm điều gì đó giống như sau:

SELECT somedata FROM yourtable
WHERE userid = 2097 OR 1=1;

Mã của bạn dự định truy vấn SQL ở trên chỉ trả về dữ liệu nếu userrid trùng với userrid của đúng user . Nhưng việc chèn SQL khiến truy vấn luôn trả về dữ liệu.

Vấn đề không phải là hành vi chính xác của bất kỳ trường hợp chèn SQL cụ thể nào. Điều quan trọng nhất cần loại bỏ là đặc điểm chung của tất cả các SQL injection: cố gắng đoán cách kết thúc một phần của truy vấn và bắt đầu một phần khác mà bạn không mong đợi. Đó là chữ ký của tất cả các lần tiêm SQL. Và đó là cách để chống lại chúng.

Bước hai - Tìm đầu vào của bạn

Trong mã của bạn, nơi tốt nhất để theo dõi tất cả các điểm nhập có thể xảy ra cho một cuộc tấn công chèn SQL không phải bằng cách tìm kiếm các biểu mẫu HTML của bạn. Chắc chắn, bạn có thể bắt một loạt theo cách đó, nhưng có những cách khác mà user có thể nhập dữ liệu, bao gồm cả trong URL hoặc thông qua một trong các giao diện AJAX của bạn.

Không, nơi tốt nhất để xem xét là ngay tại điểm có lỗ hổng - chính truy vấn SQL. Có thể tất cả các truy vấn của bạn được thực hiện bằng cùng một lệnh cơ bản - hoặc có thể là hai hoặc ba lệnh có thể có khác nhau. Chỉ cần tìm kiếm những thứ đó trong cơ sở mã của bạn và bạn sẽ tìm thấy mọi điểm rủi ro bảo mật rất nhanh chóng. Ví dụ: nếu mã của bạn sử dụng Perl, tất cả các truy vấn của bạn có thể có dạng tương tự như sau:

$result = mysql_query($sql)

Trong trường hợp đó, bạn có thể nhanh chóng tìm thấy tất cả các điểm có lỗ hổng từ dòng lệnh, sử dụng lệnh tương tự như sau:

$ grep -R mysql_query *

Bước 3 - Vệ sinh đầu vào của bạn

Có rất nhiều kỹ thuật mà mọi người sử dụng để ngăn chặn các cuộc tấn công SQL injection, nhưng biện pháp phòng thủ tuyến đầu của bạn phải là loại bỏ tất cả thông tin nhập của user . Bạn không bao giờ được cho rằng user sẽ gửi dữ liệu theo định dạng mà bạn mong muốn. Trên thực tế, bạn nên giả định ngược lại - rằng họ chỉ muốn gửi đúng chuỗi để xé mã của bạn.

Làm sạch đầu vào nghĩa là tất cả các chuỗi do user gửi đều được kiểm tra đảm bảo rằng chúng chỉ chứa các ký tự an toàn, không bao giờ được dùng trong một cuộc tấn công.

Chuỗi do user gửi sẽ được server SQL của bạn sử dụng theo một trong hai cách:

1. Như một con số, như 2097

2. Dưới dạng một chuỗi, chẳng hạn như tên user , password hoặc địa chỉ email

Mã của bạn luôn mong đợi một trong hai dạng dữ liệu này. Trong các ví dụ được đưa ra ở đầu hướng dẫn này, ví dụ đầu tiên muốn một chuỗi và ví dụ thứ hai muốn một số. Nó sẽ luôn luôn là cái này hay cái khác.

Cũng có hai cách để làm sạch dữ liệu - một cách tốt và một cách xấu. Cách xấu là kiểm tra nó để biết có thể tiêm. Lý do tồi tệ là vì số lượng mũi tiêm có thể có là quá lớn, và sự sáng tạo của những kẻ tấn công là rất lớn. Cách tốt để làm sạch dữ liệu là xác định đầu vào phù hợp trông như thế nào và loại trừ mọi thứ không tuân theo những ràng buộc đó.

Dữ liệu số là dễ dàng để làm sạch nhất, vì vậy ta sẽ đề cập đến vấn đề đó trước. Một số có dấu trừ tùy chọn ở bên trái, theo sau là một số chữ số và có thể là dấu thập phân. Không có gì khác. Trong Perl, bạn có thể kiểm tra đầu vào của user bằng số như sau:

if($numericaluserinput !~ /^-?[0-9.]+$/) {
    # the user input is not a number
}

Thật khó để tưởng tượng bất kỳ mũi tiêm thù địch nào lại lẻn qua hàng rào đó.

Việc khử trùng đầu vào văn bản khó hơn, vì có rất nhiều cách để thử. Kẻ tấn công có thể sử dụng dấu ngoặc kép và dấu gạch chéo ngược theo những cách sáng tạo. Trên thực tế, việc cố gắng đưa vào blacklist các ký tự cụ thể trong dữ liệu nhập của user rất khó chịu, vì quá dễ dàng để bỏ lỡ điều gì đó quan trọng.

Cách tiếp cận tốt hơn, như ta đã làm với đầu vào số, là giới hạn đầu vào của user trong một tập hợp các ký tự trong danh sách trắng. Ví dụ: một địa chỉ email có thể bị giới hạn ở các chữ cái, số, dấu gạch ngang, dấu gạch dưới, dấu cộng, số thập phân và ký hiệu @. Trong Perl, bạn có thể kiểm tra đầu vào địa chỉ email như sau:

if($useremail ~= /^[0-9a-zA-Z\-_+.\@]$/) {
    # the user's email address is unacceptable
}

Một danh sách trắng tương tự có thể được tìm thấy cho các loại đầu vào khác của user , chẳng hạn như tên user , địa chỉ nhà riêng, v.v.

User có thể phản đối danh sách trắng. Đặc điểm kỹ thuật cho địa chỉ email bao gồm nhiều ký hiệu không có trong thử nghiệm được đưa ra ở trên. Tất nhiên, bạn có thể tự do bao gồm các ký hiệu bổ sung trong các thử nghiệm của bạn , nhưng trước khi làm như vậy, bạn nên nghiên cứu từng ký hiệu đảm bảo rằng nó không bao giờ được sử dụng trong SQL injection. Với sự lựa chọn giữa sự thoải mái của user và bảo mật trang web, bảo mật trang web phải luôn đặt lên hàng đầu.

Vệ sinh đầu vào bằng các bộ ký tự trong danh sách trắng là tốt vì nó dễ dàng. Nếu bạn sẵn sàng đặt một vài ràng buộc đơn giản về loại dữ liệu mà user có thể gửi và nếu bạn siêng năng thường xuyên kiểm tra các truy vấn SQL của bạn đảm bảo rằng chúng chỉ sử dụng các đầu vào đã được khử trùng, bạn hầu như có thể loại bỏ nguy cơ bị tiêm SQL .

Bước bốn - Chấp nhận đầu vào rủi ro

Gì? Nhưng ta vừa mới nói về tầm quan trọng của việc không chấp nhận các yếu tố đầu vào rủi ro.

Đúng là danh sách trắng có tính hạn chế cao là con đường phù hợp, nếu ứng dụng của bạn có thể chấp nhận đặt mức hạn chế đó cho user . Nhưng trong một số trường hợp, điều quan trọng đối với mô hình kinh doanh của bạn là không đặt bất kỳ loại ràng buộc nào đối với đầu vào của user .

Trong trường hợp này, ngôn ngữ lập trình được sử dụng trong ứng dụng của bạn có thể có các thư viện để bảo vệ mã của bạn khỏi các đầu vào của user thù địch. Ví dụ: thư viện Perl DBI có các phương pháp để ngăn chặn đầu vào của user thoát ra khỏi phần cụ thể của truy vấn mà họ dự định:

my $sql = "INSERT INTO user (username, email) VALUES (?, ?)";
my $handle = $dbh->prepare( $sql );
$handle->execute( $untrustedusername, $untrustedemail);

Trong ví dụ trên, dấu '?' ký tự được sử dụng làm chỗ dành sẵn. Thư viện Perl DBI thay thế chúng bằng các biến không tin cậy được thu thập từ user . Nhưng khi làm như vậy, thư viện DBI hạn chế rõ ràng các biến đó chỉ liên quan đến các trường mong đợi chúng.

Các ngôn ngữ khác có các thư viện tương tự, để hạn chế việc sử dụng dữ liệu user hoặc để thoát khỏi dữ liệu.

Lợi ích của kỹ thuật này là bạn có thể đặt niềm tin vào những người duy trì mã thư viện, rằng họ sẽ duy trì nó và giữ cho nó không có lỗi và lỗ hổng bảo mật. Hạn chế của kỹ thuật này là nó hơi ít dễ đọc hơn, và do đó, có nhiều khả năng một số truy vấn SQL của bạn sẽ quên sử dụng các lệnh gọi thư viện thích hợp để bảo vệ chính chúng.

Bước 5 - Giảm nhẹ các cuộc tấn công có thể vượt qua

Tùy thuộc vào mô hình kinh doanh của bạn , bạn có thể cần triển khai tuyến phòng thủ cuối cùng - một thứ hoàn toàn độc lập với các nhà phát triển ứng dụng của bạn. Rốt cuộc, có thể một trong số họ đã sử dụng nhầm danh sách trắng ở đâu đó hoặc không thực hiện được lệnh gọi thư viện thích hợp để cô lập dữ liệu user . Chỉ một lỗ hổng trong mã là tất cả những gì có thể làm để khiến toàn bộ trang web dễ bị tấn công bởi SQL injection.

Trước hết, bạn nên giả định nếu kẻ tấn công phá vỡ hàng rào bảo vệ tiêm của bạn, tức là chúng đã có được toàn quyền root trên VPS đó. Họ sở hữu chiếc máy, mặc dù bạn đang làm mọi công việc chăm sóc và nuôi dưỡng nó.

Để giảm thiểu sự cố do đó, bản thân VPS phải được cấu hình trong một phần riêng biệt của mạng, để user root trên hệ thống đó không thể nhìn thấy hoặc truy cập bất kỳ hệ thống nào khác trong cơ sở hạ tầng của bạn. Loại phòng thủ đó được gọi là DMZ, và nó rất tuyệt, và cũng nằm ngoài phạm vi của hướng dẫn này.

Dù bạn sử dụng cơ chế nào để bảo vệ server cloud trước một user thù địch đã đột nhập, bạn vẫn nên cố gắng cài đặt một số loại hệ thống cảnh báo, để administrator hệ thống của bạn sẽ được thông báo nếu một số hoạt động nhất định được ghi lại trên VPS. Các chỉ báo này sẽ cho bạn biết rằng mã ứng dụng của bạn đã bị xâm nhập và bạn cần thực hiện đánh giá ngay lập tức toàn bộ cơ sở mã của bạn để tìm ra lỗi. Nếu không có những cảnh báo đó, kẻ tấn công có thể tận dụng thời gian ngọt ngào của chúng để thâm nhập DMZ của bạn và bạn có thể không bao giờ biết bất cứ điều gì là sai sót cho đến khi chúng bỏ trốn với tất cả các số thẻ tín dụng mà bạn cho là đã bị cô lập trên một server hoàn toàn khác, ở phần 'không thể truy cập được' của mạng.

Bước 6 - Thuê chuyên gia bảo mật

Nếu bạn đang triển khai một ứng dụng web mà không có sự trợ giúp của chuyên gia bảo mật, thì bạn sẽ bơi trong vùng nước rất nguy hiểm. Nếu vì lý do nào đó mà bạn chưa sẵn sàng thuê một chuyên gia bảo mật, bạn nên xem xét một cách tiếp cận rất hà khắc để đưa vào danh sách trắng các ký tự được phép trong đầu vào của user . Danh sách trắng tương đối đơn giản để thực hiện và xem xét, và một hệ thống đủ hà khắc nên khá khó xuyên qua. Hãy để user của bạn gặp phải sự bất tiện nhỏ của một bộ ký tự bị hạn chế, trong khi bạn xây dựng doanh nghiệp của bạn và chuẩn bị thực hiện việc tuyển dụng bạn cần. Khi bạn có người hiểu các vấn đề bảo mật, bạn sẽ chuẩn bị tốt hơn để đề phòng việc tiêm SQL, các cuộc tấn công tập lệnh chéo trang web và nhiều vấn đề bảo mật nguy hiểm khác đang hoành hành trên web hiện đại.


Tags:

Các tin liên quan

Cài đặt và sử dụng Vim Text Editor trên Cloud Server
2013-07-03
Cách cài đặt Zend Server 6 trên VPS CentOS 6.4
2013-07-03
Cài đặt và sử dụng Vim Text Editor trên Cloud Server
2013-07-03
Cách sử dụng Z Shell (zsh) trên server cloud
2013-07-01
Cách thêm tệp swap trên server cloud Arch Linux
2013-06-28
Cách cài đặt server DNS BIND trên CentOS 6
2013-06-12
Cách cài đặt eJabberd XMPP Server trên Ubuntu
2013-06-04
Cách cấu hình tmux trên server cloud
2013-05-20
Cách cài đặt cPanel trên server ảo chạy Centos 6
2012-11-02
Cách cài đặt Linux, Apache, MySQL, PHP (LAMP) trên Debian
2012-10-04