10/23/2019
LOGO
www.themegallery.com
Lập trình an tồn
(SECURE PROGRAMMING)
Nội dung
1
Lập trình an tồn
Tổng quan về lập trình an tồn
2
Tràn bộ đệm
3
Kiểm sốt truy nhập
4
Mã hóa thơng tin
5
Mã hóa đối xứng
6
Giới thiệu chương trình
Lập trình an tồn
1. Tên học phần: Lập trình an tồn (secure
programming).
2. Tồng số tiết: 30 tiết lý thuyết, 30 tiết thực hành
(bài tập nhóm, thảo luận, đồ án)
3. Nơi dụng chương trình: 7 chương
Thực hiện chương trình
Lập trình an tồn
1. Sinh viên nghiên cứu tài liệu.
2. Lên lớp lý thuyết (30 tiết, 10 buổi).
3. Thực hành: làm bài tập nhóm, thảo luận, báo cáo
(30 tiết).
Mã hóa cơng khai
Hàm băm và xác và xác thực thông điệp
1
10/23/2019
Đánh giá
Tài liệu tham khảo
Lập trình an tồn
Lập trình an tồn
1. Điểm chun cần+ thảo luận, báo cáo bài tập
nhóm: 40%
[1] Bài giảng Lập trình an tồn, Ths Lương Ánh
Hồng
2. Điểm thi cuối kỳ: 60%
[2] Giáo trình mã hóa thơng tin, PGS Dương Anh
Đức, TS Trần Minh Triết, ĐHKHTN TP. Hồ Chí Minh
[3] Secure Programming CookBook, John Viega
and Matt Messier
[4] Writing Secure Code, Michael Howard, Devid
LeBlanc.
Chương 1
LOGO
www.themegallery.com
Lập trình an tồn
Nội dung
Lập trình an tồn
1.1. Tầm quan trọng của an tồn - bảo
mật hệ thống.
1.2. Hướng của tiến trình phát triển an
toàn – bảo mật hệ thống phần mềm.
1.3. Các nguyên tắc của an toàn – bảo
mật phần mềm.
Tài liệu tham khảo: Writing Secure Code , Michael Howard,
Devid LeBlanc.
1.4. Các mô hình tấn cơng, đe dọa tính
an tồn – bảo mật phần mềm
2
10/23/2019
1.1. Sự cần thiết các hệ thống phải an toàn –
Lập trình an tồn
bảo mật
Một hệ điều hành được coi là “an tồn” khi nó
đảm bảo được ba yếu tố chính: Confidentiality
(tuyệt mật), Integrity (tồn vẹn) và Availability
(sẵn sàng).
1.1. Sự cần thiết các hệ thống phải an toàn –
Lập trình an tồn
bảo mật
Phần mềm có chất lượng phải là phần
mềm an toàn và tin cậy.
Để hệ thống an tồn địi hỏi rất nhiều cơng sức
trong tất cả giai đoạn phát triển phần mềm, nhất
là giai đoạn lập trình.
Những sai lầm trong việc lập trình gây ảnh
hưởng tới tính an tồn của hệ thống.
1.1. Sự cần thiết các hệ thống phải an tồn –
Lập trình an tồn
bảo mật
Một sản phẩm phần mềm khơng an tồn,
có lỗ hổng bảo mật thì chi phí khắc phục,
vá lỗi vơ cùng đắt.
Một số xu hướng cho an toàn, bảo mật
trong lập trình và kỹ thuật phần mềm trong
tương lai:
Song hành cùng phát triễn của phần cứng
và công nghệ phần mềm.
Hội thảo, hợp tác các lực lượng trong lãnh
vực an toàn, bảo mật.
1.1. Sự cần thiết các hệ thống phải an tồn –
Lập trình an tồn
bảo mật
Đẩy mạnh giáo dục về an toàn và bảo mật
Xác định trọng tâm của an tồn, bảo mật và phịng
chống các loại tấn cơng theo từng thời điểm thích
hợp
Sự tấn cơng phá hoại và sự bảo vệ; an tồn phần
mềm song hành phát triển ngày càng tin vi, phức
tạp và nâng cao.
- Nguyên lý 1: phải bảo vệ an tồn tất cả mọi điểm,
tấn cơng chỉ chọn điểm yếu nhất.
- Nguyên lý 2: Tổ chức bảo vệ an toàn trên cơ sở
hiểu biết về các cuộc tấn công; tấn cơng trên cơ
sở tìm các lỗ hõng của an tồn bảo mật
3
10/23/2019
1.1. Sự cần thiết các hệ thống phải an toàn –
Lập trình an tồn
bảo mật
1.2. Xu hướng của tiến trình phát triển của an
Lập trình an tồn
tồn và bảo mật phần mềm
- Nguyên lý 3: Tổ chức bảo vệ phải thường xuyên,
liên tục; tấn công là tùy ý.
- Nguyên lý 4: Tổ chức bảo vệ phải “đúng luật’; cịn
tấn cơng có thể “chơi bẩn”.
Cải thiện, phát triển an tồn tất cả các pha của
quy trình phần mềm: từ phỏng vấn, thiết kế, cài
đặt và nhất là pha test kiểm tra.
Tăng cường tuyên truyền, giáo dục về an toàn
và bảo mật thông tin.
Thiết kế đúng (tin cậy) và an tồn thì sản phẩm
tạo ra (phần mềm) có giá trị và giãm chi phí.
Ngược lại, nếu thiết kế sai, khơng an tồn thì chi
phí khắc phục, sửa chữa, bảo trì vơ cùng tốn
kém.
1.2. Xu hướng của tiến trình phát triển của an
Lập trình an tồn
tồn và bảo mật phần mềm
1. 3. các nguyên tắc của an toàn bảo mật
Phần mềm có chất lượng chỉ khi phần mềm an
tồn, một code có chất lượng chỉ khi code là an
tồn.
Pha kiểm thử (test) an toàn là rất quan trọng cho
chất lượng phần mềm. Kiểm thử phải kiểm
chứng được phần mềm khơng có lỗi, khơng thể
bị tấn cơng (an tồn). Ngồi ra kiểm thử cịn phải
kiểm chứng được sẽ an toàn trước các lỗi (lỗ
hỏng) phát sinh và xu hướng tấn công trong
tương lai.
a. Chiến lược SD3: thiết kế an toàn, cài đặt mặc
định an toàn, chuyển giao huấn luyện an toàn.
b. Các nguyên tắc của an toàn bảo mật:
Học từ các lỗi, các sai lầm
Cực tiểu hóa các bề mặt tấn cơng
Phịng thủ, bảo vệ theo chiều sâu
Phân quyền các đặc quyền ít nhất
Sử dụng an tồn hơn mặc định
Ln giả thuyết là hệ thống ngồi là khơng an
tồn.
Có kế hoạch cho thất bại
Luôn chỉnh lại cho đúng các lỗi an tồn bảo mật
Lập trình an tồn
4
10/23/2019
1. 4. Mơ hình các đe dọa an tồn bảo mật
Lập trình an tồn
Thiết kế an tồn thơng qua mơ hình đe dọa an
tồn bảo mật.
Các kỹ thuật an toàn – bảo mật phần mềm
Xác thực: là tiến trình, chính yếu là đảm bảo tính
tồn vẹn và kiểm chứng tính tồn vẹn của tiến
trình khác.
Có nhiều giao thức xác thực trong hệ điều hành
window. Có một giao thức xác thực được xây
dựng trong phần mềm, một số mà người sử dụng
thực hiện xác thực theo yêu cầu của OS.
Cơ bản có các bước xác thực là:
o Xác thực cơ bản
o Xác thực theo danh sách
LOGO
www.themegallery.com
Lập trình an tồn
Tràn bộ đệm
(Buffer overun)
1. 4. Mơ hình các đe dọa an tồn bảo mật
Lập trình an tồn
o Dạng thức (mẫu) xác thực cơ bản: khơng có dạng
thức chung. Có thể tham khảo qua đoạn code xác
thức ASP để đọc username và password:
<%
Dim strUsername, strPwd As String
strUsername = Request.Form("Username")
strPwd = Request.Form("Pwd")
If IsValidCredentials(strUserName, strPwd) Then
' Cool! Allow the user in!
' Set some state data to indicate this
Else
' Oops! Bad username and password
Response.Redirect "401.html"
End If
%>
Nội dung
Chương
Lập trình an tồn
2.1 Tràn stack.
2.2 Tràn heap.
2.3 Lổi định dạng chuỗi
2.4 Kích thước bộ đệm của mã Unicode và
Ansi không tương hợp.
2.5 Ngăn chặn tràn bộ đệm
5
10/23/2019
2.1. Tràn stack
Lập trình an tồn
Tổ chức bộ nhớ của Stack/Heap
2.1. Tràn stack
Ví dụ: đoan chương trình
2.1. Tràn stack
Lập trình an toàn
Tràn stack xãy ra khi buffer được khai báo trong
stack bị ghi đè bởi dữ liệu lớn hơn buffer được khai
báo.
Các biến khai báo trong stack trã về địa chỉ của
hàm gọi.
Thông thường, hệ thống (hệ điều hành) khơng kiểm
tra luồng nhập (như hàm strcpy)
Ví dụ đoạn code làm tràn stack
Lập trình an tồn
2.1. Tràn stack
Lập trình an tồn
Minh họa bộ nhớ của đoạn mã thực hiện và Stack data
void checkserial()
{
char sn[16];
scanf(‘%s‛, sn);
}
int main()
{
checkserial();
int i= 7;
return 0;
}
6
10/23/2019
2.1. Tràn stack
2.1. Tràn stack
Lập trình an tồn
Khi hàm checkserial thực hiện xong, lệnh RET sẽ nạp
lại giá trị 128 tại địa chỉ 401 trong stack vào con trỏ
lệnh IP để quay về lại lệnh i= 7.
Nếu trong hàm checkserial, người sử dụng nhập vào
chuỗi ít hơn 16 ký tự thì chương trình hoạt động bình
thường, tuy nhiên nếu người sử dụng nhập vào chuỗi
16 ký tự trở lên thì lúc này ơ nhớ 401 sẽ bị đè bởi ký tự
thứ 16, tình trạng tràn bộ đệm xảy ra. Lúc này khi lệnh
RET của hàm checkserial thực hiện, con trỏ lệnh IP sẽ
có 1 giá trị khác chứ khơng phải là 128, do đó lệnh i= 7
sẽ khơng được thực hiện.
Hacker có thể lợi dụng điều này để tiến hành các hoạt
động phá hoại.
Lập trình an tồn
Vi dụ 2: tràn stack
void checkserial()
{
char sn[16];
printf(‘\nEnter a serial number\n‛);
scanf(‚%s‛, sn);
if (!strncmp(sn‚’S123N456‛, 8))
{
printf(‚Serial number is correct‛);
}
}
int main()
{
checkserial();
int i=7;
return 0;
}
2.1. Tràn stack
Lập trình an tồn
Lợi dụng lỗi tràn bộ đệm hacker sẽ tìm cách nhập
vào một chuỗi gì đó (khác “S123N456”), mà
chương trình vẫn in ra câu “Serial number is
correct”.
Ví dụ, nhập chuỗi:
AAAAAAAAAAAAAAAAAAAAAAAAAAAAⱠ^R@
Đây chính là cách thức mà sâu Code Red vào
năm 2001 đã sử dụng để lây nhiễm.
2.2. Tràn heap
Lập trình an tồn
Tương tự như tràn stack. Tuy nhiên nhiên, tràn
heap sự tấn cơng có thể ghi tùy ý các thơng tin
vào vị trí của ứng dụng mà nó đã truy cập.
Có một số hệ điều hành và chip xử lý bảo vệ,
không cho tấn công stack; heap khơng bị tấn
cơng.
Ví dụ sau, minh họa làm tràn heap.
7
10/23/2019
2.2. Tràn heap
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
class BadStringBuf
{
public:
BadStringBuf(void)
{
m_buf = NULL;
}
~BadStringBuf(void)
{
if(m_buf != NULL)
free(m_buf);
}
void Init(char* buf)
{
m_buf = buf;
}
void SetString(const char* input)
{
strcpy(m_buf, input);
}
const char* GetString(void)
{
return m_buf;
}
private:
char* m_buf;
};
BadStringBuf* g_pInput = NULL;
void bar(void)
{
printf("Augh! I've been hacked!\n");
}
2.3. Lổi định dạng chuỗi
2.2. Tràn heap
Lập trình an tồn
void BadFunc(const char* input1,
const char* input2)
{
char* buf = NULL;
char* buf2;
buf2 = (char*)malloc(16);
g_pInput = new BadStringBuf;
buf = (char*)malloc(16);
g_pInput->Init(buf2);
strcpy(buf, input1);
g_pInput->SetString(input2);
printf("input 1 = %s\ninput 2 =
%s\n", buf, g_pInput ->GetString());
if(buf != NULL)
free(buf);
}
Định dạng sai dạng thức chuỗi (string) không xãy ra
tràn bộ đệm nhưng cũng dẫn đến vấn đề tương tự.
Xét ví dụ:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
typedef void (*ErrFunc)(unsigned
long);
void GhastlyError(unsigned long
err)
{
printf("Unrecoverable error! - err
= %d\n", err);
exit(-1);
}
int main(int argc, char* argv[])
{
char arg1[128];
char arg2[4] = {0x0f, 0x10, 0x40,
0};
int offset = 0x40;
memset(arg1, 0xfd, offset);
arg1[offset] = (char)0x94;
arg1[offset+1] = (char)0xfe;
arg1[offset+2] = (char)0x12;
arg1[offset+3] = 0;
arg1[offset+4] = 0;
printf("Address of bar is %p\n",
bar);
BadFunc(arg1, arg2);
if(g_pInput != NULL)
delete g_pInput;
return 0;
}
2.3. Lổi định dạng chuỗi
Lập trình an tồn
void RecoverableError(unsigned
long err)
{
printf("Something went wrong, but
you can fix it - err = %d\n",err);
}
void PrintMessage(char* file,
unsigned long err)
{
ErrFunc fErrFunc;
char buf[512];
}
if(err == 5)
{
fErrFunc = GhastlyError
}
else
{
fErrFunc =
RecoverableError;
}
snprintf(buf, sizeof(buf)-1,
"Cannot find %s", file);
printf("%s", buf);
printf("\nAddress of fErrFunc is
%p\n", &fErrFunc);
fprintf(stdout, buf);
printf("\nCalling ErrFunc %p\n",
fErrFunc);
fErrFunc(err);
Lập trình an tồn
Lập trình an toàn
void foo(void)
{
printf("Augh! We've been
hacked!\n");
}
int main(int argc, char* argv[])
{
FILE* pFile;
printf("Address of foo is %p\n",
foo);
pFile = fopen(argv[1], "r");
if(pFile == NULL)
{
PrintMessage(argv[1],
errno);
}
8
10/23/2019
2.3. Lổi định dạng chuỗi
else
{
}
Lập trình an tồn
2.4.Kích thước bộ đệm mã
Unicode và Ansi không tương hợp.
Tràn bộ nhớ đệm trong trường hợp này hơi giống
cơ chế Windows platforms
Tràn bộ nhớ đệm khi ta xếp ngẫu nhiên số lượng
các phần tử theo kích thước byte trong bộ nhớ
đệm Unicode.
BOOL GetName(char *szName)
Ví dụ:
{
printf("Opened %s\n",
argv[1]);
fclose(pFile);
}
return 0;
}
2.4.Kích thước bộ đệm mã
Unicode và Ansi khơng tương hợp.
Lập trình an tồn
WCHAR wszUserName[256];
// Convert ANSI name to Unicode.
MultiByteToWideChar(CP_ACP, 0,
szName,
-1,
wszUserName,
sizeof(wszUserName));
// Snip
Lập trình an tồn
Lập trình an tồn
Giá trị của tham số sizeof(wszUserName)?
256? Sai
Đúng là 512 (vì size(character) là 2).
Tràn buffer (khai báo là 256).
Đoạn code đúng là:
MultiByteToWideChar(CP_ACP,
0,
szName,
-1,
wszUserName,
sizeof(wszUserName) / sizeof(wszUserName[0])
);
2.5. Chèn câu lệnh SQL (SQL Injection)
Hê DBMS thường sử dụng câu truy vấn SQL để gửi
yêu cầu thao tác dữ liệu đến hệ quản trị CSDL. Hệ
quản trị CSDL xử lý và gửi trả lại dữ liệu kết quả cho
phần mềm.
Câu SQL không được biên dịch sẵn, chỉ khi nào phần
mềm ứng dụng tạo câu SQL và gửi cho DBMS thì
DBMS mới biên dịch và thực hiện câu SQL. Trong
quá trình tạo câu SQL, phần mềm ứng dụng
thường sử dụng tham số do người dùng nhập vào.
Đây chính là đặc điểm mà hacker có thể lợi dụng,
tiến hành thay đổi câu SQL theo ý riêng của hacker.
9
10/23/2019
Lập trình an tồn
2.5. Chèn câu lệnh SQL (SQL Injection)
Ví dụ: Để quản lý người dùng, người lập trình tạo
một table Users(username, password, email).
Và thiết kế một form như sau (ví dụ dùng C# và
ADO.NET).
Lập trình an tồn
2.5. Chèn câu lệnh SQL (SQL Injection)
Nếu người dùng nhập vào user là admin và password
là abc thì câu SQL là:
SELECT * FROM Users WHERE Username=’admin’
AND Password=’abc’
Câu SQL này hoạt động bình thường theo đúng ý
người lập trình.
Tuy nhiên nếu hacker nhập vào user là admin’ -- và bỏ
trống password thì câu SQL trở thành:
SELECT * FROM Users WHERE Username=’admin’ --’
AND Password=’’
Lập trình an tồn
2.5. Chèn câu lệnh SQL (SQL Injection)
Code của nút Login:
private void btnLogin_Click(object sender, EventArgs e)
{
string sql = " SELECT * FROM Users " +
" WHERE Username = '" + txtUser.Text + "' AND " +
" Password = '" + txtPass.Text + "'";
SqlCommand cmd = new SqlCommand(sql, strConnect);
SqlDataReader dr = cmd.ExecuteReader();
if (dr.Read()){
// login ok
}
else{
// login failed
}
dr.Close();
}
Lập trình an tồn
2.5. Chèn câu lệnh SQL (SQL Injection)
Trong SQL Server dấu – nghĩa là chú thích. Như vậy
câu SQL trên cho ra kết quả là một record có
username là admin. Điều đó nghĩa là hacker đăng
nhập với quyền admin mà không cần biết password.
Ở đây dấu ’ và dấu -- mà hacker nhập vào đã làm thay
đổi cấu trúc câu SQL mà người lập trình khơng ngờ
tới.
Nếu hacker nhập user là ’; DELETE FROM Users -thì câu SQL trở thành:
SELECT * FROM Users WHERE Username=’’; DELETE
FROM Users --’ AND Password=’’
Bây giờ có hai câu SQL, câu thứ nhất truy xuất bảng
Users và câu thứ 2 xóa tồn bộ bản Users, chương
trình bị khóa khơng đăng nhập được.
10
10/23/2019
Lập trình an tồn
2.5. Chèn câu lệnh SQL (SQL Injection)
Để chống lại tấn công SQL Injection, chúng ta sử
dụng 2 cách:
Xử lý các ký tự đặt biệt như dấu „ trong dữ liệu
nhập trước khi tạo câu SQL
Sử dụng parameter để truyền tham số cho câu
SQL.
2.7. Tràn số
2.6. Ngăn chặn tràn stack
Lập trình an tồn
Dịng code đầu tiên để bảo vệ là chắc chắn
nhất tuy có vẻ ít cần thiết cho viết code an
tồn.
Ln phải kiểm tra các luồng dữ liệu đầu vào
của hàm; không truy cập các dữ liệu từ ngồi
của hàm mà khơng kiểm tra (ln xem các dữ
liệu ngồi là kẻ thù tấn cơng hàm).
Khi lập trình trong các ngơn ngữ Java, C#..., ta
sử dụng “safe” để trình biên dịch tự động kiểm
tra lỗi tràn stack.
Lập trình an tồn
Ví dụ: Giá trị số nguyên
int main(int argc, char *argv[])
{
unsigned char total;
total = strlen(argv[1])+strlen(argv[2])+1;
char *buff = (char *)malloc(total);
strcpy(buff, argv[1]);
strcat(buff, argv[2]);
printf("%s",buff);
return 0;
}
11
10/23/2019
Ví dụ: chuyển kiểu số nguyên
int main()
{
unsigned int l=0xffffffff;
char c = -1;
if (c == l)
{
printf("Why is -1 = 4,294,967,295???\n");
}
return 0;
}
1. Biểu diễn số nguyên
1. Biểu diễn số nguyên
Có 2 cách biểu diễn số nguyên: biểu diễn bù 1 và biểu diễn bù
Ví dụ:
2. Miền giá trị số nguyên
Có 2 cách biểu diễn số nguyên: biểu diễn bù 1 và biểu diễn bù
Ví dụ:
12
10/23/2019
Các vấn đề xãy ra lỗi
Integer Overflow
Khi giá trị số nguyên tăng lớn giá trị cận trên (nhỏ hơn cận
dưới) miền giá trị của kiểu số nguyên
Sign Errors
Xãy ra khi chuyển số nguyên từ số nguyên có dấu sang số
nguyên không dấu
Truncation Errors
Xãy ra khi chuyển số nguyên lớn sang số nguyên nhỏ hơn
(số byte biểu diễn)
Ví dụ: Ép kiểu (chuyển kiếu số
nguyên)
13
10/23/2019
Ví dụ: chuyển kiểu số nguyên
Chiến lược giãm lỗi, rũi ro
int main()
{
unsigned char tol=0xff;
char tt=tol;
printf("%d\n%d",tol,tt);
return 0;
}
LOGO
www.themegallery.com
Lập trình an tồn
Kiểm sốt tuy nhập
(Access Control)
Tài liệu tham khảo:
Secure Programming Cook , John Viega,Mtt Messier
Nội dung
Chương
Lập trình an tồn
3.1 Cơ chế kiểm soát truy nhập trên
Unix/Linux.
3.2 Cơ chế kiểm soát truy nhập trên
Windows.
3.3 Hạ thấp quyền truy nhập của tiến trình.
3.4 Xóa file an tồn
3.5 Hạn chế quyền truy nhập trên file
3.6 Khóa file
3.7 Tạo file tạm
3.8 Hạn chế truy nhập đến hệ thống file
14
10/23/2019
3.1. Cơ chế kiểm sốt truy nhập
Chương
trên Unix/ Linux
Lập trình an toàn
Trên Unix/Linux tất cả các tài nguyên đều được
coi là file: tập tin, ổ đĩa, bộ nhớ, thiết bị….
Mỗi file có sở hữu (owner): chủ sở hữu (user),
nhóm sở hữu (group) và một tập các quyền truy
nhập.
Có 3 mức quyền truy nhập file: mức chủ (User:
u), mức nhóm người dùng (Group: g), mức người
dung khác (Other/All:a).
Mỗi tiến trình có ba quyền: effective user id, real
user id, saved user id.
Có ba loại quyền truy cặp:
Đọc (read: r)
Ghi (write: w)
3.1. Cơ chế kiểm soát truy nhập
Chương
trên Unix/ Linux
Lập trình an tồn
Mỗi file cũng có thể có 3 bit đặc biệt:
Sticky: Nếu bit này được thiết lập, người dùng sẽ
khơng thể xóa hay đổi tên file của người khác nằm
trong thưc mục mà người dùng quản lý. Mặc định là
không được thiết lập.
Setuid: Bit này liên quan đến quá trình tạo một tiến
trình mới. Nếu bit này được thiết lập, tiến trình
được tạo từ file này sẽ khơng kế thừa quyền từ tiến
trình cha, mà sẽ có quyền từ user id của chính file
đó.
3.1. Cơ chế kiểm sốt truy nhập
Chương
trên Unix/ Linux
Lập trình an tồn
Thực thi (execute: x)
Mỗi file sẽ có ba nhóm quyền tương ứng với: user
id, group id, và other.
drwxr-xr-x
12 root root
4096
Oct 23
2000 LinuxVN.com
Khi tiến trình tạo một file hoặc tài nguyên, hệ thống
sẽ gán user id và group id cho file mới đó bằng
effective user id và effective group id của tiến trình.
Khi tiến trình truy nhập một file hoặc tài nguyên, hệ
thống sẽ lần lượt so sánh user id, group id của tiến
trình và file và chọn ra tập quyền tương ứng. Nếu
khơng khớp thì lớp quyền thứ 3 sẽ được sử dụng.
3.1. Cơ chế kiểm sốt truy nhập
Chương
trên Unix/ Linux
Lập trình an tồn
Setgid: Đối với file thực thi, nếu bit này được thiết
lập thì một tiến trình mới được tạo sẽ có quyền từ
groupd id của file đó chứ khơng kế thừa từ tiến
trình cha (tương tự Setuid).
Đối với thư mục, nếu bit này được thiết lập thì các
file tạo trong thư mục này sẽ có groupd id của thư
mục cha, chứ khơng kế thừa từ tiến trình tạo ra file
đó.
15
10/23/2019
3.2. Cơ chế kiểm sốt truy nhập
Chương
trên Windows
Lập trình an toàn
Windows sử dụng ACL: Access Control List để phân
quyền tài nguyên.
Các tài nguyên của Windows: file, registry, mutex, event,
IPC… được kiểm sốt thơng qua DACL và SACL.
DACL là danh sách các ACE, mỗi ACE là một luật quy
định một quyền hạn cụ thể.
DACL rỗng tương đương với việc tất cả mọi người có
tồn quyền truy nhập tới đối tượng.
Mỗi ACE bao gồm 3 thông tin:
SID: Đại diện cho một user hay một group trong hệ
thống
Quyền truy nhập
Giá trị boolean tương ứng với cho phép hay khơng cho
phép.
3.2. Cơ chế kiểm sốt truy nhập
Chương
trên Windows
Lập trình an tồn
Ví dụ ACE
DENY GENERIC_ALL Everyone: Cấm mọi
quyền với group Everyone
ALLOW GENERIC_WRITE Marketing: Cho phép
nhóm group Marketing được quyền ghi
Mỗi đối tượng đều có một Owner, chính là người
tạo ra đối tượng.
Owner có tồn quyền với đối tượng bất kể trong
DACL có cấm hay khơng.
Owner có thể bị chiếm bởi user khác.
3.2. Cơ chế kiểm sốt truy nhập
Chương
trên Windows
Lập trình an toàn
Các quyền truy nhập
TÊN
Diễn giải
DELETE
The ability to delete the object
READ_CONTROL
The ability to read the object's security descriptor,
not including its SACL
SYNCHRONIZE
The ability for a thread to wait for the object to be
put into the signaled state; not all objects support
this functionality
WRITE_DAC
The ability to modify the object's DACL
WRITE_OWNER
The ability to set the object's owner
GENERIC_READ
The ability to read from or query the object
GENERIC_ALL
Full control
GENERIC_WRITE
The ability to write to or modify the object
GENERIC_EXECUTE The ability to execute the object (applies primarily to files)
3.3. Hạ thấp quyền truy nhập của
Chương
tiến trình
Lập trình an tồn
Nếu một tiến trình có đặc quyền cao, thực hiện
các thao tác nguy hiểm => cần hạ thấp quyền
trước khi thực hiện.
Tiến trình có thể kiểm tra real user id, real group
id bằng lệnh getuid (), getgid(). Đây là các đặc
quyền kế thừa từ tiến trình cha.
Tiến trình có thể kiểm tra effective user id và
effective group id bằng lệnh geteuid() và
getegid(). Đây thường là user id có đặc quyền
cao hơn (do được khởi chạy từ super user, hoặc
các bit setuid được bật).
16
10/23/2019
3.3. Hạ thấp quyền truy nhập của
Chương
tiến trình
Lập trình an tồn
Tiến trình từ bỏ đặc quyền bằng việc thiết lập
group mới chính là real user id qua lệnh:
setgroups(): Thiết lập lại nhóm của tiến trình.
setegid(): Thiết lập lại effective group id của tiến
trình.
seteuid(): Thiết lập lại effective user id của tiến
trình.
3.4.
ChươngXóa file an tồn
Lập trình an toàn
Một vài mẫu được sử dụng
static unsigned char single_pats[16] = {0x00,
0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
static unsigned char triple_pats[6][3] = {{0x92,
0x49, 0x24}, {0x49, 0x24, 0x92}, {0x24, 0x92,
0x49}, {0x6d, 0xb6, 0xdb}, {0xb6, 0xdb, 0x6d},
{0xdb, 0x6d, 0xb6 }};
3.4.
Chương
Xóa file an tồn
Lập trình an tồn
Thơng thường, một file sau khi xóa sẽ được hệ
điều hành đánh dấu là xóa, nội dung chưa hoàn
toàn bị loại bỏ trên đĩa.
Giải pháp
Ghi đè thông tin khác nhiều lần lên đĩa.
Ghi đè dữ liệu ngẫu nhiên nhiều lần lên đĩa.
Ghi đè sử dụng mẫu định sẵn lên đĩa.
Sau mỗi chu kỳ ghi, sử dụng fsync để đồng bộ
với đĩa, vơ hiệu hóa cơ chế cache. Hoặc lệnh
fflush() nếu sử dụng thư viện C.
3.5. Hạn chế quyền truy nhập
Chương
trên file
Lập trình an tồn
Unix/Linux sử dụng umask cho mỗi tiến trình để vơ
hiệu hóa một vài bit khi tiến trình tạo file.
Hàm fopen, open luôn luôn tạo file với quyền 666.
Giả sử tiến trình muốn tạo file với quyền 666:
requested_permissions = 0666;
actual_permissions = requested_permissions &
~umask( );
Ứng dụng thay đổi umask bằng hàm umask() trước
khi thực hiện lời gọi tạo file.
#include <sys/types.h>
#include <sys/stat.h>
mode_t umask(mode_t
mask);
17
10/23/2019
Chương
3.6. Khóa file
Lập trình an tồn
Tiến trình muốn kiểm sốt truy nhập trên một phần
của file hay tồn bộ file để tránh xung đột khi có
nhiều tiến trình cùng truy nhập trên file.
Unix/Linux cung cấp cơ chế khóa mềm: Mọi tiến
trình đều có quyền giành được khóa và thao tác
trên file, tuy nhiên khơng phải tiến trình nào cũng
tuân thủ theo khóa và có thể phá hỏng dữ liệu của
tiến trình khác.
Windows thực hiện vấn đề này tốt hơn bằng khóa
cứng. Có hai loại khóa:
Chương
3.6. Khóa file
Lập trình an tồn
Shared Lock: Cho phép các tiến trình khác (kể cả
tiến trình giành được khóa) đọc nhưng khơng
được ghi vào một phần đã khóa của file.
Exclusive Lock : Cấm tất cả các tiến trình khác
khơng được đọc hay ghi vào phần đã khóa của
file. Tiến trình giành được khóa có quyền đọc
hoặc ghi vào file.
Các hàm khóa file trên Windows
LockFile, UnlockFile: Khóa và mở khóa đồng
bộ, sẽ khơng trở về đến khi giành được khóa
hoặc mở được khóa.
LockFileEx, UnlockFileEx: Khóa và mở khóa
đồng bộ hoặc bất đồng bộ.
Chương
3.6. Khóa file
Lập trình an tồn
Shared Lock: Cho phép các tiến trình khác (kể cả
tiến trình giành được khóa) đọc nhưng khơng
được ghi vào một phần đã khóa của file.
Exclusive Lock: Cấm tất cả các tiến trình khác
khơng được đọc hay ghi vào phần đã khóa của
file. Tiến trình giành được khóa có quyền đọc
hoặc ghi vào file.
Các hàm khóa file trên Windows
LockFile, UnlockFile: Khóa và mở khóa đồng bộ, sẽ
khơng trở về đến khi giành được khóa hoặc mở
được khóa.
LockFileEx, UnlockFileEx: Khóa và mở khóa đồng
bộ hoặc bất đồng bộ.
Chương
3.6. Khóa file
Lập trình an tồn
Khóa file cũng có thể xác định lúc tạo lập/truy
nhập file thơng qua hàm CreateFile.
Đoạn chương trình sau sẽ mở một file để đọc với
chế độ Shared Lock.
char
buff[1024];
DWORD bytesRead = 0;
HANDLE fileHandle = NULL;
fileHandle =
CreateFile(L"C:\\SecureProgramming\\Test.txt",
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE, 0,
OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
18
10/23/2019
Chương
3.6. Khóa file
Lập trình an tồn
ReadFile(fileHandle,buff,128,&bytesRead,0);
buff[bytesRead] = 0;
printf("File content:%s\n",buff);
LockFile(fileHandle,0,0,100,0); // Exclusive Lock
printf("File is locked, press any key to unlock...\n");
getch();
UnlockFile(fileHandle,0,0,100,0);
printf("File is unlocked\n");
getch();
CloseHandle(fileHandle);
3.7. Tạo file tạm
Chương
Lập trình an tồn
Sau khi tiến trình kết thúc một cách bình
thường/khơng bình thường, file tạm sẽ khơng thể
truy nhập được nữa.
Ví dụ
char szPath[] = “fileXXXXXX";
int fd;
fd = mkstemp(szPath);
unlink(szPath);
printf("Temperary file created, press any key to
continue...");
write(fd,"Hello",5);
close(fd);
3.7. Tạo file tạm
Chương
Lập trình an tồn
Ứng dụng tạo file tạm để lưu trữ thơng tin tạm thời
của chương trình.
File tạm nên được tạo lập một cách an toàn, và
xóa khi kết thúc chương trình.
Trên unix/linux:
Hàm mkstemp() có thể sử dụng để tạo file tạm với
tên ngẫu nhiên.
Ứng dụng cần xóa file theo tên, ngay sau lời gọi
mkstemp để đảm bảo khơng tiến trình nào truy
nhập được.
3.7. Tạo file tạm
Chương
Lập trình an tồn
Trên Windows:
Khơng có hàm tương đương mkstemp()
GetTempFileName() sinh tên file ngẫu nhiên
nhưng dễ đoán.
GetTempPath() lấy đường dẫn đến thư mục tạm
của người dùng hiện tại.
Tạo file bằng hàm CreateFile với hai thuộc tính
FILE_ATTRIBUTE_TEMPORARY và
FILE_FLAG_DELETE_ON_CLOSE
19
10/23/2019
3.7. Tạo file tạm
Chương
Lập trình an tồn
Ví dụ
HANDLE fileHandle = NULL;
fileHandle =
CreateFile(L"C:\\SecureProgramming\\Tmp.txt",
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE, 0,
OPEN_ALWAYS,FILE_ATTRIBUTE_TEMPORARY|
FILE_FLAG_DELETE_ON_CLOSE,0);
3.8. Hạn chế truy nhập đến hệ
Chương
thống file
3.8. Hạn chế truy nhập đến hệ
Chương
thống file
Lập trình an tồn
Trên Unix/Linux, ứng dụng có thể tự giới hạn phạm vi
truy nhập hệ thống tập tin của mình bằng lệnh
chroot()
Sau khi gọi chroot():
Tiến trình khơng thể mở rộng phạm vi truy nhập
bằng lệnh chroot lần nữa..
Tiến trình chỉ có thể thu hẹp hơn nữa phạm vi truy
nhập của mình.
Tiến trình phải chủ động gọi thêm chdir() để lệnh
chroot có hiệu lực.
Lập trình an tồn
VD:
#include <unistd.h>
chroot("/new/root/directory");
chdir("/");
20