Bài giảng Lập trình an toàn - Chương 1: Kiểm tra đầu vào - Lương Ánh Hoàng
1.1 Nguyên tắc kiểm tra.
1.2 Các hàm định dạng xâu (string formatting) .
1.3 Tràn bộ đệm.
1.4 Tràn số học.
1.5 Kiểm tra tên }ile và đường dẫn.
1.6 Giải mã URL
1.7 Cross-‐Site Scripting
1.8 SQL Injection
Bạn đang xem 20 trang mẫu của tài liệu "Bài giảng Lập trình an toàn - Chương 1: Kiểm tra đầu vào - Lương Ánh Hoàng", để tải tài liệu gốc về máy hãy click vào nút Download ở trên
Tóm tắt nội dung tài liệu: Bài giảng Lập trình an toàn - Chương 1: Kiểm tra đầu vào - Lương Ánh Hoàng
Lương Ánh Hoàng hoangla@soict.hut.edu.vn LẬP TRÌNH AN TOÀN Secure Programming • Cung cấp các kiến thức, kỹ thuật cơ bản để xây dựng các ứng dụng an toàn. Mục đích 2 • Yêu cầu về kiến thức: – An ninh mạng – Ngôn ngữ lập trình C/C++. • Lên lớp đầy đủ Yêu cầu 3 • Thời lượng: 45 tiết – Lý thuyết: 30 tiết – Bài tập:15 tiết Thời lượng môn học 4 • Secure Program Cookbook for C and C++, Matt Messier, John Viega, O'Reilly 2003. Tài liệu 5 • Chương 1. Kiểm tra đầu vào • Chương 2. Kiểm soát truy nhập • Chương 3. Kiểm soát xung đột • Chương 4. Mã hóa đối xứng • Chương 5. Hàm băm và xác thực thông điệp • Chương 6. Mã hóa công khai • Chương 7. Anti-‐Tampering • Chương 8. Các vấn đề khác Nội dung 6 7 • Bài tập lớn: 70% • Quá trình: 30% Đánh giá 8 Lương Ánh Hoàng hoangla@soict.hut.edu.vn Chương 1. Kiểm tra đầu vào Input Validation 1.1 Nguyên tắc kiểm tra. 1.2 Các hàm định dạng xâu (string formatting) . 1.3 Tràn bộ đệm. 1.4 Tràn số học. 1.5 Kiểm tra tên }ile và đường dẫn. 1.6 Giải mã URL 1.7 Cross-‐Site Scripting 1.8 SQL Injection Nội dung 10 • Luôn luôn giả định dữ liệu đầu vào là không đáng tin cậy – Dữ liệu từ mạng trong mô hình client-‐server – Dữ liệu từ người dùng – Dữ liệu từ tệp tin – • Ưu tiên loại bỏ dữ liệu hơn là cố gắng sửa chữa dữ liệu. • Thực hiện kiểm tra đầu vào tại nhiều cấp, nhiều điểm – Kiểm tra đầu vào ở các hàm – Kiểm tra đầu vào giữa các module. – • Không tiếp nhận lệnh trực tiếp từ người dùng nếu chưa qua kiểm tra. • Kiểm tra các ký tự đặc biệt, dấu nháy. • Tìm hiểu và sử dụng cơ chế trích dẫn (quoting mechanism) nếu cần. • Càng hiểu về dữ liệu bao nhiêu càng lọc được tốt bấy nhiêu. 1.1 Các nguyên tắc kiểm tra 11 • Họ các hàm printf() , syslog() cho phép định dạng dữ liệu rất mềm dẻo và mạnh mẽ tuy nhiên cũng cực kỳ nguy hiểm. • Thận trọng khi sử dụng “%n” – Tham số %n cho phép ghi ra số lượng ký tự đã kết xuất được ra một địa chỉ bất kỳ chỉ ra trong tham số tương ứng. Nếu không tồn tại tham số nào thì printf sẽ ghi đè lên một vùng nào đó thuộc stack của luồng đang thực thi. – VD. int counter = 0; printf(“Hello%n”,&counter); // OK, counter = 5 printf(“Hello%n”); // Nguy hiểm !!! • Không sử dụng trực tiếp xâu định dạng từ nguồn bên ngoài – Xâu định dạng có nguồn gốc từ ngoài chương trình có thể có một vài ký tự đặc biệt mà chương trình chưa lường trước được, hoặc không có tham số thay thế tương ứng. – VD. char str[1024]; gets(str); printf(“Xin chao:”); printf(str); // Nguy hiểm !!! printf(“%s”,str); // OK 1.2 Các hàm định dạng xâu 12 • Thận trọng khi sử dụng sprintf, vsprintf với “%s” – Các hàm trên đều giả định kích thước bộ đệm cho xâu đích là vô hạn. – Nên chỉ rõ số lượng ký tự tối đa sẽ sử dụng khi dùng với %s. – Nên sử dụng snprintf, vsnprintf nếu có thể. – VD char str[1024]; char dst[32]; gets(str); sprintf(dst,”Xau vua nhap vao la %s”,str); // Nguy hiểm sprintf(dst,”Xau vua nhap vao la %.16s”,str); // OK snprintf(dst,32,”Xau vua nhap vao la %s”,str);// OK 1.2 Các hàm định dạng xâu 13 • Tràn bộ đệm (Buffer Over}low): copy dữ liệu vượt quá biên của một bộ đệm nào đó => đè lên vùng nhớ của biến (cấu trúc) khác. • Phần lớn các hàm xử lý xâu trong C đều không thực hiện kiểm tra biên của bộ đệm: gets, strcpy, • VD1: Dữ liệu bị hỏng int x = 0; char buff[8]; strcpy(buff,”Hello AAAAAAAAAAAAAAAAAAAAAAAAAAAAA”); printf(“%d”,x); • VD2: Stack bị hỏng char name[8]; gets(name); printf(name); 1.3 Tràn bộ đệm 14 • VD3: Không trở về được từ chương trình con void Hello() { char name[8]; printf(“What is your name ?”); gets(name); printf(“Hello %s !”, name); } void main() { Hello(); printf(“Bye”); } 1.3 Tràn bộ đệm 15 • VD4: Tấn công có chủ ý trên bộ đệm void Bye() { printf(“Bye”); } void Hello() { void (*p)() = Bye; char name[8]; printf(“What is your name ?”); gets(name); printf(“Hello %s !”, name); p(); } void main() { Hello(); } 1.3 Tràn bộ đệm 16 • Giải pháp: – Sử dụng các hàm strncpy, memcpyvà những hàm có kiểm soát kích thước bộ đệm một cách tường minh. – Sử dụng Stack Guard trong các trình biên dịch hỗ trợ. – Sử dụng DEP (Data Execution Preventation) trên hệ điều hành hỗ trợ. – Sử dụng ASLR (Address Space Layout Randomization) trên trình biên dịch và hệ điều hành hỗ trợ. 1.3 Tràn bộ đệm 17 • Dữ liệu nhận về có thể có sai sót trong trường liên quan đến kích thước. • Các thao tác liên quan đến số nguyên lớn có thể bị tràn, lẫn lộn giữa số nguyên không dấu và có dấu • VD1: Tràn số unsigned int x = 0xFFFFFFFF; // MAX_INT if ( x+5 > 5 ) printf (“X > 0” ) else printf(“X < 0”); • VD2: Dùng sai kiểu có/không dấu if (x < MAX_SIZE) { // x, số byte cần cấp phát tùy theo giải thuật tính được if (!(ptr = (unsigned char *)malloc(x))) abort( ); } else { /* Handle the error condition ... */ } 1.4 Tràn số học 18 • Dữ liệu nhận về có thể là tên }ile, ứng dụng cần xác định đường dẫn tuyệt đối nếu cần thiết. • Dùng hàm realpath() trên Unix/Linux và GetFullPathName trên Windows. • Sử dụng realpath() § Nguyên mẫu: char *realpath(const char *pathname, char resolved_path[MAXPATHLEN]); § Thận trọng: Có thể tràn resolved_path và không thread-‐safe. § Thư viện: stdlih.h § VD char resolved[1024]; char * result = realpath("printf.c",resolved); printf("%s",result); 1.5 Kiểm tra tên qile và đường dẫn 19 • Sử dụng GetFullPathName() § Thư viện: windows.h § Nguyên mẫu: DWORD GetFullPathName(LPCTSTR lpFileName, DWORD nBufferLength, LPTSTR lpBuffer, LPTSTR *lpFilePath); § VD: int nBufferLen = 0; LPTSTR lpBuffer; nBufferLen = GetFullPathName(L"test.c",0,0,0); if (nBufferLen>0) { lpBuffer = new TCHAR[nBufferLen+1]; GetFullPathName(L"test.c",nBufferLen,lpBuffer,0); wprintf(L"%s",lpBuffer); } 1.5 Kiểm tra tên qile và đường dẫn 20 • RFC 1738 quy định cách mã hóa các ký tự không nhìn thấy được trong URL dưới dạng “%”. • VD: • Cách giải mã: duyệt từ đầu đến cuối , tìm các ký tự % và thay thế bằng mã ASCII tương ứng. • Không sử dụng các hàm xử lý xâu chuẩn vì có thể có ký tự NULL trong URL. 1.6 Giải mã URL 21 • Cross-‐Site Scripting (XSS) là hình thức tấn công vào trình duyệt người dùng bắt nguồn từ việc kiểm tra lỏng lẻo từ server. • Có thể dẫn đến thất thoát thông tin nhạy cảm: mật khẩu, session, cookie • Thực hiện bằng cách chèn mã HTML/JAVASCRIPT vào dữ liệu sẽ hiển thị ra trình duyệt => đoạn mã sẽ chạy trên trình duyệt của nạn nhân. • VD. Một ứng dụng web có hai trang – Hello.php: Hiển thị form và nhận tên của người dùng. – Chao.php: hiển thị tên nhận được lại cho người dùng. 1.7 Cross-‐Site Scripting 22 • File Hello.php Xin chào, vui lòng nhập tên bạn • File Chao.php <?PHP echo "Xin chao ".$_POST['name']; ?> • Demo • Với tên là : Secure • Với tên là: Secure alert('XSS was found !'); • Với tên là: Secure alert(‘Hacked’); • Giải pháp: Lọc bỏ các thẻ HTML khỏi dữ liệu từ người dùng. Mỗi ngôn ngữ lập trình có một cách riêng. 1.7 Cross-‐Site Scripting 23 • SQL Injection: Tấn công vào CSDL thông qua dữ liệu nhập từ trình duyệt. • Lợi dụng việc kiểm tra lỏng lẻo từ đầu vào, chèn mã lệnh SQL vào các truy vấn đến CSDL của ứng dụng web. • Thường lợi dụng dấu nháy “ ‘ “ để kết thúc câu truy vấn SQL hoặc thêm các câu truy vấn khác. • VD: Lệnh so sánh tên và mật khẩu trong SQL – select * from users where username = ‘$user’ and password = ‘$pass’ – Nếu $user hoặc $pass chứa dấu “’” thì SQL sẽ hiểu nhầm nội dung truy vấn • Các kỹ thuật khai thác: An ninh mạng • VD: Một ứng dụng web muốn kiểm tra tên và mật khẩu gồm hai trang – ask.php: Hiện form đăng nhập và thu nhận tên, mật khẩu – login.php: Kết nối đến CSDL và kiểm tra 1.8 SQL Injection 24 • VD (tiếp – File ask.php Vui long nhap ten va mat khau Ten: Mat khau: 1.8 SQL Injection 25 • VD (tiếp) – File login.php <?PHP $db_server = "localhost"; $db_username= "root"; $db_password= "123456"; $db = "test"; $table = "users"; $conn = mysql_connect($server,$db_username,$db_password); if (!$conn) { echo "Khong ket noi dc den CSDL"; return; } $ret = mysql_select_db($db,$conn); 1.8 SQL Injection 26 if (!$ret) { echo "Khong ton tai CSLD tuong ung"; return; } $user = $_GET['name']; $pass = $_GET['pass']; $sql = "select * from $table where username='$user' and password='$pass'"; echo $sql; $ret =mysql_query($sql,$conn); if (mysql_num_rows($ret)>0) echo "Dang nhap thanh cong"; else echo "Sai ten hoac mat khau"; ?> 1.8 SQL Injection 27 • Tấn công – username = a’ or ‘1’=‘1 – password = b’ or ‘1’=‘1 – • Phòng chống – Loại bỏ tất cả các dấu ‘ và các ký tự đặc biệt nếu cần. – Sử dụng escaped string • Với php/mysql: mysql_real_escape_string, hoặc thêm ‘\’. • Với SQL server: thêm ký tự ‘ trước ký tự đặc biệt. • Với Oracle DB: thêm ký tự ‘\’ trước ký tự đặc biệt. 1.8 SQL Injection 28
File đính kèm:
- bai_giang_lap_trinhantoan_chuong_1_kiem_tra_dau_vao_luong_an.pdf