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 Các nguyên tắc kiểm tra

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.2 Các hàm định dạng xâu

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.

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.

char str[1024];

gets(str);

printf(“Xin chao:”);

printf(str); // Nguy hiểm !!!

printf(“%s”,str); // OK

 

docx 28 trang kimcuc 3620
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

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ẬP TRÌNH AN TOÀN
Secure Programming Lương Ánh Hoàng hoangla@soict.hut.edu.vn
Mục đích
■
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.
Yêu cầu
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 đủ
Thời lượng môn học
Thời lượng: 45 tiết
Lý thuyết: 30 tiết
Bài tập:15 tiết
Tài liệu
Secure Program Cookbook for C and C++, Matt Messier, John Viega, O'Reilly 2003.
Nội dung
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
Đánh giá
Bài tập lớn: 70%
Quá trình: 30%
Chương 1. Kiểm tra đầu vào
Input Validation Lương Ánh Hoàng hoangla@soict.hut.edu.vn
Nội dung
Nguyên tắc kiểm tra.
Các hàm định dạng xâu (string formatting) .
Tràn bộ đệm.
■ ■
Tràn số học.
■
Kiểm tra tên file và đường dẫn.
Giải mã URL
Cross-Site Scripting
SQL Injection
Các nguyên tắc kiểm tra
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.
Các hàm định dạng xâu
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
Các hàm định dạng xâu
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[i024];
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
Tràn bộ đệm
Tràn bộ đệm (Buffer Overflow): 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);
Tràn bộ đệm
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”);
}
Tràn bộ đệm
VD4: Tấn công có chủ ý trên bộ đệm
void Bye()
{	
printf(“Bye”);
} 	 '
void Hello()
{	 _ _
void (*p)() = Bye;
char nãme[8]; printf(“What is your name ?”); gets(name);
printf(“Hello %s !”, name);
'	p();
void main()
{	
Hello();
}
Tràn bộ đệm
Giải pháp:
Sử dụng các hàm strncpy, memcpy.và 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ợ.
Tràn số học
■
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 = oxFFFFFFFF; // MAX_INT
if	( x+5 > 5 ) printf (“X > o” )
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 ... */
}
Kiểm tra tên file và đường dẫn
Dữ liệu nhận về có thể là tên file, ứng dụng cần xác định đường dẫn tuyệt đối nếu cần thiết.
Dùng hàm realpathQ 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[i024];
char * result = realpath(”printf.c”,resolved);
printf(”%s”,result);
Kiểm tra tên file và đường dẫn
Sử dụng GetFullPathName()
Thư viện: windows.h
Nguyên mẫu:
DWORD GetFullPathName(LPCTSTR IpFileName, DWORD nBufferLength, LPTSTR IpBuffer, LPTSTR *lpFilePath);
VD:
int nBufferLen = 0;
LPTSTR lpBuffer;
nBufferLen = GetFullPathName(L”test.c”,0,0,0);
if (nBufferLen>0)
{	, _ _	 ,
lpBuffer = new TCHAR[nBufferLen+i];
GetFullPathName(L”test.c”,nBufferLen,lpBuffer,0); wprintf(L”%s”,lpBuffer);
}
Giải mã URL
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.
Cross-Site Scripting
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.
Cross-Site Scripting
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.
SQL Injection
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 = 'Spass'
Nếu $user hoặc Spass 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
SQL Injection
VD (tiếp
- File ask.php
Vui long nhap ten va mat khau
 Ten: Mat khau: 
SQL Injection
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);
SQL Injection
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)>o)
echo "Dang nhap thanh cong";
else
echo "Sai ten hoac mat khau";
?>
SQL Injection
Tấn công
username = a' or ‘1'=‘1
password = b' or T=‘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.

File đính kèm:

  • docxbai_giang_lap_trinh_an_toan_chuong_1_kiem_tra_dau_vao_luong.docx
  • pdfsecureprogramming_1_2968_505054.pdf