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 đủ
28 trang |
Chia sẻ: Mr Hưng | Lượt xem: 871 | Lượt tải: 0
Bạn đang xem trước 20 trang nội dung tài liệu Lập trình an toàn, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
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
Các file đính kèm theo tài liệu này:
- secureprogramming_1_1436.pdf