Download as pdf or txt
Download as pdf or txt
You are on page 1of 7

Machine Translated by Google

Phòng thí nghiệm Giáo dục An ninh Máy tính 1

Phòng thí nghiệm khám phá khả năng Linux

Bản quyền c 2006 - 2011 Wenliang Du, Đại học Syracuse.


Việc xây dựng tài liệu này được/được tài trợ bởi ba khoản tài trợ từ Quỹ Khoa học Quốc gia Hoa Kỳ: Giải thưởng
Số 0231122 và 0618680 từ TUES/CCLI và Giải thưởng Số 1017771 từ Trustworthy Computing.
Quyền được cấp để sao chép, phân phối và/hoặc sửa đổi tài liệu này theo các điều khoản của Giấy phép Tài liệu
Tự do GNU, Phiên bản 1.2 hoặc bất kỳ phiên bản nào mới hơn do Tổ chức Phần mềm Tự do xuất bản. Bạn có thể tìm
thấy bản sao của giấy phép tại http://www.gnu.org/licenses/fdl.html.

1 Mô tả phòng thí nghiệm

Mục tiêu học tập của phòng thí nghiệm này là để sinh viên có được trải nghiệm trực tiếp về khả năng, đánh giá
cao lợi thế của các khả năng trong kiểm soát truy cập, nắm vững cách sử dụng khả năng để đạt được nguyên tắc
đặc quyền tối thiểu và phân tích thiết kế của kiểm soát truy cập dựa trên khả năng trong Linux. Phòng thí
nghiệm này dựa trên khả năng POSIX 1.e, được triển khai trong các phiên bản gần đây của nhân Linux.

2 thiết lập phòng thí nghiệm

Phòng thí nghiệm được phát triển dựa trên Ubuntu 11.04, sử dụng nhân Linux phiên bản 2.6.38. Một số tính năng
liên quan đến phòng thí nghiệm này không khả dụng trước phiên bản kernel 2.6.24.

2.1 Cài đặt Libcap

Có một số cách để các chương trình cấp người dùng tương tác với các tính năng khả năng trong Linux; cách thuận
tiện nhất là sử dụng thư viện libcap, hiện là thư viện chuẩn cho lập trình liên quan đến khả năng. Thư viện này
không đi kèm với một số bản phân phối Linux, vì vậy bạn cần tải xuống và cài đặt nó. Nếu bạn đã có tệp /usr/
include/sys/capability.h thì thư viện libcap đã được cài đặt sẵn. Nếu tệp tiêu đề không có ở đó, hãy cài đặt
thư viện bằng các lệnh sau:

# apt-get install wget # cd


dir_name (giả sử bạn muốn đặt thư viện libcap trong dir_name) # wget http://www.kernel.org/pub/linux/libs/
security/linux-privs/
libcap2/libcap-2.21.tar.gz # tar xvf
libcap-2.21.tar.gz # cd libcap-2.21 # tạo
(cái này sẽ biên dịch
libcap) # thực hiện cài đặt

Lưu ý: Nếu bạn đang sử dụng Máy ảo Ubuntu dựng sẵn của chúng tôi, thì libcap 2.21 đã được cài đặt sẵn.

Đối với bài lab này, bạn cần làm quen với các lệnh sau đi kèm với libcap:

• setcap: gán khả năng cho một tập tin.

• getcap: hiển thị các khả năng mà một tập tin mang theo.

• getpcaps: hiển thị các khả năng được thực hiện bởi một tiến trình.
Machine Translated by Google

Phòng thí nghiệm Giáo dục An ninh Máy tính 2

2.2 Đặt SELinux ở Chế độ cho phép

Ubuntu 11.04 không đi kèm với SELinux. Bỏ qua phần này nếu Linux của bạn không có SELinux.

Tuy nhiên, các phiên bản gần đây của Fedora đi kèm với SELinux. Thật không may, SELinux sẽ cản đường chúng ta, ngăn cản

chúng ta thực hiện một số hoạt động trong phòng thí nghiệm này. Chúng tôi cần đặt SELinux ở chế độ cho phép cho phòng thí
nghiệm này.

Để tạm thời đặt SELinux ở chế độ cho phép, hãy đặt 'setenforce 0' với quyền root. Để đặt mỗi chế độ bỏ lỡ làm chế độ

khởi động, bạn cần sửa đổi /etc/selinux/config bằng cách thay đổi dòng 'SELINUX=enforcing' thành 'SELINUX=permissive'. Lưu

ý: không tắt SELinux (chỉ tạm thời đặt nó ở chế độ cho phép), nếu không, khi bạn bật SELinux lần sau, HĐH sẽ mất thời gian

để gán lại hệ thống tệp cho bối cảnh SELinux trong thời gian khởi động.

3 nhiệm vụ phòng thí nghiệm

Trong một hệ thống khả năng, khi một chương trình được thực thi, quy trình tương ứng của nó được khởi tạo với một danh sách

các khả năng (mã thông báo). Khi quy trình cố gắng truy cập một đối tượng, hệ điều hành sẽ kiểm tra các khả năng của quy

trình và quyết định có cấp quyền truy cập hay không.

3.1 Nhiệm vụ 1: Trải nghiệm khả năng

Trong các hệ điều hành, có nhiều hoạt động đặc quyền chỉ có thể được thực hiện bởi người dùng đặc quyền.

Ví dụ về các hoạt động đặc quyền bao gồm định cấu hình thẻ giao diện mạng, sao lưu tất cả các tệp người dùng, tắt máy tính,

v.v. Nếu không có khả năng, các hoạt động này chỉ có thể được thực hiện bởi những người siêu thẩm quyền, những người thường

có nhiều đặc quyền hơn mức cần thiết cho nhiệm vụ dự định. Do đó, việc cho phép siêu người dùng thực hiện các hoạt động đặc

quyền này là vi phạm Nguyên tắc đặc quyền tối thiểu.

Hoạt động đặc quyền là rất cần thiết trong hệ điều hành. Tất cả các chương trình Set-UID liên quan đến các hoạt động

riêng tư mà người dùng bình thường không thể thực hiện được. Để cho phép người dùng bình thường chạy các chương trình này,

các chương trình Set-UID biến người dùng bình thường thành người dùng có quyền (ví dụ: root) tạm thời, mặc dù các hoạt động

đặc quyền liên quan không cần tất cả quyền. Điều này rất nguy hiểm: nếu chương trình bị xâm phạm, kẻ thù có thể lấy được

quyền root.

Các khả năng phân chia đặc quyền gốc mạnh mẽ thành một tập hợp các đặc quyền ít mạnh mẽ hơn. Mỗi đặc quyền này được gọi

là một khả năng. Với các khả năng, chúng tôi không cần phải là siêu người dùng để thực hiện các hoạt động đặc quyền. Tất cả

những gì chúng ta cần là có các khả năng cần thiết cho các hoạt động đặc quyền. Do đó, ngay cả khi một chương trình đặc

quyền bị xâm phạm, đối thủ chỉ có thể nhận được quyền hạn hạn chế. Bằng cách này, rủi ro của chương trình đặc quyền có thể

giảm đáng kể.

Các khả năng đã được triển khai trong Linux từ khá lâu, nhưng chúng chỉ có thể được gán cho các quy trình. Kể từ phiên

bản kernel 2.6.24, các khả năng có thể được gán cho các tệp (tức là chương trình) và biến các chương trình đó thành các

chương trình đặc quyền. Khi một chương trình đặc quyền được thực thi, tiến trình đang chạy sẽ mang những khả năng được gán

cho chương trình đó. Theo một nghĩa nào đó, điều này tương tự như các tệp Set-UID, nhưng điểm khác biệt chính là số lượng

đặc quyền được mang theo bởi các quy trình đang chạy.

Chúng tôi sẽ sử dụng một ví dụ để chỉ ra cách sử dụng các khả năng để loại bỏ nguồn điện không cần thiết được gán cho

một số chương trình đặc quyền. Đầu tiên, chúng ta hãy đăng nhập như một người dùng bình thường và chạy lệnh sau:

% ping www.google.com

Chương trình sẽ chạy thành công. Nếu bạn nhìn vào thuộc tính tệp của chương trình /bin/ping, bạn sẽ phát hiện ra rằng

ping thực sự là một chương trình Set-UID với chủ sở hữu là root, tức là khi bạn thực thi ping, id người dùng hiệu quả của

bạn sẽ trở thành root và quá trình chạy là rất mạnh mẽ. Nếu có
Machine Translated by Google

Phòng thí nghiệm Giáo dục An ninh Máy tính 3

lỗ hổng trong ping, toàn bộ hệ thống có thể bị xâm phạm. Câu hỏi đặt ra là liệu chúng ta có thể xóa các đặc quyền này khỏi

ping hay không.

Hãy biến /bin/ping thành một chương trình không phải Set-UID. Điều này có thể được thực hiện thông qua lệnh sau (bạn

cần đăng nhập với quyền root):

# chmod us /bin/ping

Lưu ý: Các tệp nhị phân như ping có thể định vị ở những nơi khác nhau trong bản phân phối Linux khác nhau, hãy sử dụng

' which ping ' để định vị chương trình ping của bạn.

Bây giờ, hãy chạy 'ping www.google.com' và xem điều gì sẽ xảy ra. Thật thú vị, lệnh sẽ không hoạt động. Điều này là

do ping cần mở ổ cắm RAW, đây là một hoạt động đặc quyền chỉ có thể được thực hiện bởi root (trước khi các khả năng được

triển khai). Đó là lý do tại sao ping phải là một chương trình Set-UID.

Với khả năng, chúng ta không cần cung cấp quá nhiều năng lượng cho ping. Chúng ta hãy chỉ gán khả năng cap net raw cho

ping và xem điều gì sẽ xảy ra:

$ su root #

setcap cap_net_raw=ep /bin/ping # su normal_user $ ping

www.google.com

Câu hỏi 1: Hãy biến các chương trình Set-UID sau thành các chương trình non-Set-UID mà không làm ảnh hưởng đến hoạt động

của các chương trình này.

• /usr/bin/passwd

Câu hỏi 2: Bạn đã thấy những gì chúng tôi có thể làm với khả năng cap net thô. Chúng tôi muốn bạn làm quen với một số khả

năng khác. Đối với mỗi khả năng sau, hãy làm như sau: (1) giải thích mục đích của khả năng này; (2) tìm một chương trình

để chứng minh tác dụng của những khả năng này (bạn có thể chạy ứng dụng có và không có khả năng đó, đồng thời giải thích

sự khác biệt trong kết quả). Bạn cũng có thể viết các ứng dụng của riêng mình nếu muốn, miễn là chúng có thể chứng minh

tác dụng của khả năng. Đây là danh sách các khả năng mà bạn cần phải làm việc (đọc bao gồm/linux/capability.h để tìm hiểu

về các khả năng).

• cap dac read search

• cap dac ghi đè

• mũ lưỡi trai

• cài đặt giới hạn

• nắp giết

• giới hạn ròng thô


Machine Translated by Google

Phòng thí nghiệm Giáo dục An ninh Máy tính 4

3.2 Nhiệm vụ 2: Điều chỉnh Đặc quyền

So với kiểm soát truy cập bằng ACL (Danh sách kiểm soát truy cập), các khả năng có một ưu điểm khác: khá thuận tiện để điều

chỉnh động số lượng đặc quyền mà một quy trình có, điều này rất cần thiết để đạt được nguyên tắc đặc quyền tối thiểu. Ví

dụ: khi một đặc quyền không còn cần thiết trong một quy trình, chúng ta nên cho phép quy trình loại bỏ vĩnh viễn các khả

năng liên quan đến đặc quyền này. Do đó, ngay cả khi quy trình bị xâm phạm, kẻ tấn công sẽ không thể có được các khả năng

đã bị xóa này. Điều chỉnh đặc quyền có thể đạt được bằng cách sử dụng các hoạt động quản lý khả năng sau đây.

1. Xóa: Một quy trình có thể xóa vĩnh viễn một khả năng.

2. Vô hiệu hóa: Một quy trình có thể tạm thời vô hiệu hóa một khả năng. Không giống như xóa, vô hiệu hóa chỉ là nhịp độ

hiếm có; quá trình sau đó có thể kích hoạt nó.

3. Kích hoạt: Một quy trình có thể kích hoạt một khả năng tạm thời bị vô hiệu hóa. Một khả năng bị xóa không thể
được kích hoạt.

Nếu không có khả năng, chương trình Set-UID đặc quyền cũng có thể xóa/tắt/bật đặc quyền của chính nó.

Điều này được thực hiện thông qua lệnh gọi hệ thống setuid() và seteuid(); cụ thể là, một quy trình có thể thay đổi id

người dùng hiệu quả của nó trong thời gian chạy. Mức độ chi tiết khá thô khi sử dụng các cuộc gọi hệ thống này, bởi vì bạn

có thể là người dùng có đặc quyền (ví dụ: root) hoặc người dùng không có đặc quyền. Với các khả năng, các đặc quyền có thể

được điều chỉnh theo cách tốt hơn nhiều, bởi vì mỗi khả năng có thể được điều chỉnh độc lập.

Để hỗ trợ điều chỉnh khả năng động, Linux sử dụng một cơ chế tương tự như cơ chế Set-UID, tức là, một quy trình mang

ba bộ khả năng: được phép (P), có thể kế thừa (I) và hiệu quả (E). Bộ được phép bao gồm các khả năng mà quy trình được phép

sử dụng; tuy nhiên, bộ khả năng này có thể không hoạt động. Tập hợp hiệu quả bao gồm những khả năng mà quy trình hiện có

thể sử dụng (điều này giống như uid người dùng hiệu quả trong cơ chế Set-UID). Tập hợp hiệu quả phải luôn là tập hợp con

của tập hợp được phép. Quá trình có thể thay đổi nội dung của tập hợp hiệu quả bất cứ lúc nào miễn là tập hợp hiệu quả

không vượt quá tập hợp cho phép. Tập kế thừa chỉ được sử dụng để tính toán các tập khả năng mới sau exec(), nghĩa là các

khả năng nào có thể được kế thừa bởi các tiến trình con.

Khi một tiến trình rẽ nhánh, các bộ khả năng của đứa trẻ được sao chép từ cha mẹ. Khi một tiến trình thực hiện một

chương trình mới, các bộ khả năng mới của nó được tính theo công thức sau:

pI_new = pI pP_new

= fP | (fI & pI) pE_new = pP_new nếu

fE = true pE_new = rỗng


nếu fE = sai

Giá trị kết thúc bằng “new” cho biết giá trị mới được tính toán. Giá trị bắt đầu bằng ap biểu thị khả năng xử lý. Giá

trị bắt đầu bằng f cho biết khả năng của tệp.

Để thuận tiện cho các chương trình tắt/bật/xóa khả năng của chúng, vui lòng thêm ba chức năng sau vào /home/seed/temp/

libcap-2.21/libcap/cap proc.c (libcap-2.21 là thư mục được tạo khi bạn chạy 'tar xvf libcap-2.21.tar.gz' để trích xuất tuổi

gói libcap).

int cap_disable(cap_value_t capflag) {

cap_t mycaps;

mycaps = cap_get_proc(); nếu (mycaps


== NULL)
Machine Translated by Google

Phòng thí nghiệm Giáo dục An ninh Máy tính 5

trả về -1; if
(cap_set_flag(mycaps, CAP_EFFECTIVE, 1, &capflag, CAP_CLEAR) != 0) trả về -1; if (cap_set_proc(mycaps) !=
0) return -1;
trả về 0;

int cap_enable(cap_value_t capflag) {

cap_t mycaps;

mycaps = cap_get_proc(); nếu (mycaps


== NULL)
trả về -1;
nếu (cap_set_flag(mycaps, CAP_EFFECTIVE, 1, &capflag, CAP_SET) != 0)
trả về -1; if
(cap_set_proc(mycaps) != 0) return -1;

trả về 0;
}

int cap_drop(cap_value_t capflag) {

cap_t mycaps;

mycaps = cap_get_proc(); nếu (mycaps


== NULL)
trả về -1; if
(cap_set_flag(mycaps, CAP_EFFECTIVE, 1, &capflag, CAP_CLEAR) != 0) trả về -1; if (cap_set_flag(mycaps,
CAP_PERMITTED,
1, &capflag, CAP_CLEAR) != 0) trả về -1; if (cap_set_proc(mycaps) != 0) return -1; trả về 0;

Chạy các lệnh sau để biên dịch và cài đặt libcap đã cập nhật. Sau khi thư viện được cài đặt,
các chương trình có thể sử dụng ba chức năng thư viện mà chúng tôi vừa thêm vào.

# cd libcap_directory # make #
make

install (Bạn cần root để chạy cài đặt)

Câu 3: Biên dịch chương trình sau và gán khả năng tìm kiếm đọc cap dac cho tệp thực thi. Đăng nhập như một người
dùng bình thường và chạy chương trình. Mô tả và giải thích những quan sát của bạn.

/* use_cap.c */
#include <fcntl.h>

#include <sys/types.h> #include


<errno.h>
#include <stdlib.h>
#include <stdio.h>
Machine Translated by Google

Phòng thí nghiệm Giáo dục An ninh Máy tính 6

#include <linux/capability.h> #include <sys/


capability.h> int main(void) {

nếu (mở ("/etc/shadow", O_RDONLY) < 0)


printf("(a) Mở không thành công\n");
/* Câu hỏi (a): mở như trên có thành công không? Tại sao? */

nếu (cap_disable(CAP_DAC_READ_SEARCH) < 0) trả về -1;

nếu (mở ("/etc/shadow", O_RDONLY) < 0)


printf("(b) Mở không thành công\n");
/* Câu hỏi (b): mở như trên có thành công không? Tại sao? */

nếu (cap_enable(CAP_DAC_READ_SEARCH) < 0) trả về -1;

nếu (mở ("/etc/shadow", O_RDONLY) < 0)


printf("(c) Mở không thành công\n");
/* Câu hỏi (c): mở trên có thành công không? Tại sao?*/

nếu (cap_drop(CAP_DAC_READ_SEARCH) < 0) trả về -1;

nếu (mở ("/etc/shadow", O_RDONLY) < 0)


printf("(d) Mở không thành công\n");
/* Câu hỏi (d): mở như trên có thành công không? Tại sao?*/

nếu (cap_enable(CAP_DAC_READ_SEARCH) == 0) trả về -1;

nếu (mở ("/etc/shadow", O_RDONLY) < 0)


printf("(e) Mở không thành công\n");
/* Câu hỏi (e): mở như trên có thành công không? Tại sao?*/
}

Chương trình có thể được biên dịch bằng lệnh sau (lưu ý trong lệnh thứ hai, ký tự thứ hai trong ”-lcap” là ell,

không phải một; nó có nghĩa là liên kết thư viện libcap):

$ gcc -c use_cap.c $ gcc -o

use_cap use_cap.o -lcap

Sau khi hoàn thành nhiệm vụ trên, hãy trả lời các câu hỏi sau:

• Câu hỏi 4: Nếu muốn tự động điều chỉnh số lượng đặc quyền trong kiểm soát truy cập dựa trên ACL, chúng ta phải

làm gì? So với các khả năng, điều khiển truy cập nào thuận tiện hơn để làm như vậy?

• Câu hỏi 5: Sau khi một chương trình (đang chạy với tư cách người dùng bình thường) vô hiệu hóa khả năng A, nó sẽ

bị tấn công tràn bộ đệm. Kẻ tấn công đã tiêm thành công mã độc hại của mình vào không gian ngăn xếp của chương

trình này và bắt đầu chạy nó. Kẻ tấn công này có thể sử dụng khả năng A không? Điều gì sẽ xảy ra nếu quá trình

xóa khả năng, kẻ tấn công có thể sử dụng khả năng đó không?

• Câu hỏi 6: Tương tự như câu hỏi trước, ngoại trừ việc thay thế cuộc tấn công tràn bộ đệm bằng cuộc tấn công điều

kiện chủng tộc. Cụ thể, nếu kẻ tấn công khai thác điều kiện cạnh tranh trong chương trình này, anh ta có thể sử

dụng khả năng A nếu khả năng này bị vô hiệu hóa không? Nếu khả năng bị xóa thì sao?
Machine Translated by Google

Phòng thí nghiệm Giáo dục An ninh Máy tính 7

4 đệ trình

Bạn cần gửi báo cáo phòng thí nghiệm chi tiết để mô tả những gì bạn đã làm và những gì bạn đã quan sát được; bạn cũng

cần đưa ra lời giải thích cho những quan sát thú vị hoặc đáng ngạc nhiên. Trong báo cáo của mình, bạn cần trả lời tất

cả các câu hỏi được liệt kê trong phòng thí nghiệm này.

You might also like